简述

CloudCanal 近期实现了 MySQL(RDS) 到 ClickHouse 实时同步的能力,功能包含全量数据迁移、增量数据迁移、结构迁移能力,以及附带的监控、告警、HA等能力(平台自带)。

ClickHouse 本身并不直接支持 Update 和 Delete 能力,但是他自带的 MergeTree 系列表中 CollapsingMergeTreeVersionedCollapsingMergeTree 可变相实现实时增量的目的,并且性能完全够用,能够比较轻松达到 1k RPS 以上的能力。

接下来的文章,简要介绍 CloudCanal 是如何实现这个能力,以及作为用户我们怎么比较好的使用这个能力。

技术点

结构迁移

CloudCanal 默认提供结构迁移,默认选择 CollapsingMergeTree 作为表引擎,并增加一个默认字段 __cc_ck_sign,源主键作为 sortKey,如下示例:

  1. CREATE TABLE console.worker_stats
  2. (
  3. `id` Int64,
  4. `gmt_create` DateTime,
  5. `worker_id` Int64,
  6. `cpu_stat` String,
  7. `mem_stat` String,
  8. `disk_stat` String,
  9. `__cc_ck_sign` Int8 DEFAULT 1
  10. )
  11. ENGINE = CollapsingMergeTree(__cc_ck_sign)
  12. ORDER BY id
  13. SETTINGS index_granularity = 8192

ClickHouse 表引擎中,CollapsingMergeTree 和 VersionedCollapsingMergeTree 都能通过标记位按规则折叠数据,从而达到更新和删除的效果。VersionedCollapsingMergeTree 相比 CollapsingMergeTree 优势在于同一条数据的不同变更可以乱序写入,但是 CloudCanal 选择 CollapsingMergeTree 主要原因在于2点

    1. CloudCanal 中同一条记录必定是按源库变更顺序写入,不存在乱序情况
    1. 不需要维护 VersionedCollapsingMergeTree 中的 Version 字段(版本,也可以起其他名字)

所以 CloudCanal 选择了 CollapsingMergeTree 作为默认表引擎。

写数据

CloudCanal 写数据主要包含全量和增量两种,即单次搬迁存量数据和长期同步,两者写入略有不同。全量写入对端主要工作是批量和多线程,因为 CloudCanal 结构迁移默认设置了标记位字段 __cc_ck_sign default 值为 1, 所以就不需要做特殊处理。

对于增量, CloudCanal 则需要做 3 件事情。

  • 转换 Update、Delete 操作为 Insert

    这一步有两件事情要做,第一件是按照操作类型,填充标记字段值,其中 Insert 和 Update 为 1 ,Delete 为 -1 ,第二件是将对应增量数据的前镜像或者后镜像填充到结果记录中,以便后续 insert 写入。
  1. for (CanalRowChange rowChange : rowChanges) {
  2. switch (rowChange.getEventType()) {
  3. case INSERT: {
  4. for (CanalRowData rowData : rowChange.getRowDatasList()) {
  5. rowData.getAfterColumnsList().add(nonDeleteCol);
  6. records.add(rowData.getAfterColumnsList());
  7. }
  8. break;
  9. }
  10. case UPDATE: {
  11. for (CanalRowData rowData : rowChange.getRowDatasList()) {
  12. rowData.getBeforeColumnsList().add(deleteCol);
  13. records.add(rowData.getBeforeColumnsList());
  14. rowData.getAfterColumnsList().add(nonDeleteCol);
  15. records.add(rowData.getAfterColumnsList());
  16. }
  17. break;
  18. }
  19. case DELETE: {
  20. for (CanalRowData rowData : rowChange.getRowDatasList()) {
  21. rowData.getBeforeColumnsList().add(deleteCol);
  22. records.add(rowData.getBeforeColumnsList());
  23. }
  24. break;
  25. }
  26. default:
  27. throw new CanalException("not supported event type,eventType:" + rowChange.getEventType());
  28. }
  29. }
  • 按表归组

    因为 IUD 操作已全部转换为 Insert, 且为全镜像(所有字段都填充了值),所以可以按表归组,然后批量写入。即使单线程也能满足大部分场景的同步性能要求。
  1. protected Map<TableUnit, List<CanalRowChange>> groupByTable(IncrementMessage message) {
  2. Map<TableUnit, List<CanalRowChange>> data = new HashMap<>();
  3. for (ParsedEntry entry : message.getEntries()) {
  4. if (entry.getEntryType() == CanalEntryType.ROWDATA) {
  5. CanalRowChange rowChange = entry.getRowChange();
  6. if (!rowChange.isDdl()) {
  7. List<CanalRowChange> changes = data.computeIfAbsent(new TableUnit(entry.getHeader().getSchemaName(), entry.getHeader().getTableName()), k -> new ArrayList<>());
  8. changes.add(rowChange);
  9. }
  10. }
  11. }
  12. return data;
  13. }
  • 并行写入

    将按表归组的数据使用并行执行框架执行,具体不详述。

举个"栗子"

  • 添加数据源

  • 创建任务,选择数据源和库,并连接成功,点击下一步

  • 选择数据同步,建议规格至少选择 1 GB.目前 MySQL->ClickHouse 结构迁移自动过滤,所以选择无效。点击下一步

  • 选择表,默认 ClickHouse 上创建 CollapsingMergeTree 表引擎,并自动添加 __cc_ck_sign 折叠标记字段。点击下一步

  • 选择字段,点击下一步

  • 创建任务

  • 等待任务自动结构迁移、全量迁移、数据同步追上

  • 造点 Insert、Update、Delete 负载

  • 延迟追平状态,停止负载

  • 检查源端 MySQL 表数据,以其中一张表为例

  • 检查对端 ClickHouse 表数据,不一致?!!

  • 手动优化下表,数据一致。虽然可以等待 ClickHouse 自动优化,但是如果需要直接得到准确结果,可手动优化(注意:手动优化可能导致数据库机器压力过大)

常见问题

我在ClickHouse上已经创建了表怎么办?

目前比较建议直接使用 CloudCanal 自动结构迁移的方式来创建任务。

如果已建表为 CollapsingMergeTree 表引擎,请将标记位字段改成 __cc_ck_sign Int8 DEFAULT 1`,再创建任务(此时就不再自动结构迁移,而是使用已存在表)。

如果为其他表引擎,暂时不支持(主要是不支持增量能力,需要 CloudCanal 进一步探索)。

同步过去的数据什么时候合并?

当 CloudCanal 同步数据到 ClickHouse 时,ClickHouse 并不会实时合并数据,也没有一致性可言,所以一般情况是等待合并,或者直接手动合并(造成机器高负载、高IO),optimize table worker_stats FINAL

DDL 怎么做?

目前 CloudCanal 还未支持到 ClickHouse 的 DDL 同步,产品实现上,目前是忽略的。所以如果做 DDL ,加字段建议对端先加,再加源端,减字段反之。

总结

本文简要介绍了 CloudCanal 实现 MySQL(RDS) 到 ClickHouse 数据迁移同步的能力,具备一站式、数据实时特点,从技术点、例子、以及常见问题角度展开。文章如有错误,烦请大家勘误,后续也欢迎大家试用,提供宝贵的意见和建议。

CloudCanal-免费好用的企业级数据同步工具,欢迎品鉴。

了解产品可以查看官方网站: http://www.clougence.com

CloudCanal社区:https://www.askcug.com/

MySQL到ClickHouse实时同步-CloudCanal实战的更多相关文章

  1. 实时同步sersync实战

    目录 实时同步sersync实战 什么是实时同步 sersync和rsync+inotify对比 sersync项目实战 安装rsync的服务端(backup) NFS服务端部署sersync 实时同 ...

  2. logstash-input-jdbc实现mysql 与elasticsearch实时同步(ES与关系型数据库同步)

    引言: elasticsearch 的出现使得我们的存储.检索数据更快捷.方便.但很多情况下,我们的需求是:现在的数据存储在mysql.oracle等关系型传统数据库中,如何尽量不改变原有数据库表结构 ...

  3. 几篇关于MySQL数据同步到Elasticsearch的文章---第五篇:logstash-input-jdbc实现mysql 与elasticsearch实时同步深入详解

    文章转载自: https://blog.csdn.net/laoyang360/article/details/51747266 引言: elasticsearch 的出现使得我们的存储.检索数据更快 ...

  4. 生产环境实践:Cana实现MySQL到ES实时同步

    注:由于文章篇幅有限,完整文档可扫下面二维码免费获取,更有深受好评的大数据实战精英+架构师好课等着你. 速点链接加入高手战队:http://www.dajiangtai.com/course/112. ...

  5. mysql 与elasticsearch实时同步常用插件及优缺点对比(ES与关系型数据库同步)

    前言: 目前mysql与elasticsearch常用的同步机制大多是基于插件实现的,常用的插件包括:elasticsearch-jdbc, elasticsearch-river-MySQL , g ...

  6. 将linux上的网站代码托管到gogs git服务器上进行实时同步(实战)

    一.说明 本说明只针对php,其他语言需要编译请用别的架构实现 二.实现效果 本地开发员门提交推送代码到git服务器,会立即同步更新网站服务器上代码 三.实战步骤小节 首次托管请先看   https: ...

  7. Mysql 到 Hbase 数据如何实时同步,强大的 Streamsets 告诉你

    很多情况大数据集群需要获取业务数据,用于分析.通常有两种方式: 业务直接或间接写入的方式 业务的关系型数据库同步到大数据集群的方式 第一种可以是在业务中编写代码,将觉得需要发送的数据发送到消息队列,最 ...

  8. mysql数据实时同步到Elasticsearch

    业务需要把mysql的数据实时同步到ES,实现低延迟的检索到ES中的数据或者进行其它数据分析处理.本文给出以同步mysql binlog的方式实时同步数据到ES的思路, 实践并验证该方式的可行性,以供 ...

  9. rsync nfs 实时同步,结合实战

    目录 rsync nfs 实时同步,实战 一.部署rsync服务端(backup) 二.部署rsync客户端(nfs,web01) 三.部署web代码(web01) 四.NFS服务端部署(nfs) 五 ...

随机推荐

  1. 黄衫女子,黄衫好.png

    正想着团队项目中数据该如何解析,就收到了来自软工课程组的一件小黄衫,真是意外之喜.详问其来源,竟是因结对项目做的"较好"而来,顿感受之有愧. 结对项目是两人对文件系统的一个小模拟, ...

  2. [敏杰开发]Beta阶段测试报告

    [敏杰开发]Beta阶段测试报告 这是一篇软工课程博客 项目 内容 课程:北航-2020-春-软件工程 博客园班级博客 作业要求 Beta阶段测试报告 我们在这个课程的目标是 测试项目 这个作业在哪个 ...

  3. 【转载】一次「Too many open files」故障

    一次「Too many open files」故障 发表于2015-08-02 昨天,项目的 ElasticSearch 服务挂了,我说的挂可不是进程没了,因为有 Supervisor 保护,而是服务 ...

  4. Ansible_常用文件模块使用详解

    一.Ansibel常用文件模块使用详解 1.file模块 1️⃣:file模块常用的参数列表: path       被管理文件的路径 state状态常用参数: absent           删除 ...

  5. 基于多IP地址Web服务

    [Centos7.4版本] !!!测试环境我们首关闭防火墙和selinux [root@localhost ~]# systemctl stop firewalld [root@localhost ~ ...

  6. shell基础之for循环语句

    For语句 格式:for name [ [ in [ word ... ] ] ; ] do list ; done for 变量名 in 取值列表; do 命令 done 或者 for 变量名 in ...

  7. S8 Linux磁盘与文件系统管理命令

    8.1 fdisk:磁盘分区工具 8.2-3 partprobe.tune2fs 8.4 parted:磁盘分区工具 8.5-7 mkfs.dumpe2fs.resize2fs 8.8-9 fsck. ...

  8. 8.4 parted:磁盘分区工具

    parted     对于小于2TB的磁盘可以用fdisk和parted命令进行分区,这种情况一般采用flisk命令,但对于大于2TB的磁盘则只能用parted分区,且需要将磁盘转换为GPT格式. p ...

  9. [leetcode] 38. 报数(Java)(字符串处理)

    38. 报数 水题 class Solution { public String next(String num) { String ans = ""; int i = 0; wh ...

  10. Go语言协程并发---互斥锁sync.Mutex

    package main import ( "fmt" "sync" "time" ) /* mt.Lock() 抢锁 一次只能被一个协程锁 ...