写点什么

MySQL 数据实时同步到 Elasticsearch 的技术方案选型和思考

2021 年 3 月 23 日

MySQL 数据实时同步到 Elasticsearch的技术方案选型和思考

前言

本文具体探讨 MySQL 数据实时同步到 Elasticsearch (以下简称 ES ) 技术方案和思考,同时使用一定篇幅介绍一些前置知识,从理论到实践,让读者更好的理解这块内容和相关问题。包括:


  • 为什么我们要将数据从 MySQL 实时同步到 ES ,本质是什么?

  • 为什么是 ES,而不是其他 OLAP 引擎?

  • MySQL 到 ES 数据实时同步方案中有哪些细节需要注意?

  • MySQL 到 ES 数据实时同步方案可以有哪些选择,优缺点是什么?


相信看完本文,你会对 MySQL 数据实时同步到 ES 有更多了解。

数据库去规范化

Database normalization is the process of structuring a database, usually a relational database, in accordance with a series of so-called normal forms in order to reduce data redundancy and improve data integrity. It was first proposed by Edgar F. Codd as part of hisrelational model.


数据库规范化是指关系型数据库中通过一系列数据库范式来减少数据冗余、增强数据一致性的策略。例如我们平时使用的关系型数据库的关系模型可以认为是 Database Normalization 的一种实现方式,这些关系型数据库基本都至少遵循了数据库第三范式,可以称之为 Normalized Database。关于数据库范式的内容,本文不再展开。


Denormalization is a strategy used on a previously-normalized database to increase performance. In computing, denormalization is the process of trying to improve the read performance of a database, at the expense of losing some write performance, by addingredundant copies of data or by grouping data. It is often motivated by performance orscalability in relational database software needing to carry out very large numbers of read operations. Denormalization differs from the unnormalized form in that denormalization benefits can only be fully realized on a data model that is otherwise normalized.


Database Normalization 在带来我们看得见的好处同时(利于事务操作性能、存储成本降低),伴随数据规模扩大、并发度提高、复杂度上升,弊端也慢慢展现,这时候 Database Denormalization 能够一定程度满足这些挑战,总体思路是通过一系列降低写入性能的操作例如更多的数据冗余、数据分组等来提升数据库读取的性能。

去规范化的时机

数据去规范化动机多样,当出现因数据复杂操作影响系统稳定性、业务响应/并发要求不满足等都是触发因素。


业务稳定性问题:面向 C 端的互联网应用特征是并发量较高,SQL 偏向点查点写,相对简单,但是沉淀下来的数据(比如订单、支付等) 需要做运营往往涉及传统企业级应用对于数据库的操作特征,大范围数据栅查、表关联、排序等实时操作,以及满足报表/BI 等更加复杂的数据库需求。通过去规范化和负载分离是较合理的选择。


复杂查询性能问题:企业级应用例如 ERP、CRM、BOSS 或者其他一些企业运营系统,经常涉及表关联、聚合、多维筛选、排序等操作,并常常带来性能问题。通过去规范化的一些方式,如下文提到的数据冗余和预计算方式,显著改善性能。

去规范化的几种实现方式

假设有如下三张表,学生、班级和教师。需求是:已知学生的学号,需要查询当前学生的班主任是名字。



使用规范化数据查询,是一个 3 表联查操作,而在数据库中,大体分三步:

  1. 通过学生学号获取学生信息,得到班级编号

  2. 通过班级编号获取班级信息,得到班主任工号

  3. 通过班主任工号得到教师信息,得到班主任的名字


如果在数据量较大,有一定并发要求,并且涉及更多表关联时候,这种计算就不能满足需求,这个时候去规范化的优化方式就登场了。

列级处理——主查询表冗余字段

通过在主表冗余计算好的数据,可避免频繁重复计算数据。如下场景适合在主数据表内冗余数据:

  • 应用系统需要经常获取计算好的数据

  • 冗余的原始数据不经常变化


在学生表冗余班主任的名字信息,表的设计变为如下:


这时候查询就只有一步了:

  1. 根据序号获取学生信息,同时也得到了其班主任名字的信息


优点:方法较为简单易懂,容易实现。


缺点:侵入业务逻辑,拖慢业务代码性能的同时,长期迭代所产生的变化可能会有稳定性风险。

表级处理——宽表预构建/Cube 预构建

表级处理主要操作就是构建宽表,或者构建数据立方体(Data Cube)。构建好的宽表包含了用户查询时需要的所有维度、度量信息。以上面学生查找班主任的问题为例,构建的宽表结构如下。


表级处理常见实现方式包括 应用多写数据库自身实现的物化视图数据迁移同步

应用多写

在主数据相同数据库内创建宽表,应用写入数据的时候同时也向宽表写入数据(事务保证一致性),复杂查询即可从该表进行。


优点:实现简单、低成本

缺点:对主数据库造成更大的读写压力,外加业务改造成本。

RDBMS 物化视图

Oracle、SqlServer 等数据库物化视图方案,通过数据冗余与预计算减少 join、聚合,从而提升查询性能。例如,在 Oracle 上完成学生查找班主任这个查询,可以构建一张“学生管理表”的物化视图,查询请求直接请求物化视图即可得到查询结果,避免 join ,显著改善该 SQL 执行效率。


优点:数据库引擎自身支持,使用成本较低

缺点:RDBMS 实现的方式有自己的局限性,比如生成物化视图的数据需要做一些业务紧相关变换就无法满足,或者某些数据库并没有完整实现该能力(物化视图在 2000 年左右是数据库学术圈研究的重点)。

数据迁移同步

借助数据同步工具,准实时将主数据表数据组织变换(包括按照业务逻辑变换)形成普通表或大宽表,写入第三方存储引擎(如 OLAP 存储引擎或者搜索系统)。复杂查询直接在预构建好的表上或者 cube 上执行,从而达到良好的性能。数据迁移工具的选择较多,总体上按照其侧重点,可以分为如下几类:

  • 大数据类:为大数据产品流入数据提供服务,因为大数据产品本身特点,侧重批量定时的迁移,实时同步一般需要用特别的方法,往往和业务特征紧耦合。常见的数据迁移同步工具有 sqoopdatax 

  • 流计算类:为自身流计算框架生态服务,侧重计算,迁移同步更多是类似数据连接器的角色,代表的产品如 Flink

  • 消息类:为自身消息产品生态服务,如丰富的 kafka connectordebezium 

  • 数据库类:数据库厂家一般都会提供原厂工具,典型如 Oracle 的 GoldenGate

  • 云厂商类:云厂商提供的数据迁移同步工具,主要侧重自身云上数据库生态产品之间的互融互通和将线下自建数据库的数据上云,例如阿里云 DTS, 腾讯云 DTS ,  AWS 的 DMS 等

  • 专业数据迁移同步工具: 包括部分开源产品或第三方独立公司提供的数据迁移同步工具,例如 canalstreamsetsmaxwell、cloudcanal、striimfivetran ,以及老牌数据集成厂商 Informatica 、Qlik 等所提供的产品


优点:

  • 主库更稳定:异步化解耦业务系统事务查询和复杂查询,避免复杂查询对主数据库产生影响

  • 易运维、链路稳定:数据迁移同步链路有标准化产品支撑,和主业务系统、主库读写解耦。整体架构上职责清晰,易于维护和问题追踪


缺点:需要对纷繁多样的数据迁移同步工具、承载复杂查询数据库产品选型,对技术同学能力有一定要求

MySQL 到 ES 数据实时同步技术架构


我们已经讨论了数据去规范化的几种实现方式。MySQL 到 ES 数据同步本质上是数据去规范化的一种。本节我们展开讨论“MySQL 到 ES 数据迁移同步”的技术解决方案,通过比较他们的优缺点和应用场景给读者提供一些思路。

为什么是 MySQL

MySQL 在关系型数据库历史上并没有特别优势的位置,Oracle/DB2/PostgreSQL(Ingres) 三老比 MySQL 开发早了 20 来年, 但是乘着 2000 年的互联网东风, LAMP 架构得到迅速的使用,特别在中国,大部分新兴企业的 IT 系统主数据沉淀于 MySQL 中。


  • 高并发能力:MySQL 内核特征特别适合高并发简单 SQL 操作 ,链接轻量化(线程模式),优化器、执行器、事务引擎相对简单粗暴,存储引擎做得比较细致

  • 稳定性好:主数据库最大的要求就是稳定、不丢数据,MySQL 内核特征反倒让其特点鲜明,从而达到很好的稳定性,主备系统也很早就 ready ,应对崩溃情况下的快速切换,innodb 存储引擎也保障了 MySQL 下盘稳定

  • 操作便捷:良好、便捷的用户体验(相比 PostgreSQL) , 让应用开发者非常容易上手 ,学习成本较低

  • 开源生态:MySQL 是一款开源产品,让上下游厂商围绕其构建工具相对简单,HA proxy、分库分表中间件让其实用性大大加强,同时开源的特质让其有大量的用户

为什么是 ES

ES 几个显著的特点,能够有效补足 MySQL 在企业级数据操作场景的缺陷,而这也是我们将其选择作为下游数据源重要原因


  • 文本搜索能力:ES 是基于倒排索引实现的搜索系统,配合多样的分词器,在文本模糊匹配搜索上表现得比较好,业务场景广泛

  • 多维筛选性能好:亿级规模数据使用宽表预构建(消除 join),配合全字段索引,使 ES 在多维筛选能力上具备压倒性优势,而这个能力是诸如 CRM, BOSS, MIS 等企业运营系统核心诉求,加上文本搜索能力,独此一家

  • 开源和商业并行:ES 开源生态非常活跃,具备大量的用户群体,同时其背后也有独立的商业公司支撑,而这让用户根据自身特点有了更加多样、渐进的选择

为什么是数据迁移同步方式

相对于数据去规范化的其他几种方案,数据迁移同步方式存在以下几个优点,也是其成为目前业界主流方式的原因:

  • 稳定性好:迁移同步对主数据库的操作主要是进行数据和日志的顺序读取,同时并发小,对主数据库稳定性影响较小(较多的下游订阅可能在网络层面存在影响,一般用消息解决)。另外日志(Binlog/WAL/Redo 等)可重放特质,让下游丢数据的可能性大大减小(处理好幂等的情况下)

  • 业务解耦:一般而言主数据库更多承载事务型操作,而下游数据系统承载运营等层面的业务, 典型如电商的买家侧和卖家侧业务

  • 业务侵入小:数据迁移同步对业务无侵入,双端对接标准数据库(源),可以便利地找到开源、商业、云等各个方向的成熟解决方案或产品

  • 业务适配性好:某些数据迁移同步产品能够嵌入业务逻辑,让下游获取到更加贴近业务的数据,从而让数据服务更加有效和便捷

数据迁移同步模型选择

订阅消费

优点
  • 堆积能力:由于引入了消息队列,所以整个链路是具备变更数据的堆积能力的。假设变更数据消费的比较慢,MySQL 本地较老的 binlog 文件由于磁盘空间的不足而被删除时,消息队列中的数据仍然存在,数据同步仍然可以正常进行

  • 数据分发能力:引入消息队列后可以支持多方订阅。如果下游多个应用都依赖源端的变更数据,可以订阅同一份 topic 即可

  • 数据加工能力:由于变更数据是由下游消费者订阅,因此订阅后可以灵活的做一些数据加工。例如从外部调用微服务接口或者反查一些数据来做数据加工都是比较方便的

缺点
  • 运维成本相对较高:包含了较多的组件和应用,运维保障相对复杂。

  • 稳定性风险较高:一环出问题会导致整个数据同步链路的稳定性受到影响。而且排查和定位问题也会比较困难。

端到端直连

优点
  • 低延迟:端到端的直接同步,链路较短,延迟低

  • 稳定性好:链路组件少,出问题概率较低,定位排查均比较容易。适合对数据精确性高的严苛场景。

  • 功能拓展性强:对端写入消息系统,模拟订阅模式,可扩展性强

  • 运维部署简单:链路组件少,部署运维更简单

缺点:无

数据迁移同步模型选择总结

从笔者以往的经验来看,如果没有众多的下游数据订阅,建议采用直连模式。数据同步链路往往置于在线业务中,随着业务规模以及重要性逐渐加大,链路 稳定性 更为重要些。另外 端到端模式 只要支持对端数据源为消息中间件,可立刻实现订阅模式,数据加工能力在某些数据迁移同步产品上可通过上传业务代码运行的方式解决。


数据架构在满足业务需求的同时,简洁清晰能够让系统更加易于维护和排查,当遇到链路每天同步几千万条上亿条数据、偶发丢几条需要排查,或同步链路卡住不同步等情况,端到端方式往往体现出相当大的优势。

MySQL 到 ES 数据实时同步核心挑战

关系型数据库中不同表之间的数据常存在关联,同步到 ES 之后,这种关联关系该如何去组织,同时又能够很好的匹配到 ES 的最佳实践 ? 本小节会展开讨论这个问题,并对常见的数据同步工具选型提供一些参考对比。

MySQL 关联表在 ES 上的设计

关系型数据库库中的表 join 关系在 ES 可以用几种数据类型来表达,包括 objectednestedjoin 三种。

objected

object 类型可以存储嵌套结构.

优点

  • 表示主 field 和 object 内部 field 之间的一对多关系,支持 doc 的 join 查询。由于所有查询时依赖的关联数据也都在一个文档内,避免了 ES 内部的 join,查询效率较高

缺点

  • 一对多关系只能保留一层,多于一层的会被打平,会丢失嵌套 field 内部的关联关系。下面的例子中,第一幅图看到写入 ES 的是一条订单数据,其中 producets 这个 field 是 object 类型,其中包含了多个产品的记录。


当采用 objected 字段存储 products 信息时,原本存储的信息如下:


"order_id" : 123,"products" : [
{ "price" : 10, "sku" : "SKU_10", }, { "price" : 20, "sku" : "SKU_20", }]
复制代码

在 ES 中存储的样子为:

{
"order_id": [ 123 ], "products.price": [ 10, 20], "products.sku": [ SKU_10, SKU_20 ],
}
复制代码


可以看到在 ES 的存储中,products 中每个字段的值都已经被打平处理。如果我们查询订单 ID 为 123,价格 price 为 10,SKU 为 “SKU_20” 的文档,我们同样可以搜索到结果,但这样显然就丢失了其内部之间的关系了。

nested

nested 类型可以存储嵌套结构,表示一对多关系,是 object 类型的拓展。


优点

  • 不会出现 object 的缺点,整个嵌套关系是完整维护的,子文档内部的关联关系保存是完整的

  • 关联数据通过实现上自然关联到主文档上,搜索时性能较好(相对于 join 类型)


缺点

  • 一个 nested field 只能属于一个主文档

  • 在 nested 类型中,子文档和主文档之间是强绑定,主文档更新的时候会强制更新子文档。在写多读少的场景,性能开销较大

  • child 文档的查询必须通过父文档再找到子文档

  • 子文档频繁修改的话会影响别的子文档和父文档,因为本质上在 lucence 实现上是父文档下的冗余存储

join

join 类型可以配置父子文档,通过父子文档来实现一对多的能力,一个索引只能建一个。相比 nested 类型,该类型更加灵活。父子文档之间通过 parentId 来关联,实际实现上他们就是独立的文档。


优点

  • 子文档更新不影响父文档和其他子文档

  • 一个子文档可以单独搜索

  • 一个文档在作为子文档时可以自己选择属于哪个父文档。通过 relation 可以指定不同的 join 列


缺点

  • 需要建个全局序数,用于服务于父子文档的关联关系,这个会影响搜索性能

join 和 nested 类型比较

  • join 适合写多读少场景,更加适合关注索引性能的场景。这意味着更新的生效会更快,但是搜索时的开销也相对大些

  • nested 适合读多写少的场景,更加关注搜索的性能

MySQL 到 ES 实时数据同步实现去规范化

在了解 ES 的一些关键类型之后,我们就可以描述通过数据同步去规范化的几种实现方式。

主表冗余数据

业务侧将一些查询时需要的关系数据提前冗余在源表的一个字段中。例如序列化成 json 存储在源表的一个冗余字段内,利用数据同步工具写入对端 ES 的 join/nested 类型字段。例如我们有订单表和商品表如下图所示。假设我们的搜索需求是,给定一个订单 ID,同时将这个订单的订单明细以及所有包含的多件商品的明细全部搜索出来。

如果采用这种列级处理模式,我们在订单表新增一个冗余列,然后将商品表的所有明细信息,按照 kv 组织成 json 写入冗余列即可,如下图所示。对端 ES 的 mapping 结构按照如下方式定义。数据同步工具直接将该保函关联表数据的订单表直接同步到对端 ES ,即可在 ES 上搜索符合我们需求的数据。


{  "mappings": {    "_doc": {      "properties": {        "order_id": {          "type": "long"        },        "order_price": {          "type": "long"        },        "product_count": {          "type": "long"        },        "discount": {          "type": "long"        },        "product_info": {          "type": "nested"        },      }    }  }}
复制代码


优点:

  • 处理模式能应对各种一对多的关联关系,对数据同步工具的功能要求低,配置简单,只需要支持单表同步到 ES 即可。


缺点:

  • 索引、搜索性能非最佳:提供给 ES 的不是预构建好的宽表数据。例如例子中,订单关联的商品信息,全部存储在主表的一个 object/nested/join 字段内,这种实现方式会有索引、搜索性能方面的额外开销,不是性能最佳的实现方式

  • 业务系统侵入:业务系统写主数据的时候需要额外写入信息

  • 主数据库表冗余过多数据:关系型数据库的表冗余了过多其他表的信息,可能存在存储和性能开销


总结:不太推荐该方式

多表订阅合并预构建宽表数据

数据同步工具同时订阅搜索时依赖的所有表,先到的数据先进到 ES,没有数据过来的字段为空。以上面提到的订单和商品表的例子来说,即同时同步订单表和商品表到对端索引。对端索引的 mapping 定义如下所示,包含订单和商品表的所有字段,定义的索引是一张宽表。流计算中多流汇聚配合时间窗口 join 多表的方式与该种方式有异曲同工之处。


优点

  • 数据同步工具配置同步任务较为简单,无业务入侵,不耦合业务系统逻辑

  • 对数据同步工具要求低,除了同步以外,不需要其他额外的功能特性

  • 基于预构建宽表的方式在 ES 上也有较好的索引和查询性能。

  • 同步链路不会因为宽表某些列缺失数据阻塞整个数据链路的同步(是否有该优点取决于数据同步工具本身设计,如果引入时间窗口,则同步链路会因为等待列数据影响同步时效性)。


缺点:

  • 基于事实表主动触发式的方式来进行宽表的构建。源端订阅的表,如果更新很少或者从来不更新产生 binlog,则对端的文档中的列值可能一直不完整,导致时效性会比较差。搜索的时候有一些列的数据会缺少


总结:

  • 适合构成宽表的事实表数据写入有事务保证一起落盘的场景,这样可以避免对端 ES 搜索到不完整的数据。

  • 适合构建宽表不需要业务加工处理的场景,构建宽表只是单纯的将多张表的列拼接在一起,形成宽表。


{  "mappings": {    "_doc": {      "properties": {        "order_id": {          "type": "long"        },        "order_price": {          "type": "long"        },        "product_count": {          "type": "long"        },        "discount": {          "type": "long"        },        "product_id": {          "type": "long"        },        "product_unit_price": {          "type": "long"        },        "product_name": {          "type": "text"        },      }    }  }}
复制代码

同步过程回查预构建

数据同步工具订阅的表称为主表。数据同步过程中,反查数据库查询的表称为从表。利用数据同步工具自身的能力,在订阅主表期间,自动通过回查的方式,填补宽表中的列,形成完整的宽表行数据。对端 ES 的 mapping 定义例子与“多表订阅合并预构建宽表数据”中的保持相同。


优点

  • 基于反查的方式构建宽表灵活性好,可以在生成宽表前基于主表的数据对从表数据做一些轻度的数据加工

  • 一条主表的数据,通过反查生成宽表行,可以配合数据加工生成多条宽表行数据

  • 基于反查的方式可以比较轻松的实现跨实例的 join ,从而生成宽表行(相对好实现,具体要看数据同步工具本身是否支持)

  • 基于宽表预构建的方式在 ES 上有较好的索引、查询性能。


缺点

  • 反查时数据可能没有准备好,导致数据缺失(这里具体的影响取决于数据同步工具本身设计,可以引入时间窗口配合超时等待,也可以没有数据时直接同步到对端)

  • 需要数据同步工具在数据反查、数据加工方面进行支持


总结:

  • 对于构建宽表涉及数据加工的场景,该方式比较适合。

  • 由于该方式的回查机制、预构建前数据加工的能力支持,能力上是“多表订阅合并预构建宽表数据”这种方式的超集。如果有比较好的数据同步工具支持,这种方式是比较推荐的。

数据迁移同步工具选型

数据迁移同步工具的选择比较多样,下表仅从 MySQL 同步 ES 这个场景下,对一些笔者深度使用研究过的数据同步工具进行对比(不一定精确,如有错误请联系笔者更正),用户可以根据自己的实际需要选取适合自己的产品。


特性\产品

Canal

DTS

CloudCanal

是否支持自建ES

ES对端版本支持丰富度

  • 支持ES6和ES7

  • 支持ES5,ES6和ES7

  • 支持ES6和ES7

嵌套类型支持

join/nested/object

object

nested/object

join支持方式

基于join父子文档&反查

基于宽表预构建&反查

是否支持结构迁移

是否支持全量迁移

是否支持增量迁移

数据过滤能力

  • 仅全量可添加where条件

  • 全增量阶段where条件

  • 全增量阶段where条件

是否支持时区转换

同步限流能力

任务编辑能力

数据源支持丰富度

架构模式

订阅消费模式

  • 需先写入消息队列

直连模式

直连模式

监控指标丰富度

  • 性能指标监控

  • 性能指标监控

  • 性能指标、资源指标监控

报警能力

针对延迟、异常的电话报警

针对延迟、异常的钉钉、短信、邮件报警

任务可视化创建&配置&管理能力

是否开源

是否免费

  • 社区版、SAAS版免费

是否支持独立输出

  • 依赖云平台整体输出

是否支持SAAS化使用

写在最后

MySQL 到 ES 数据同步构建数据检索服务给中小企业带来了稳定且实用的在线数据方案,在满足业务诉求(高并发业务与企业级应用常态化)的同时 ,易上手且具备不错的可维护性,在适当的场景下,值得尝试和实践。


最后感谢各位的阅读,内容相对浅显且直接,希望对你有所帮助和启发。在此也简单介绍下笔者自己,本人在阿里巴巴中间件和云智能团队从事过几年数据相关工作,在该领域具备一定的经验,对这个方向感兴趣的朋友可以一起探讨相关技术问题,我们专门开设了一个问答社区 askcug.com 以便大家探讨,欢迎加入探讨。

参考资料

  • [1] 维基百科:Database normalization

  • [2] 维基百科:Denormalization

  • [3] When and How You Should Denormalize a Relational Database

  • [4] 爱奇艺|海量数据实时分析服务技术架构演进

  • [5] 从 ES 到 Kylin,斗鱼客户端性能分析平台进化之旅

  • [6] 常见开源 OLAP 技术架构对比

  • [7] Elasticsearch:Tune for search speed

  • [8] Elasticsearch:Field data types

  • [9] Designing Data-Intensive Applications

  • [10] Materialized Views

  • [11] A Relational Model of Data for Large Shared Data Banks 


作者介绍: 万凯明,前阿里巴巴集团数据同步中间件核心成员(花名万少),有多年数据同步领域工作经验,专注于数据集成、数据融合领域的工作和研究。当前就职于 clougence,打造多源多端数据迁移同步工具 CloudCanal。


本文转载自公众号:clougence

2021 年 3 月 23 日 14:4315427

评论 33 条评论

发布
用户头像
请教下,如果需要同步多个库的多张表,这些表之间有一对一、一对多、多对多的关系,这些表如何同步到ES,在ES里如何存储呢?一对一的用宽表,一对多的用nested/join,多对多的拆成两个一对多吗?非常感谢!
2021 年 08 月 19 日 17:32
回复
一条主表的数据,通过反查生成宽表行,可以配合数据加工生成多条宽表行数据
这句的意思是,针对一对多的表,也可以使用宽表,每条子表数据作为宽表的行数据,并冗余主表数据吗?比如订单表的某条记录对应5行订单明细表数据,那么宽表中存储5行宽表行数据,每行数据里冗余相同的那条订单表数据吗?
2021 年 08 月 19 日 17:39
回复
https://github.com/alibaba/canal/wiki/Sync-ES
从Canal的官方文档来看,是否可以将关联表写成SQL后直接同步过去?就不需要单表一张张同步了?
2021 年 08 月 20 日 08:52
回复
用户头像
上面示例中的“订单”表和“商品”表,是不是缺少了关联的字段?不然如何知道订单里有哪些商品
2021 年 04 月 14 日 18:55
回复
用户头像
表结构的变更是否会对下游订阅产生影响,以及怎么处理的?
2021 年 04 月 01 日 10:36
回复
这个不同的数据同步工具处理不同。以CloudCanal为例,它是支持DDL同步的,如果源端有表结构变更,对端也是一个关系型数据库,我们会自动从binlog解析出ddl语句,并且改写成对端数据库支持的SQL方言,保证对端和源端的表结构一致。如果用户不想源端的结构变更影响下游,创建任务的时候勾选”不同步DDL“就可以了。
2021 年 04 月 01 日 10:47
回复
用户头像
如果是一个订单对应多个商品,怎么构建宽表呢
2021 年 03 月 31 日 15:51
回复
如果你场景是订单表、商品表关联,在ES构建索引(订单id为主键)。可以考虑建2个同步任务,第一个同步任务以订单表为主表(同步订阅的表,驱动表),同步时反查商品表,然后构建宽表行数据写入对端。第二个同步任务以商品表为主表,同步时反查订单表即可。两个同步任务一起运行,无论商品表更新还是订单表更新,对端索引数据都会实时更新。如果商品表有冗余关联的订单id信息,那么反查订单表的过程可以省略,直接根据订单id更新对端索引对应doc即可(订单id作为对端es routing)
2021 年 03 月 31 日 18:15
回复
这样同步任务有点多了。可以一个同步任务同时订阅订单和商品表的更新吗
2021 年 10 月 13 日 12:01
回复
用户头像
有两个端到端模式的问题请教:
1. 关于缺点,举个例子,印象中canal是存在脑裂风险的: https://github.com/alibaba/canal/issues/2859,所以直接使用端到端模式的话会有数据重复的风险吧?
2. 单纯限流感觉只能搞定正常情况,突发和异常操作 带来的瞬间峰值流量,如果没有mq削峰还是容易出问题的?
2021 年 03 月 31 日 11:42
回复
您好,你的问题我是这样看的哈:
1. 首先脑裂导致的数据双写和使用端到端模式还是消费订阅模式没有强相关关系,这个取决于工程实现。考虑两个进程同时写入对端时,如果是无主键表,对端会产生重复数据。在无主键表同步的场景下,尽量要避免产生进程双跑导致的数据重复问题;如果是有主键的表并且两者的同步的进度差异比较大,会导致对端同一个主键的行数据新老交替出现,也会影响业务使用。综上,主要是考虑工程上面避免进程双跑的问题。比如针对订阅的表都是有主键的情况下,可以采用”事后处理“的策略。这里我们假设的订阅的表都是有主键的,如果出现了双跑的情况,需要及时退出多余的写入。这里可以只保留写的最慢的那个线程,这样其他线程退出后,最慢的线程持续写入,最终数据是一致的。如果是无主键表,事后处理仍然会导致重复数据写入,这时候就要考虑事前处理,从工程实现上就尽量杜绝双跑的可能性。例如cloudcanal中,我们都是通过事前处理提前判断任务进程是否有在运行,如果已经运行,不会启动重复的进程,这样在工程角度上避免双跑。


2. 我理解数据同步工具层面的限流已经达到了削峰填谷的目的,写入对端的流量是不会有峰值的。mq是把数据持久化到本次存储,对于直连的方式来说,数据只不过持久化在mysql server的本地存储而已,堆积在mq server和堆积在mysql server本质上原理是一样的。只不过mq数据一般堆积的量可以更多,mysql则要注意本地binlog文件可能会被定时清理。使用mq主要还是考虑个性化订阅、一对多分发、更强的消息堆积能力。
展开
2021 年 03 月 31 日 14:26
回复
感谢回答,说的非常清楚
仍有一点疑问:事前处理的方式在“已经出现网络分区”或者“旧进程已经掉锁且处于Full GC”的情况下,新进程如何感知已存在重复进程呢?


2021 年 03 月 31 日 20:56
回复
你说的情况其实不能算事前处理了。比如cloudcanal事前处理的方式,是没用zk的,通过好的架构设计、任务生命周期管理、元数据管理,是可以杜绝同一个同步任务,在分布式环境中启动重复的进程(这个和工程实现相关,要说清楚可能需要专门一篇文章来说明)。至于你提到的场景,其实只能是事后处理了,如果事前处理的话,就应该避免这样的情况出现。对于你说的情况,我提出一种可能的工程处理办法:提供一种进程自杀机制,掉锁了就自己退出进程就好了,确保只有一个获取到锁的同步进程可以执行。如果自杀机制有问题,可以额外提供一个外部巡检进程,识别掉锁的情况,识别到之后kill对应的进程。我这边主要提供一些思路,如果自己设计同步工具考虑分布式环境下避免双跑,具体问题还是要具体分析。
2021 年 04 月 01 日 10:43
回复
用户头像
我想问几个问题:


1、如果三表联表查询,源表(mysql表)中某一张表中的一条数据发生变更,同步工具支持实时更新数据吗?
2、es存在一个问题,如果mysql表结构发生变更,是否同步作业需要重新全量同步,因为在我印象中es需要重新创建index才可以
2021 年 03 月 29 日 18:53
回复
1. 支持实时更新的,对端索引只更新有修改的列
2. 结构变更如果只是增加mapping里面的field不需要reindex,如果修改field类型需要reindex。这个可以参考官方如下资料,还有问题可以再提问哈
https://www.elastic.co/guide/en/elasticsearch/reference/master/data-streams-change-mappings-and-settings.html

https://www.elastic.co/cn/blog/changing-mapping-with-zero-downtime
展开
2021 年 03 月 30 日 10:45
回复
非常感谢
2021 年 03 月 30 日 16:51
回复
不好意思,能否详细讲解一下cloudcanal实现多表联表查询的数据同步到es的具体实现吗?
2021 年 03 月 30 日 17:56
回复
查看更多回复
用户头像
多维栅选 ?多维删选?多维筛选?请问应该是哪一个?
2021 年 03 月 28 日 16:58
回复
多维筛选,这个是错别字,需要修改下~
2021 年 03 月 29 日 10:15
回复
用户头像
真的很棒,涨知识了
2021 年 03 月 27 日 20:01
回复
用户头像
笔者写的很好,由浅入深,化繁为简。
2021 年 03 月 24 日 16:08
回复
用户头像
端到端直连模式是有缺陷的。当某个表被多个索引关联时怎么办?如果数据库变更字段为非索引字段该如何过滤?当辅表变更致使大量索引更新,引发延迟后如何保障其他索引不受影响?如何防止上游并发量太高打垮ES集群,不需要流控?
2021 年 03 月 23 日 23:09
回复
我们先假设讨论的前提是引入数据同步中间件的情况下(或者自己实现了对应的同步工具),采用数据同步中间件完成端到端直连,是可以解决你提的几个问题的:
1. 某个表被多个索引关联怎么办?这个在数据同步工具上建多条同步链路即可,源端某个事实表被更新,几条同步链路会同时感知这个变化,写入对端,各个数据同步链路之间独立工作,分别汇聚数据后写入对端的索引即可
2. 如果数据库变更字段为非索引字段该如何过滤?这个在创建同步链路的时候已经定义好了我们需要订阅哪些字段,数据同步工具支持对表进行列裁剪后再订阅是比较常见的能力。这样源端非索引字段更新自然不会同步到对端索引
3. 当辅表变更致使大量索引更新,引发延迟后如何保障其他索引不受影响?这个和第1个问题有点类似,不同索引 关联的是不同的数据同步链路,一个索引依赖的辅表如果延迟了,只影响他自己的同步链路
4. 如何防止上游并发量太高打垮ES集群,不需要流控?业务提前做好容量评估,例如ES能承载的读写上限以及各个同步链路源端的峰值吞吐,提前在数据同步工具上对每个同步链路做好限流设置就可以了(限流能力也算数据同步工具的标配能力了)


不知道我的回答有没有解答您的疑惑,如果还有问题可以继续留言,希望能帮助到你~
展开
2021 年 03 月 25 日 14:01
回复
如此的话你提供的几种数据同步工具选型是满足不了需求的。而对于上述几点问题的答复,反倒有点像是把订阅模式的涉及到的功能点都揉合到同步工具中了。
2021 年 03 月 29 日 13:56
回复
感谢回复,我稍微补充下哈。上面我提到的几点能力cloudcanal都是有的,你可以用下试试,也是免费的。当然如你所说,这个取决于工具实现,有些数据同步工具本身这方面能力是没做完整的,那用户在实时方案是自己需要考虑这些问题。另外数据同步工具只是服务于你进行数据迁移和同步的,至于你选择消费订阅模式还是直连模式都是可以的。如果使用消费订阅模式,数据同步工具可以支持你数据先写入到kafka,然后你的应用直接订阅kafka的消息,自己再写入对端ES。或者你也可以直接使用数据同步工具,订阅源端binlog,由数据同步工具直接负责帮你落库到对端数据库,这个过程不需要流经kafka这样的消息系统。
2021 年 03 月 29 日 16:11
回复
查看更多回复
用户头像
很专业,各种工具都有了一个比较清晰都对比。 CloudCanal 以前没用过,看上去很猛啊。下个业务里面一定要试一试。
2021 年 03 月 23 日 16:12
回复
用户头像
深度好文顶一下,期待作者的更多文章!
2021 年 03 月 23 日 16:10
回复
没有更多了
发现更多内容

Dromara团队发布Hmily全新架构的2.1.1版本

猫大人

分布式事务 分布式柔性事务‘’

我一定是熬夜熬傻了,小程序后台获取用户信息居然发生了这件事

小Q

Java 小程序 学习 编程 架构

Nexmark: 如何设计一个流计算基准测试?

Apache Flink

flink

Smartisan

Changing Lin

摄影

一个草根的日常杂碎(9月29日)

刘新吾

随笔杂谈 生活记录 社会百态

极光无限:用AI赋能安全 解决安全行业人才紧缺难题

风向标

人工智能

LeetCode题解:242. 有效的字母异位词,数组排序,JavaScript,详细注释

Lee Chen

LeetCode 前端进阶训练营

关于 UML 类图

西贝

UML 图表

Java源码系列4——HashMap扩容时究竟对链表和红黑树做了什么?

超超不会飞

Java

在 InfoQ 兼职做运营

邓瑞恒Ryan

创业 用户增长 创业心态 运营 产品运营

架构师训练营 1 期 - 第三周 - 设计模式

三板斧

极客大学架构师训练营

第三周学习代码重构总结

三板斧

极客大学架构师训练营

2020HC大会上,这群人在讨论云原生…

华为云开发者社区

华为 华为云 大会

阿里内部超流行的“SpringBoot+ 微服务指南”,理论与实战双管齐下

Java架构之路

Java 程序员 微服务 Spring Boot 编程语言

GitHub上标星68k,基于SpringBoot+Netty分布式开源的即时通讯系统项目

Java架构之路

Java 程序员 编程语言 Netty 项目实战

单例模式

knight

码住!Flink Contributor 速成指南

Apache Flink

flink 开源社区

传统网络缺失货币层,比特币是否能担此大任?

blockchain

比特币 区块链 数字货币 比特币数字货币 区块俩金融

2020互联网公司中秋礼盒大比拼!(文末送福利)

Java架构师迁哥

国内上市进程或将提速!百度宣布小度科技独立融资

脑极体

FastDFS 分布式文件系统详解

哈喽沃德先生

文件系统 分布式文件存储 fastdfs 分布式文件

烦人的Null,你可以走开点了

四猿外

Java 注解 空指针 Optional null

基于 Flink + Hive 构建流批一体准实时数仓

Apache Flink

flink

架构师训练营第 1 期第 3 周学习总结

好吃不贵

极客大学架构师训练营

一个Hibernate的事务问题

YoungZY

hibernate

Java源码系列3——LinkedHashMap

超超不会飞

Java

谈谈测试

得大自在

测试的价值 测试文化 测试落地

一个好系统自我完善自我进化的方法

boshi

产品思维 系统工程 即时反馈 生态体系

Java源码系列2——HashMap

超超不会飞

Java

太牛了,这份神仙级面试笔记把所有 Java 知识面试题都详解出来了

Java架构之路

Java 程序员 面试 编程语言

开源=免费?

Philips

开源 开源社区

开源中间件技术学习路线

开源中间件技术学习路线

MySQL 数据实时同步到 Elasticsearch的技术方案选型和思考-InfoQ