流式捕捉:ClickHouse的开箱即用CDC解决方案

ClickHouse生态圈 ProxySQL 是基于 MySQL 的一款开源的中间件的产品,是一个灵活的 MySQL 代理层,可以实现读写分离,支持 Query 路由功能,支持动态指定某个 SQL 进行缓存,支持动态加载(无需重启 ProxySQL 服务),故障切换和一些 SQL 的过滤功能。DBH是万山数据研发的一款数据集成工具,能够实现多源异构数据之间灵活、快速、无侵入式的数据集成与转化,数据源通过DBH可以一键映射到clickhouse中,转化成对应的数据表和统一的操作视图,通过统一的SQL界面供分析工具或者应用系统使用。 阅读详情

图片

本文字数:13714;估计阅读时间:35 分钟

作者:Streamkap

审校:庄晓东(魏庄)

本文在公众号【ClickHouseInc】首发

介绍

今天,欢迎来自我们的技术合作伙伴Streamkap的客座文章,Streamkap是一种针对ClickHouse开箱即用的变更数据捕捉(CDC-change data capture)解决方案。这篇博客深入探讨了构建这样一个产品的细节和挑战。对于那些只想要一个开箱即用CDC解决方案的ClickHouse用户,我们很高兴向你推荐Streamkap这个托管服务。

我们很高兴地宣布:新的ClickHouse连接器,可以从诸如PostgreSQL、MySQL、SQL Server、Oracle和MongoDB等数据库中流式传输CDC数据到ClickHouse。

Streamkap最近切换到使用ClickHouse来实时处理所有日志和指标,因为我们发现其他解决方案无法实现我们所需的查询性能。在采用ClickHouse之后,我们希望开始提供一个ClickHouse CDC集成,但发现现有的连接器存在问题,因此我们着手构建了一个新的连接器来解决这些问题。

在这篇文章中,我们假设您熟悉ClickHouse数据库和Change Data Capture(CDC)的概念,但如果不熟悉,您可以通过阅读有关流式变更数据捕捉的文章来了解更多。

我们将深入探讨为ClickHouse构建CDC解决方案的挑战,以及我们如何解决这些问题,讨论我们如何处理模式演变、数据一致性和快照。最后,我们将展示如何在保持性能的流式流程的同时实现所有需求。

技术

ClickHouse是一个开源的列式数据库。列导向结构意味着数据是按列而不是按行存储和检索的。ClickHouse已经成为构建实时应用程序的首选,因为它能够摄取大量数据,并且在写入时,而不是在读取时将数据物化。这导致查询速度显着加快,使ClickHouse适用于支撑实时应用程序。

Streamkap是一个无服务器流式传输平台,可以实现:实时的变更数据捕捉(CDC),并传入ClickHouse。在底层,诸如Kafka、Debezium、Flink之类的技术与生产级连接器/管道相结合。

下面是Streamkap从数据库流式传输到ClickHouse的概述。

图片

挑战

当我们首次尝试将CDC数据流式传输到ClickHouse时,我们寻找了可以使用的现有连接器。在考察了官方的ClickHouse Kafka Connect连接器,以及市场上的其他连接器后,我们很快意识到:我们需要对其进行大量修改,才能支持不同的用例。意识到这些连接器需要进行大量修改,我们开始构建自己的解决方案。以下是我们需要确保:在将解决方案带入生产之前需要解决的一些关键需求。

数据类型

现有解决方案对数据类型的支持不太好:

  • 嵌套结构

  • 嵌套数组,包含嵌套结构的数组

  • 具有微秒精度的时间戳

  • 具有微秒精度的时间

  • 不包含时间信息的日期(自历元以来的天数)

  • 将JSON传输为普通字符串字段

元数据

在处理CDC数据时,添加额外的元数据列(如时间戳和CDC记录类型)很有帮助。这样可以使后续处理转换更简单、更强大,同时还能诊断延迟问题。

插入/更新

在Streamkap中,我们看到一半的客户希望使用插入或更新。插入是追加模式,因此保持所有更改的历史记录,而更新则仅显示最终数据(插入+更新)。虽然大多数公司在批量ETL中习惯了这种能力,但当与流式ETL结合使用时,这是一个新概念。了解更多关于批处理与实时处理的信息

模式(Schema)演变

当源表发生变化时,我们需要更新目标表以处理这种模式漂移,以避免导致管道中断。

半结构化数据

像MongoDB/Elasticsearch这样的源允许复杂的嵌套记录结构中存在不一致性,需要在插入到ClickHouse之前由摄取管道进行调和。例如:

  • 日期/时间在某些记录中表示为数字(自纪元以来的秒/毫秒)而在其他记录中表示为字符串(ISO格式)

  • 在某些记录中,嵌套字段是字符串,而在其他记录中是更复杂的嵌套结构

  • 深度嵌套的复杂半结构化数据通常需要在插入到ClickHouse之前进行预处理,将其映射到适当的类型,例如元组、嵌套。

我们的方法

现在让我们深入研究我们的连接器,以及如何解决这些挑战。

数据类型

我们发现默认方法通常是将数据插入到ClickHouse中,然后在加载后转换数据。

我们内置支持以下数据类型:

Kafka Connect Data TypeClickHouse Data type
INT8Int8
INT16Int16
INT32Int32
INT64Int64
FLOAT32Float32
FLOAT64Float64
BOOLEANBool
BYTESBLOB (String)
STRINGString
org.apache.kafka.connect.data.DecimalDECIMAL(38, 0)
org.apache.kafka.connect.data.Timestampio.debezium.time.ZonedTimestampDateTime64
org.apache.kafka.connect.data.DateDate
io.debezium.data.JsonString
STRUCTTuple
ARRAYArray

JSON字段当前作为字符串进行摄取,allow_experimental_object_type=1的使用目前正在测试中。

元数据

连接器为每个插入到ClickHouse表中的插入添加了额外的关键列,以便在加载后进行更好的分析和建模,以及支持更新。

以下元数据列被添加到每个ClickHouse表中:

  • _streamkap_ts_ms:CDC事件时间戳

  • _streamkap_deleted:如果当前的CDC事件是一个删除事件

  • _streamkap_partition:表示内部Streamkap分区编号,通过对源记录的键字段应用一致性哈希获取

  • _streamkap_source_ts_ms:变更事件在源数据库中发生的时间戳

  • _streamkap_op:CDC事件操作类型(c insert, u update, d delete, r snapshot, t truncate)

插入/更新

Streamkap连接器支持两种将数据摄入到ClickHouse的模式:插入(追加)和更新。

更新模式是我们连接器的默认模式,当需要ClickHouse表包含源数据的最新版本时使用。

插入(追加)模式

插入模式导致每个变更都被跟踪,并作为新行插入到ClickHouse中,而删除事件将在ClickHouse中标记为已删除,使用元值_streamkap_deleted。

这在处理较大的数据量时很有用,可以保持延迟较低,并保持更改的历史记录。

例如,Streamkap在收集我们的指标时使用插入模式,因为只有不可变数据被插入。

然后,我们在指标表上使用Materialized Views创建了许多聚合,以进行时间序列分析。对这个表设置一个合适的TTL,以便ClickHouse为我们处理删除操作,同时提供足够的历史数据来调查任何问题,或者如果我们必须出于某种原因重建Materialized Views。

要使用插入(追加)模式,使用ClickHouse引擎MergeTree。

图片

更新模式

更新是插入和更新的组合。如果行的主键有匹配,值将被覆盖。相反,如果没有匹配,事件将被插入。

更新模式使用ClickHouse的ReplacingMergeTree引擎实现。

ReplacingMergeTree引擎根据排序键在周期性的后台合并中去重数据,允许清理旧记录。这个过程的异步性意味着可能会有一个小窗口,留下了视图中的旧记录。因此,查询必须使用FINAL修饰符来确保返回数据的最新版本,然后在查询时对任何剩余的相同记录进行去重。

带有基本类型的更新示例

这里以JSON格式显示了一个用于更新的输入记录。键只有一个字段,id,这是将对行进行去重的主键:

{
    "id": "123456hYCcEM62894000000000",
    "str_col": "some-str-values-000000000",
    "IntColumn": 123000,
    "Int8": 0,
    "InT16": 10,
    "bool_col": true,
    "double_col": 1.7976931348623157E308,
    "json_col": "{\"a\": 0}",
    "__deleted": false,
    "created_at": 1707379532748,
    "date_col": 19761,
    "ts_tz": "2023-10-24T15:19:51Z",
    "_streamkap_ts_ms": 1707379532748,
    "binary_col": "AQIDBAU=",
    "byte_buf": "AQIDBAU=",
    "bigint_col": "E4f/////0tCeAA=="
}

结果表:

SHOW CREATE TABLE streamkap_test_nominal_upsert
FORMAT Vertical

Query id: 1abf2898-69b3-4785-a849-65c3879493bb

Row 1:
──────
statement: CREATE TABLE streamkap.streamkap_test_nominal_upsert
(
    `id` String COMMENT 'id',
    `str_col` String COMMENT 'str_col',
    `IntColumn` Int32 COMMENT 'IntColumn',
    `Int8` Int8 COMMENT 'Int8',
    `InT16` Int16 COMMENT 'InT16',
    `bool_col` Bool COMMENT 'bool_col',
    `double_col` Float64 COMMENT 'double_col',
    `json_col` String COMMENT 'json_col',
    `__deleted` Bool COMMENT '__deleted',
    `created_at` DateTime64(3) COMMENT 'created_at',
    `date_col` Date COMMENT 'date_col',
    `ts_tz` DateTime64(3) COMMENT 'ts_tz',
    `_streamkap_ts_ms` Int64 COMMENT '_streamkap_ts_ms',
    `binary_col` String COMMENT 'binary_col',
    `byte_buf` String COMMENT 'byte_buf',
    `bigint_col` Decimal(38, 0) COMMENT 'bigint_col',
    `_streamkap_partition` Int32 COMMENT '_streamkap_partition',
    `_streamkap_deleted` UInt8 MATERIALIZED if(__deleted = true, 1, 0)
)
ENGINE = ReplicatedReplacingMergeTree('/clickhouse/tables/{uuid}/{shard}', '{replica}', _streamkap_ts_ms, _streamkap_deleted)
PARTITION BY _streamkap_partition
PRIMARY KEY id
ORDER BY id
SETTINGS index_granularity = 8192

示例数据:

SELECT *
FROM streamkap_test_nominal_upsert
FORMAT Vertical

Row 1:
──────
id:                   123456hYCcEM62894000000000
str_col:              some-str-values-000000000
IntColumn:            123000
Int8:                 0
InT16:                10
bool_col:             true
double_col:           1.7976931348623157e308
json_col:             {"a": 0}
__deleted:            false
created_at:           2024-02-08 08:03:37.368
date_col:             2024-02-08
ts_tz:                2023-10-24 15:19:51.000
_streamkap_ts_ms:     1707379417368
binary_col:
byte_buf:
bigint_col:           92233720368547000000000
_streamkap_partition: 0

Row 2:
──────
id:                   123456hYCcEM62894000000000
str_col:              some-str-values-000000000
IntColumn:            123000
Int8:                 0
InT16:                10
bool_col:             true
double_col:           1.7976931348623157e308
json_col:             {"a": 0}
__deleted:            false
created_at:           2024-02-08 08:03:41.608
date_col:             2024-02-08
ts_tz:                2023-10-24 15:19:51.000
_streamkap_ts_ms:     1707379421608
binary_col:           java.nio.HeapByteBuffer[pos=0 lim=5 cap=5]
byte_buf:             java.nio.HeapByteBuffer[pos=0 lim=5 cap=5]
bigint_col:           92233720368547000000000
_streamkap_partition: 0

去重数据,使用FINAL:

SELECT *
FROM streamkap_test_nominal_upsert
FINAL
FORMAT Vertical

Row 1:
──────
id:                   123456hYCcEM62894000000000
str_col:              some-str-values-000000000
IntColumn:            123000
Int8:                 0
InT16:                10
bool_col:             true
double_col:           1.7976931348623157e308
json_col:             {"a": 0}
__deleted:            false
created_at:           2024-02-08 08:03:41.608
date_col:             2024-02-08
ts_tz:                2023-10-24 15:19:51.000
_streamkap_ts_ms:     1707379421608
binary_col:           java.nio.HeapByteBuffer[pos=0 lim=5 cap=5]
byte_buf:             java.nio.HeapByteBuffer[pos=0 lim=5 cap=5]
bigint_col:           92233720368547000000000
_streamkap_partition: 0

处理半结构化数据

嵌套数组和结构体

下面,我们提供了一些如何将复杂结构自动映射到ClickHouse类型的示例。

为了支持包含结构的数组,我们需要修改Streamkap在ClickHouse中的角色,将flatten_nested设置为0:

ALTER ROLE STREAMKAP_ROLE SETTINGS flatten_nested = 0;

包含子数组的嵌套结构字段

这里以JSON格式显示了一个输入记录,键只有一个字段id:

{
  "id": 1,
  "obj": {
    "nb": 123,
    "str": "abc",
    "sub_arr": [
      {
        "sub_nb": 789,
        "sub_str": "mnp"
      }
    ]  
  }
}

结果表。注意obj列已经被映射到一个Tuple(nb Int32, str String, sub_arr Array(Tuple(n Int32, s String)), sub_arr_str Array(String))来处理复杂的结构:

SHOW CREATE TABLE chdb.streamkap_nested_struct_with_array

CREATE TABLE chdb.streamkap_nested_struct_with_array
(
    `obj` Tuple(nb Int32, str String, sub_arr Array(Tuple(n Int32, s String)), sub_arr_str Array(String)) COMMENT 'obj',
    `__deleted` Bool COMMENT '__deleted',
    `_streamkap_ts_ms` Int64 COMMENT '_streamkap_ts_ms',
    `_streamkap_partition` Int32 COMMENT '_streamkap_partition',
    `id` Int32 COMMENT 'id',
    `_streamkap_deleted` UInt8 MATERIALIZED if(__deleted = true, 1, 0)
)
ENGINE = ReplacingMergeTree(_streamkap_ts_ms, _streamkap_deleted)
PARTITION BY _streamkap_partition
PRIMARY KEY id
ORDER BY id
SETTINGS index_granularity = 8192 

示例数据:

SELECT *
FROM chdb.streamkap_nested_struct_with_array
LIMIT 1 format Vertical

obj:                               (123,'abc',[(789,'mnp')],['efg']) 
__deleted:                         false     
_streamkap_ts_ms:                  1702519029407 
_streamkap_partition:              0 
id:                                1 

包含子结构的嵌套数组字段

这里以JSON格式显示了一个输入记录,键只有一个字段id:

{
    "id": 1,
    "arr": [
        {
            "nb": 123,
            "str": "abc"
        }
    ]
}
SHOW CREATE TABLE streamkap_nested_array_of_struct

CREATE TABLE streamkap.streamkap_nested_array_of_struct
(
    `arr` Array(Tuple(nb Int32, str String)) COMMENT 'arr',
    `__deleted` Bool COMMENT '__deleted',
    `_streamkap_ts_ms` Int64 COMMENT '_streamkap_ts_ms',
    `_streamkap_partition` Int32 COMMENT '_streamkap_partition',
    `id` Int32 COMMENT 'id',
    `_streamkap_deleted` UInt8 MATERIALIZED if(__deleted = true, 1, 0)
)
ENGINE = ReplacingMergeTree( _streamkap_ts_ms, _streamkap_deleted)
PARTITION BY _streamkap_partition
PRIMARY KEY id
ORDER BY id
SETTINGS index_granularity = 8192

示例数据:

SELECT *
FROM streamkap_nested_array_of_struct
LIMIT 1 format Vertical

arr:                            [(123,'abc')]
__deleted:                      false
_streamkap_ts_ms:               1702529856885
_streamkap_partition:           0
id:                             1

快照

快照是指将现有数据从数据库加载到ClickHouse的过程。

我们有两种方法可以加载这些历史数据。

阻塞快照

阻塞快照的目的是捕获数据库表的整个当前状态,并将使用大型的select语句来实现。这些也可以并发运行,速度非常快。从效率上讲,阻塞快照可能会对系统资源产生较大的影响,特别是对于大型表,每个查询可能需要更长的时间。

增量快照

增量快照旨在提高效率,对系统资源的影响通常较小,并且特别适用于非常大的表格或希望同时进行快照和流式传输的情况。

数据一致性和交付保证

交付保证主要是指在出现故障场景时,未确认的CDC事件可能被重播,导致重复的行插入到ClickHouse中。

Streamkap为ClickHouse提供至少一次交付保证。

使用插入摄入模式,可能会将一些重复的行插入到ClickHouse中。然而,通过在materialized view中添加去重代码,不会有任何影响。

如前所述,对于更新摄入模式,我们通过源记录键进行去重。强制使用一次性交付保证会增加性能开销,而没有额外的好处,因为相同的进程处理重复的CDC事件,将所有CDC事件合并为一个记录的最终记录状态。

变换

Streamkap支持管道中的变换,因此数据可以在发送到ClickHouse之前进行预处理。

这对于半结构化数据、预处理和清理任务特别有用。这可能比在摄入后处理数据效率更高。

在清理过的结构化数据上进行实时分析自然是在ClickHouse中完成的,查询性能受益于将数据转换移到插入时间。

下面,我们介绍了Streamkap执行的一些常见转换。

修复半结构化数据中的不一致性

考虑修复一个不一致的半结构化日期字段:

"someDateField": {"$date": "2023-08-04T09:12:20.29Z"}
"someDateField": "2023-08-07T08:14:57.817325+00:00"
"someDateField": {"$date": {"$numberLong": 1702853448000}}

使用Streamkap转换,所有记录都可以转换为用于摄入到Clickhouse DateTime64列的公共格式:

"someDateField": "yyyy-MM-dd HH:mm:ss.SSS"

拆分大型半结构化JSON文档

对于文档数据库,子实体可以被建模为嵌套在父实体文档内部的子数组:

{
    "key": "abc1234",
    "array": [
        {
            "id": "11111",
            "someField": "aa-11"
        },
        {
            "id": "22222",
            "someField": "bb-22"
        }
    ]
}

在ClickHouse中,将这些子实体表示为单独的行是有意义的。使用Streamkap转换,子实体记录可以拆分为单独的记录:

{
    "id": "11111",
    "parentKey": "abc1234",
    "someField": "aa-11"
}

{
    "id": "22222",
    "parentKey": "abc1234",
    "someField": "bb-22"
}

模式演变

模式演变或漂移处理是对目标表进行更改以反映上游更改的过程。

Streamkap连接器会自动处理以下情况的模式漂移。

  • 额外列:检测到一个额外的字段,并且将创建一个新的列来接收新的数据。

  • 删除列:此列现在将被忽略,并且不会采取进一步的操作。

  • 更改列类型:在表中创建一个附加列,使用后缀表示新类型。例如。ColumnName_type

可以在任何阶段向管道中添加附加表。我们在下面展示了一些此模式演变的示例。

添加列

在模式演变之前考虑以下输入记录:

{
    "id": "123456hYCcEM62894000000000",
    "str_col": "some-str-values-000000000",
    "IntColumn": 123000,
    "Int8": 0,
    "InT16": 10,
    "bool_col": true,
    "double_col": 1.7976931348623157E308,
    "json_col": "{\"a\": 0}",
    "binary_col": "AQIDBAU=",
    "byte_buf": "AQIDBAU=",
    "bigint_col": "E4f/////0tCeAA==",
    "__deleted": false,
    "created_at": 1702894985613,
    "ts_tz": "2023-10-24T15:19:51Z",
    "_streamkap_ts_ms": 1702894985613
}

一个新的列new_double_col被添加到上游模式中。这导致ClickHouse模式演变:

{
    "id": "123456hYCcEM62894xxx",
    "str_col": "some-str-values-000000000",
    "IntColumn": 123000,
    "Int8": 0,
    "InT16": 10,
    "bool_col": true,
    "double_col": 1.7976931348623157E308,
    "json_col": "{\"a\": 0}",
    "binary_col": "AQIDBAU=",
    "byte_buf": "AQIDBAU=",
    "bigint_col": "E4f/////0tCeAA==",
    "__deleted": false,
    "created_at": 1702894985613,
    "ts_tz": "2023-10-24T15:19:51Z",
    "_streamkap_ts_ms": 1702894985613,
    "new_double_col": 1.7976931348623157E308
}

ClickHouse数据:

SELECT
    id,
    new_double_col
FROM streamkap_test_nominal_add_new_column
ORDER BY _streamkap_ts_ms ASC

┌─id─────────────────────────┬─new_double_col─┐
│ 123456hYCcEM62894000000000 │              0 │
└────────────────────────────┴────────────────┘
┌─id───────────────────┬─────────new_double_col─┐
│ 123456hYCcEM62894xxx │ 1.7976931348623157e308 │
└──────────────────────┴────────────────────────┘

将Int演变为String

模式演变之前的输入记录:

{
    "id": "123456hYCcEM62894000000000",
. . . 
    "IntColumn": 123000,
. . . 
    "_streamkap_ts_ms": 1702894492041
}

模式演变后摄入的新记录:

{
    "id": "123456hYCcEM62894xxx",
. . .
    "IntColumn": "new-str-value",
. . .
}

ClickHouse数据,在IntColumn_str已添加的情况下:

SELECT
    id,
    IntColumn,
    IntColumn_str
FROM streamkap_test_nominal_evolve_int2string
ORDER BY _streamkap_ts_ms ASC


┌─id─────────────────────────┬─IntColumn─┬─IntColumn_str─┐
│ 123456hYCcEM62894000000000 │    123000 │               │
└────────────────────────────┴───────────┴───────────────┘
┌─id───────────────────┬─IntColumn─┬─IntColumn_str─┐
│ 123456hYCcEM62894xxx │         0 │ new-str-value │
└──────────────────────┴───────────┴───────────────┘

性能

以下15分钟的负载测试旨在展示与延迟相关的各种批量大小的性能特征。此外,我们将评估Streamkap ClickHouse目的地连接器的可伸缩性。

ClickHouse Cloud实例详细信息:每个32GiB的3个节点,每个节点有8个vCPU

输入记录格式包含基本类型,一个中等字符串约100个字符和一个大字符串约1000个字符:


select * from streamkap_test_nominal_perf limit 1 format Vertical;

id:                   123456hYCcEM62894000000001
str_col:              some-str-values-000000001
IntColumn:            123001
Int8:                 1
InT16:                10
bool_col:             true
double_col:           1.7976931348623157e308
json_col:             {"a": 1}
__deleted:            false
created_at:           1970-01-01 00:00:19.751
ts_tz:                2023-10-24 15:19:51.000
_streamkap_ts_ms:     1706539233685
binary_col:           java.nio.HeapByteBuffer[pos=0 lim=5 cap=5]
byte_buf:             java.nio.HeapByteBuffer[pos=0 lim=5 cap=5]
bigint_col:           92233720368547000000001
medium_str:           str-medium-000000001x000000001x000000001x000000001x000000001x000000001x000000001x000000001x000000001x000000001x000000001
large_str:            str-large-000000001x000000001x000000001x000000001x000000001x000000001x000000001x000000001x000000001x000000001x000000001x000000001x000000001x000000001x000000001x000000001x000000001x000000001x000000001x000000001x000000001x000000001x000000001x000000001x000000001x000000001x000000001x000000001x000000001x000000001x000000001x000000001x000000001x000000001x000000001x000000001x000000001x000000001x000000001x000000001x000000001x000000001x000000001x000000001x000000001x000000001x000000001x000000001x000000001x000000001x000000001x000000001x000000001x000000001x000000001x000000001x000000001x000000001x000000001x000000001x000000001x000000001x000000001x000000001x000000001x000000001x000000001x000000001x000000001x000000001x000000001x000000001x000000001x000000001x000000001x000000001x000000001x000000001x000000001x000000001x000000001x000000001x000000001x000000001x000000001x000000001x000000001x000000001x000000001x000000001x000000001x000000001x000000001x000000001x000000001x000000001x000000001x000000001x000000001x000000001x000000001
_streamkap_partition: 0

当前测试中将摄入模式设置为“upsert”。使用“append”时,吞吐量会稍微更好,因为不需要一些内存中的去重逻辑。

基线单个分区

单个Streamkap任务和Clickhouse分区的基线测试,具有多个批量大小。

吞吐量:

图片

每个批量大小的延迟:

图片

通常,用于回填的原始吞吐量是必需的,而延迟则不是一个关注点。在这种情况下,超过100k行的较大批量大小更合适。

通常,流式更改的吞吐量要求较低,并且可能希望延迟较小。在这种情况下,较小的批量大小更合适。

这些是使用固定批量大小的人工测试,以说明吞吐量和延迟之间的权衡。在实践中,批量大小随内部队列大小而变化。如果有许多记录在队列中等待,批量大小将增长,因此,吞吐量将增加。

可伸缩性

以相同的批量大小进行测试:每个批量大小100,000条记录,并逐渐增加任务的数量:1、2、4和8。我们可以看到,吞吐量与任务数量呈近似线性关系。

图片

总结

这只是我们与ClickHouse合作的开始,在接下来的几周里,我们将继续构建尽可能处理变更数据捕获事件及其以上的最佳集成。

以下是我们希望获得反馈的一些领域,以确定社区是否会投票支持这些领域:

  • 使用allow_experimental_object_type=1

  • 自动创建的材料化视图,基于模板

  • 跨多个表的流式ACID事务

  • 单记录转换

  • 多记录转换(分割、连接、聚合)

  • 确保一次性

希望这个连接器能够使您更轻松地享受ClickHouse的优势,就像我们一样。

Streamkap和ClickHouse都提供免费试用;您可以在Streamkap.com和ClickHouse.com上注册。

图片

​​联系我们

手机号:13910395701

邮箱:Tracy.Wang@clickhouse.com

满足您所有的在线分析列式数据库管理需求

信创 CDC 实战 | TiDB 实时入仓难点与解决方案解析(以 ClickHouse 为例) 本文介绍如何构建稳定、高兼容性的 TiDB → ClickHouse 实时同步链路,支持信创场景下的日志级数据采集、结构变更感知与秒级延迟入仓,助力国产数据库高效落地。 阅读详情

相关推荐

数据对接方案设计:从ETL到CDC,打通企业数据孤岛的实战指南

数据对接是企业数据治理与数据中台建设的核心基础环节,旨在解决不同系统间的数据流通与整合问题。其核心原理是通过抽取、转换、加载等过程,将异构数据源的数据进行标准化处理并同步至目标系统。这项技术的价值在于打破数据孤岛,实现数据资产统一,为数据分析、业务协同和实时决策提供高质量的数据基础。在应用场景上,无论是传统的T+1报表、数据仓库构建,还是实时数仓、用户画像更新和系统间状态同步,都依赖于高效可靠的数据对接方案。本文聚焦于数据对接的实战设计,深入剖析了包括ETL、实时CDC在内的主流技术路径,并针对数据同步延迟

weixin_30924239的博客 354

flink-cdc,clickhouse写入,多路输出

高级:入clickhouse的同时推送到kafka供2次数据流程处理。kafka日志数据从kafka读取。2、判断日志内容级别:多路输出。1、关联字典表:完善日志数据。低级:入clickhouse。

javaMylife的博客 2520

大数据领域实时分析:开启数据洞察新时代

大数据领域的“实时分析”,本质是对“流动中的数据”进行低延迟(毫秒/秒级)的处理,输出即时结果。模式数据类型处理延迟典型场景价值定位离线分析历史静态数据T+1/T+7月度销售报表、用户画像总结规律、回溯问题近实时分析准实时数据分钟级小时级流量统计、监控报警快速响应、初步预警实时分析流式动态数据毫秒/秒级实时推荐、反欺诈、IoT监控即时决策、阻断风险举个例子:如果某电商要统计“双11当天的销售额”,离线分析(T+1)能给你“11月12日的总销售额”;

小白菜的博客 586

数据变更捕获 (CDC):PostgreSQL 与 ClickHouse - 第一部分

本文字数:13442;估计阅读时间:34 分钟审校:庄晓东(魏庄)本文在公众号【ClickHouseInc】首发。

ClickHouseDB的博客 2235

数据仓库核心表型全解:全量、增量、拉链、流水与快照表的设计与选型

在数据仓库与大数据领域,表结构设计是业务逻辑沉淀与技术实现的基石。其核心原理在于根据数据的变化特性和业务查询需求,选择不同的数据存储与组织模型,以实现存储成本、计算效率与历史追溯能力之间的最佳平衡。从技术价值看,合理的表型设计能直接提升数据处理的性能、保障数据质量,并支撑复杂的时态分析与业务复盘。常见的应用场景包括用户行为分析、交易流水记录、维度状态追踪以及关键业务里程碑存档等。本文将聚焦于数据仓库中最核心的五种表模型:全量表、增量表、拉链表、流水表和快照表。其中,拉链表通过记录每条数据的生效与失效时间,完

aizexi2652的博客 314

【信息科学与工程学】【数据科学】数据科学领域-第十一篇 数据集成算法01

​​降低维护成本​​:通过抽象通用流程(如),当需要修改故障注入逻辑(如更换混沌工具)时,只需修改一处代码,无需修改所有测试用例;​​提升扩展性​​:通过参数化故障场景(如),可快速生成新的故障用例(如针对新服务的延迟故障),适应系统迭代需求;​​增强场景真实性​​:通过组合混沌操作(如),模拟真实生产环境中的复杂故障链(如“网络延迟+服务宕机”),更准确地验证系统韧性;​​提高分析效率​​:通过自动化结果分析(如),快速获取MTTR、错误率等关键指标,减少人工分析时间。

weixin_49199313的博客 953

十分钟掌握 Flink CDC,实现Mysql数据增量备份到Clickhouse [纯干货,建议收藏]

挖了很久的CDC坑,今天打算填一填了。本文我们首先来介绍什么是CDC,以及CDC工具选型,接下来我们来介绍如何通过Flink CDC抓取mysql中的数据,并把他汇入Clickhouse里,最后我们还将介绍Flink SQL CDC的方式。 CDC 首先什么是CDC ?它是Change Data Capture的缩写,即变更数据捕捉的简称,使用CDC我们可以从数据库中获取已提交的更改并将这些更改发送到下游,供下游使用。这些变更可以包括INSERT,DELETE,UPDATE等操作。 ...

麒思妙想 1万+

【信息科学与工程学】【数据中心】第二十四篇 数据中心DaaS场景及算法

Flink, Kafka Streams, 时序数据库。Flink, Kafka Streams, 流处理引擎。Presto, ClickHouse, 查询加速引擎。Presto, ClickHouse, 查询加速引擎。延迟<50ms,可用性>99.99%,QPS>10K。REST API, GraphQL, API网关。Tableau, Power BI, 自助BI。Tableau, Power BI, 可视化库。Spark, Hadoop, 分布式计算框架。Spark, Hadoop, 分布式计算。

weixin_49199313的博客 1058

Flink CDC实现数据增量备份到ClickHouse实战

点击上方蓝色字体,选择“设为星标”回复"面试"获取更多惊喜八股文教给我,你们专心刷题和面试Hi,我是王知无,一个大数据领域的原创作者。放心关注我,获取更多行业的一手消息。本文我们首先来介...

微信搜:import_bigdata,大数据领域硬核原创作者 3584

构建企业级数据神经中枢:流批一体架构与智能监控实践

在数据驱动的业务决策中,实时计算与历史数据分析是两大核心技术支柱。实时计算通过流式处理引擎(如Apache Flink)实现低延迟的数据处理,满足即时监控与告警需求;而历史回溯则依赖批处理框架(如Apache Spark)与数据湖技术,支撑复杂的关联分析与趋势挖掘。流批一体架构通过统一存储与计算逻辑,有效解决了数据一致性、开发效率与资源成本等工程难题,其技术价值在于打通从数据采集到决策应用的全链路。在应用场景上,该架构广泛应用于业务健康度监控、KPI自动化追踪、运营异常检测与趋势预测等领域。本文以综合性业务

weixin_28694169的博客 300

块式读取与流式读取对比demo

块式读取与流式读取对比,欢迎大家前来交流。 相比于传统的流读取,要快很多。

如何利用 Flink CDC 实现数据增量备份到 Clickhouse

挖了很久的CDC坑,今天打算填一填了。本文我们首先来介绍什么是CDC,以及CDC工具选型,接下来我们来介绍如何通过Flink CDC抓取mysql中的数据,并把他汇入Clickhouse里...

微信搜:import_bigdata,大数据领域硬核原创作者 1610

QCM6490平台DDR测试:从QDUTT配置到眼图分析的实战指南

本文详细介绍了QCM6490平台DDR测试的全流程,从QDUTT工具安装配置到眼图分析,提供了实战操作指南和常见问题解决方案。通过具体案例分享,帮助工程师掌握DDR测试技巧,确保内存稳定性,特别适用于物联网和边缘计算设备的开发调试。

weixin_33910191的博客 456

flinkcdc同步mongo数据到clickhouse

通过flink-mongo-cdc同步数据到clickhouse

catcher92的博客 2767

添加odbc数据源时的一些问题和解决办法

pl/sql

Mr_Syh的博客 9642

别再被无限debugger卡住了!Chrome DevTools实战绕过技巧(含Hook与文件替换)

本文详细介绍了如何通过Chrome DevTools绕过无限debugger封锁的实战技巧,包括Hook技术与文件替换方法。针对常见的定时器轰炸、循环陷阱和动态注入等反调试手段,提供了高效的解决方案,帮助开发者快速突破调试障碍,提升爬虫和逆向工程效率。

weixin_30326515的博客 241

【使用 flink-cdc 将数据从 mysql 同时同步到 redis, elastisearch, clickhouse】

首先,需要在 Flink 中配置 CDC 数据源,使其能够连接到 MySQL 并捕获变化的数据。然后,将捕获的数据流通过 Flink Table API 转换为流表,然后使用表 API 的 sink() 函数将数据流发送到 Redis、Elasticsearch 和 Clickhouse 中。要从 MySQL 同时同步到 Redis、Elasticsearch 和 Clickhouse,可以使用 Flink CDC 和 Flink Table API 来实现。

npk191954的专栏 2151

R语言实战:从Raw Counts到TPM/FPKM的完整转换指南(含代码调试技巧)

本文详细介绍了在R语言环境中将RNA-seq原始计数(raw counts)转换为TPM/FPKM值的完整流程,包含代码实现和常见错误调试技巧。通过具体案例演示如何正确处理基因长度和测序深度因素,实现表达量标准化,为生物信息学分析提供可靠数据基础。特别适合需要进行转录组数据分析的研究人员和实验室技术人员参考。

weixin_28559803的博客 477

【flink cdc】flink读mysql写clickhouse

1. 使用flink cdc 读mysql 写clickhouse 2. clickhouse使用CollapsingMergeTree sign 1 is a “state” row, -1 is a “cancel” row. 3. 解决时间差8个小时问题

jomplte博客 1240

STM32H7 FMC驱动TFT-LCD原理与实战

TFT-LCD并行接口驱动是嵌入式人机交互的基础技术,其核心在于将显示控制器抽象为存储器映射设备,依托硬件时序控制器实现低开销、高确定性刷新。FMC(Flexible Memory Controller)作为STM32H7系列的关键外设,通过地址/数据总线复用、可配置读写时序及Bank分区机制,支持将ILI9341、ST7789等主流LCD控制器挂载为‘慢速异步存储器’,从而替代GPIO模拟8080时序或LTDC+DMA2D方案。该技术显著降低CPU占用率,提升帧率稳定性,适用于工业HMI、实时仪表盘等对响

weixin_32306683的博客 547

OV5640调试大坑,关于binning、RES分辨率与EV曝光

OV5640在使用binning模式时,必须考虑使用场景,分辨率下降叠加动态范围压缩,会使目标对象细节在高光环境下大量丢失,2x2的binning模式,分辨率会远低于感光面积的1/4。

chongyun_的专栏 1824

用flink cdc sqlserver 将数据实时同步到clickhouse

flink cdc 终于支持 sqlserver 了。 现在互联网公司用sqlserver的不多,大部分都是一些国企的老旧系统。我们以前同步数据,都是用datax,但是不能实时同步数据。现在有了flinkcdc,可以实现实时同步了。 1、首先sqlserver版本:要求sqlserver版本为14及以上,也就是SQL Server 2017 版。 2、sqlserver开启cdc,具体细节可以百度,有一点要注意,必须启动SQL Server 代理服务。 3、需要实现一个json解析方法,用于将同

cardinalzbk的专栏 8430

virtualbox虚拟机里面最顶部没有控制、设置和帮助等选项

无意中操作,导致virtualbox虚拟机里面最顶部没有控制,设置和帮助选项  virtualbox虚拟机窗口显示如下如: 如何设置,窗口显示如下图所示呢: virtualbox虚拟机窗口模式显示设置,切换可以通过如下图所示操作进行切换: PS:一定要是右边的Ctrl+C

WEL测试 8780

MySQL FlinkCDC 通过Kafka实时同步到ClickHouse(自定义Debezium格式支持增加删除修改)

把MySQL多库多表的数据通过FlinkCDC DataStream的方式实时同步到同一个Kafka的Topic中,然后下游再写Flink SQL拆分把数据写入到ClickHouse,FlinkCDC DataStream通过自定义Debezium格式的序列化器,除了增加,还能进行删除修改。关于Debezium格式的更多信息,参考Flink官网,网址如下。MySQL FlinkCDC 通过Kafka实时同步到ClickHouse(自定义Debezium格式支持增加删除修改)自定义Debezium序列化器。

qq_42575907的博客 2671

SAP 集成泛微 OA Open API 新建流程申请接口

《SAP ERP 与泛微 OA 的系统集成》系列文章。泛微 Open API 是基于 HTTPS 的 Restful 接口,上篇文章,我已经完成了调用业务接口之前的准备工作,这篇文章我以新建流程申请这个系统集成最重要的接口为例,讲解接口设计、泛微 API 调用的过程、遇到的问题、解决的办法。

SAP李斌,本人承诺所有原创文章均不使用任何AI生成技术,请大家放心阅读。 3555

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

数据变更捕获 (CDC):PostgreSQL 与 ClickHouse - 第二部分

我们在之前的博客中提出的端到端架构如下所示。该架构假设用户已经拥有一个运行Kafka Connect框架的Kafka实例。在我们的示例中,我们假设用户正在使用Confluent Cloud来托管Kafka,该服务会自动为事件创建相应的主题。不过,用户也可以选择自行托管Kafka。我们提出的架构将适用于任何能够写入由Debezium生成的事件的摄取管道。

ClickHouseDB的博客 1618

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

上一篇: 加速您的ClickHouse查询
下一篇: ClickHouse Grafana插件4.0版 - 升级SQL可观测性
ClickHouseDB
博客等级 码龄3年 1707粉丝 320原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值