构建实时搜索的选型与思考
前言
本文具体探讨 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 his relational 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 adding redundant copies of data or by grouping data.[1][2] It is often motivated by performance or scalability 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 表联查操作,而在数据库中,大体分三步:
- 通过学生学号获取学生信息,得到班级编号
- 通过班级编号获取班级信息,得到班主任工号
- 通过班主任工号得到教师信息,得到班主任的名字
如果在数据量较大,有一定并发要求,并且涉及更多表关联时候,这种计算就不能满足需求,这个时候去规范化的优化方式就登场了。
列级处理——主查询表冗余字段
通过在主表冗余计算好的数据,可避免频繁重复计算数据。如下场景适合在主数据表内冗余数据:
- 应用系统需要经常获取计算好 的数据
- 用于计算 calculated data 的原始数据不经常变化
在学生表冗余班主任的名字信息,表的设计变为如下:
这时候查询就只有一步了: 根据序号获取学生信息,同时也得到了其班主任名字的信息
优点:方法较为简单易懂,容易实现。 缺点:侵入业务逻辑,拖慢业务代码性能的同时,长期迭代所产生的变化可能会有稳定性风险。
表级处理——宽表预构建/Cube预构建
表级处理主要操作就是构建宽表,或者构建数据立方体(Data Cube)。构建好的宽表包含了用户查询时需要的所有维度、度量信息。以上面学生查找班主任的问题为例,构建的宽表结构如下。
表级处理常见实现方式包括 应用多写、数据库自身实现的物化视图、数据迁移同步。
应用多写
在主数据相同数据库内创建宽表,应用写入数据的时候同时也向宽表写入 数据(事务保证一致性),复杂查询即可从该表进行。
优点:实现简单、低成本 缺点:对主数据库造成更大的读写压力,外加业务改造成本。
RDBMS 物化视图
Oracle、SqlServer 等数据库物化视图方案,通过数据冗余与预计算减少 join、聚合,从而提升查询性能。例如,在 Oracle 上完成学生查找班主任这个查询,可以构建一张“学生管理表”的物化视图,查询请求直接请求物化视图即可得到查询结果,避免 join ,显著改善该 SQL 执行效率。
优点:数据库引擎自身支持,使用成本较低 缺点:RDBMS 实现的方式有自己的局限性,比如生成物化视图的数据需要做一些业务紧相关变换就无法满足,或者某些数据库并没有完整实现该能力(物化视图在 2000 年左右是数据库学术圈研究的重点)。
数据迁移同步
借助数据同步工具,准实时将主数据表数据组织变换(包括按照业务逻辑变换)形成普通表或大宽表,写入第三方存储引擎(如 OLAP 存储引擎或者搜索系统)。复杂查询直接在预构建好的表上或者 cube 上执行,从而达到良好的性能。数据迁移工具的选择较多,总体上按照其侧重点,可以分为如下几类:
- 大数据类:为大数据产品流入数据提供服务,因为大数据产品本身特点,侧重批量定时的迁移,实时同步一般需要用特别的方法,往往和业务特征紧耦合。常见的数据迁移同步工具有 sqoop、datax 等
- 流计算类:为自身流计算框架生态服务,侧重计算,迁移同步更多是类似数据连接器的角色,代表的产品如 Flink
- 消息类:为自身消息产品生态服务,如丰富的 kafka connector、debezium 等
- 数据库类:数据库厂家一般都会提供原厂工具,典型如 Oracle 的 GoldenGate
- 云厂商类:云厂商提供的数据迁移同步工具,主要侧重自身云上数据库生态产品之间的互融互通和将线下自建数据库的数据上云,例如阿里云 DTS, 腾讯云 DTS , AWS 的 DMS 等
- 专业数据迁移同步工具: 包括部分开源产品或第三方独立公司提供的数据迁移同步工具,例如 canal、streamsets、maxwell、cloudcanal、striim、fivetran ,以及老牌数据集成厂商 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 可以用几种数据类型来表达,包括 objected , nested , join 三种。
objected
object 类型可以存储嵌套结构.