数仓大搜索能力增强方案

613 阅读5分钟

随着数据规模增大,搜索的需求仅靠关系型数据库中的like %searchKey%已经无法满足大数据量下的快速检索相应。无论sql再怎么优化,由于索引结构的限制走不了索引,数据增长到一定规模后再用复古sql like方案给用户的体验非常差。

市面上的搜索组件已经非常成熟了,提升搜索能力第一反应就是使用全文检索最流行的ElasticSearch组件。通过其强大的倒排索引及其他特性加速查询。

使用这种组件就会引入另外一个问题,如何保证数据同步,业务数据存储在关系型数据库中,搜索的数据存储在ES中,如何保证业务侧的增删改操作同步更新到ES中。

全量同步

引入ES组件首先要解决的就是旧数据问题,也就是之前的数据都是存放在MySQL中的,使用ES搜索就必须要把MySQL的数据同步到ES中。

脚本同步最实在,开发量可能偏大,在我们的场景下是有一个每次升级前跑的python脚本,数据库变动、数据变更等操作都在这做,直接select所有数据,写入es完事。

或者使用各种数据同步组件如FlinkX、DataX、Cancel同步数据等,全量的同步方案都很成熟,这波主要讨论下增量同步的方案。

增量同步

同步修改

同步修改就是指业务侧在执行增删改的操作后同步更新的ES中,这种方案的实时性最高,但开发成本也会更高。需要找到所有的修改入口,在每个接口都加上同步ES的操作,还要保证写业务库与写ES的原子性

这个方案在我们的业务场景下基本可以忽略不计,leader每次把控技术方案的时候都是以尽可能的少改旧代码为宗旨。所谓多做多错,所以暂不讨论具体的方案。

  • 优势:
    1. 开发难度低
  • 劣势:
    1. 代码耦合度高,硬编码
    2. 入口太多,代码工作量大

异步修改

FlinkX

FlinkX是袋鼠云开源的一个底座给予Flink引擎的数据同步插件,实现了多种数据源高效的数据同步,基本功能和DataX差不多,据说是原班人马写的,代码风格也很像。(现已改名为ChunJun)。

使用此方案的思路则是使用flinkX组件创建出一个流式同步作业,作业内容把mysql的数据变更实时同步到ES中。mysql和es的数据同步插件都提供更好了,构造任务json即可。

由于底座基于flink引擎,可以依赖一些flink的特效去保证数据的可靠性,flink-ui查看同步进度以及任务状态。使用此方案首先需要搭建flink组件,然后使用flinkx开发出一套source为flink,sink为es的作业。最重要的一点是如果在tob场景下,部署环境较为复杂,任务极有可能因为flink集群状态异常挂掉,或者因为资源不足被系统杀掉。

这时候还需要有一个健康检查的小服务去不断检查任务的flink同步任务状态,如果发现任务挂掉则需要重新提交任务。

  • 优势:

    1. 开发难度相对较低
    2. 借助flink引擎特性保证数据可靠
  • 劣势:

    1. 增加新组件的维护成本
    2. 代码开发量较大,tob场景下任务挂掉会有较长时间的数据不一致情况

cancel

使用阿里开源cancel组件监听binlog日志。

本质上canal模拟MySql集群的交互协议,伪装自己为MySql集群的一个节点,向MySql master发送 dump协议,MySQL master 收到 dump 请求,开始推送binary log给slave(即canal),canal解析binary log 对象同步数据。

大体上与FlinkX方案类似,都是通过第三方组件异步的同步数据,既然是异步就会存在数据不一致问题,而且mysql集群本身就存在主从数据同步不一致问题。

  • 优势:
    1. 开发难度相对较低
  • 劣势:
    1. 增加新组建的维护成本
    2. 基于binlog做数据同步会出现数据不一致情况
    3. 保证进程常驻

webhook

以上的方案都会产生引入了新组建之后需要规避特殊场景下的各种问题,如果说要找一个完全没问题的方案也不太可能,就像CAP不能完全满足,10除以3永远除不尽的问题,那有没有一个折中方案尽可能的将各种影响降到最低呢。

基于当前的业务场景,最终确定的方案就是webhook

webhook是当下web应用比较流行的一个能力,可以简单类比为"订阅-发布模型",一端触发事件结束后另一端监听执行,相当于一个回调操作。当事件触发执行完成后通过webhook回调配置好的地址后触发配置的动作。

使用过钉钉的群自定义机器人或者gitlab或者jenkins的同学应该对这个能力不陌生,这两个成熟的产品都提供了稳定的webhook能力,以供开发者配置推送规则,比如配置Jenkins服务成功打包后推送到钉钉群里。

image.png

基于此能力即可在网关层拦截对应的增删改请求,为了不影响业务操作,需要在请求结束后再触发同步es数据操作。这样的话只需要在网关配置好需要拦截的路由规则,同步es数据的操作统一抽象成方法,统一调用。

这样既影响不到业务操作,也不会造成太久的数据不一致时间,甚至不需要增加服务来维护数据同步。