背景
前提说明,本文中的Canal版本使用的是1.1.7, 分支:canal-1.1.7-hotfix-1,es为8.0
项目中涉及到大数据量的模糊查询、多表关联查询,已有的关系型数据库(Mysql)性能并不能支持业务需要,因此通过引入ES中间件构建宽表优化查询。
大致的技术方案,采用的是Canal订阅Mysql的binlog日志,然后发送到kafka,再启动Canal的client-adapter模块将其同步到ES。
实践中的问题
在具体的测试过程中,我们也遇到了一些跟得物相似的问题,这些问题同样在下面的参考资料中得物的技术文档有所说明。这里摘抄部分案例过来:
- 多表关联部分情况不同步
- 多表关联同步性能问题 同时官方文档中同样有说说明,sql支持多表关联自由组合, 但是有一定的限制:
- 主表不能为子查询语句。
- 只能使用left outer join即最左表一定要是主表。
- 关联从表如果是子查询不能有多张表。
- 主sql中不能有where查询条件(从表子查询中可以有where条件但是不推荐, 可能会造成数据同步的不一致, 比如修改了where条件中的字段内容)。
- 关联条件只允许主外键的'='操作不能出现其他常量判断比如: on a.role_id=b.id and b.statues=1。
- 关联条件必须要有一个字段出现在主查询语句中比如: on a.role_id=b.id其中的a.role_id 或者b.id必须出现在主select语句中。
- Elastic Search的mapping 属性与sql的查询值要一一对应(不支持 select *), 比如: select a.id as _id, a.name, a.email as _email from user, 其中name将映射到es mapping的name field, _email将 映射到mapping的_email field, 这里以别名(如果有别名)作为最终的映射字段. 这里的_id可以填写到配置文件的 _id: _id映射。
基于上述的问题,这里主要讲的就是如何自定义ES的同步模块,解除上面的限制,实现多表关联的同步。
方案落地
前提:已经搭建好Canal-server的集群、zookeeper、Canal-admin等服务。这部分内容本文不进行赘述。
- 拉取代码:git clone github.com/alibaba/can…
- 切换分支: canal-1.1.7-hotfix-1
- 在client-adapter工程,新创建一个模块:esCustom,模块配置可复制es8x
- 由于client-adapter是基于spi的方式,将外部适配器作为插件(plugin)根据配置动态加载,所以同样的,我们新建的模块esCustom也需要进行配置
项目地址:github.com/Bigezno/Can… 欢迎大家Star,亲测生产可用。
参考资料:
- Canal官方文档:github.com/alibaba/can…
- 得物Canal同步文档:zhuanlan.zhihu.com/p/336211358