MySQL数据同步到ES,折腾半天才搞定,真是累并快乐着
- 问答
- 2026-01-23 11:24:36
- 4
(来源:知乎用户“三分钟热度”分享)当时我接到的任务是把商品数据从MySQL实时同步到Elasticsearch里,好让前端搜索能快点,一开始我以为就是个配置活儿,顶多半天搞定,结果没想到一脚踩进坑里,前后折腾了快三天,真是应了那句话——理想很丰满,现实很骨感。
我最先试的是用Logstash,网上很多教程(来源:CSDN技术博客)都说这个简单,配个jdbc输入插件,再配个ES输出插件就行了,我照猫画虎,把数据库连接信息、SQL查询语句都写进配置文件,满心欢喜地一运行,数据倒是哗哗地出来了,也进ES了,但问题马上来了:这只能全量同步啊!我总不能每次有商品价格变动或者上新,都把整个几百万的表重新导一遍吧?数据库也受不了啊,得想办法做增量同步。
(来源:Logstash官方文档)文档里说可以用sql_last_value配合自增ID或者更新时间戳来追踪增量,我用的是update_time字段,心想这总行了吧,结果又遇到新坑,Logstash它毕竟是定时轮询的,我设个每分钟跑一次,那这一分钟内更新的数据就没法实时反映到ES,有延迟,这还不算,有时候网络抖一下,或者ES集群压力大一点,某次同步失败了,sql_last_value的值却没回滚,下次同步就会漏掉那批失败的数据,头疼死了,为了处理异常和保证准实时,我又得去研究重试机制和更精细的时间戳控制,感觉越来越复杂。
后来同事说,干嘛不用阿里巴巴的Canal?(来源:公司内部技术分享会)它原理是伪装成MySQL的从库,直接读取binlog,这才是真正的实时同步,我一听,有道理啊,从源头抓变更,又准又快,兴致勃勃地搭环境,配置Canal Server和Canal Adapter,结果光是让Canal能连上MySQL就费了老大劲,MySQL要开binlog,格式还得是ROW模式,授权账号也有一堆权限要求,一步不对就报错,报的错误信息还经常看得云里雾里。
好不容易连上了,数据变更也能抓到了,新的麻烦又来了,Canal解析出来的binlog数据格式,和ES文档需要的JSON格式对不上,比如数据库里一个商品的状态字段是tinyint,0和1,到了ES里我想映射成布尔值,或者一个复杂的JSON对象在MySQL里是存成文本字段的,需要解析成嵌套结构,这都需要在Canal Adapter里写一堆映射配置,有时候还要自己写转换器,那几天我满脑子都是字段映射、类型转换,感觉像个数据裁缝,不停地修修补补。
最崩溃的一次是,同步过程中不小心把一个大文本字段(商品描述,里面啥特殊字符都有)直接怼进ES了,导致ES报错,整个同步任务卡住,排查了半天才发现是某个商品描述里有个特殊的控制字符,ES不认,只好又去研究怎么在同步前清洗数据,或者配置ES的字符过滤规则。
就这么反复折腾,测试了无数次,增删改查各种场景都试了个遍,终于看着MySQL里的数据变动能几乎实时地、准确地反映在ES里了,当我在Kibana里秒搜到刚刚在后台修改的商品时,那种感觉,真的就像打通了任督二脉,之前所有的烦躁和疲惫都烟消云散了,只剩下“搞定”的痛快,虽然过程很累,但确实学到了不少东西,怎么处理数据一致性,怎么排查链路问题,算是痛并快乐着吧。

本文由度秀梅于2026-01-23发表在笙亿网络策划,如有疑问,请联系我们。
本文链接:https://haoid.cn/wenda/84426.html
