分库分表后复杂查询的应对之道:基于 DTS 实时性 ES 宽表构建技术实践
1 问题域
业务发展的初期,我们的数据库架构往往是单库单表,外加读写分离来快速的支撑业务,随着用户量和订单量的增加,数据库的计算和存储往往会成为我们系统的瓶颈,业界的实践多数采用分而治之的思想:分库分表,通过分库分表应对存系统读写性能瓶颈和存储瓶颈;分库分表帮我们解决问题的同时,也带来了复杂性;比如多条件的分页查询,多条件的联表查询变得复杂起来,通过调研我们发现针对这些分页,联表的复杂查询,业界常用的解决方案有以下两种:1 构建 ES 宽表,2 构建查询条件到表主键 Mapping 映射表;本表文章介绍我们的实践:基于公司的中间件 DTS 构建实时性的 ES 宽表。所谓的宽表是通过主键将多张表关联成一张表,比如订单维度的宽表字段包含:订单主表,订单明细表,商品表,用户表等表字段。
2 ES 宽表构建解决方案域
2.1 同步双写
应用在接收到写请求后,同步写 DB 成功,然后再同步写 ES。
![](https://static001.geekbang.org/infoq/15/15162fc1f77e3ddc29bf1661f0d5c4da.png)
2.2 异步双写
应用在接收到写请求后,同步写 DB 成功,异步发送 MQ,消费 MQ 异步写 ES。
![](https://static001.geekbang.org/infoq/46/46115bbc3ca7bb62e4e944fd4247d015.png)
2.3 基于 Binlog 的实时同步
2.3.1 Binlog 作为消息
将 Binlog 作为消息,或者驱动的 Event,接收到消息后,RPC 调取下游的业务系统,获取业务数据进行数组的组装,写入 ES。
![](https://static001.geekbang.org/infoq/6b/6b18dff4a0e05e0c22b445adf43a7f69.png)
2.3.2 Binlog 作为数据
解析 Binlog 中的数据,获取库表,字段变更前后的内容,INSERT, UPDATE, DELETE 事件,基于 Binlog 中的数据去构建宽表,写入 ES。
![](https://static001.geekbang.org/infoq/ac/ac269a99d084256cab7e43ced346d20f.png)
3 解决方案优缺点对比
![](https://static001.geekbang.org/infoq/1e/1e37419c938f91cb6925cc80fd322a7b.png)
4 我们的实践
4.1 Binlog 作为数据构建 ES 宽表
![](https://static001.geekbang.org/infoq/70/70e187d813db378e6cef7d88d37cef16.png)
4.1.1 顺序性的保证
上游 DTS 监听的 binlog 是有序的;发送消息时,业务方可以配置业务主键例如 uep_order_no,DTS 可以根据业务主键进行 hash,将该条消息发送到对应的队列保证局部有序性;消费者消费时,同一个订单号 uep_order_no 映射到同一个分区,保证顺序消费;
4.1.2 幂等性的保证
DTS 可以保证消息不丢失,但不保证消息不重复,可能发送重复的消息需要业务方保证幂等性,
UPDATE/DELETE 操作天然具有幂等性
INSERT 操作在进行操作前需要先判断下数据是否存在,不存在则插入,存在则更新
4.1.3 数据一致性的保证
由于数据存储在 Mysql 和 ES 两种存储媒介,可以采用定时任务对账机制保证数据的一致性,如果数据不一致采用补偿任务进行补偿操作
4.1.4 存量数据迁移
采用定时任务分页将数据从 Mysql 迁移到 ES
4.2 ES 复杂检索
4.2.1 检索的分类
多条件的复杂查询,采用 Bool 查询;
![](https://static001.geekbang.org/infoq/a1/a1e1af9f84d08b8f37ac18b6f3ed50db.png)
4.2.2 查询条件构建
![](https://static001.geekbang.org/infoq/3a/3a49275b7e160a128c4b09ccfc7111ff.png)
版权声明: 本文为 InfoQ 作者【京东科技开发者】的原创文章。
原文链接:【http://xie.infoq.cn/article/482fa17a622eb28038c0b37a5】。文章转载请联系作者。
评论