数据双份存储, ES + MySQL, 如何保证一致性 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
ayonel
V2EX    Elasticsearch

数据双份存储, ES + MySQL, 如何保证一致性

  •  
  •   ayonel 2019-09-16 14:01:27 +08:00 14823 次点击
    这是一个创建于 2216 天前的主题,其中的信息可能已经有所发展或是发生改变。

    目前业务的数据都存在 mysql 中,为了做一个搜索模块,故需要将数据冗余一份至 es. mysql 中的数据可以理解为星型模型, 由一个主表 跟 多个副表 关联而成。比如:主表是用户基本信息,副表 1:用户爱好; 副表 2:用户课程; 副表 3:用户历史购物记录。副表跟主表根据 user_id 关联,且副表跟主表都会独自更新。

    期望是在 es 中维护一份 mysql 的逻辑视图,因为要做搜索,所以相当于 es 中是一张大宽表。 为了不影响现有业务逻辑,不期望在代码逻辑中双写,可能走数据同步的策略(监听 binlog,做增删改 es 逻辑)

    这样的话,如何保证这两份数据的一致性,以及 mysql 更新时 es 的更新时延。大佬们有类似的经验么,望不吝赐教。

    14 条回复    2019-09-17 14:16:07 +08:00
    iluhcm
        1
    iluhcm  
       2019-09-16 14:19:43 +08:00
    mysql binlog -> kafka -> es,通过消息可以保证最终一致,无法做到强一致。
    Rush9999
        2
    Rush9999  
       2019-09-16 14:53:56 +08:00
    https://dbaplus.cn/news-11-2397-1.html
    MySQL 数据同步到 ES 中,大致总结可以分为两种方案:



    # 方案 1:监听 MySQL 的 Binlog,分析 Binlog 将数据同步到 ES 集群中。



    优点:业务与 ES 数据耦合度低,业务逻辑中不需要关心 ES 数据的写入;

    缺点:Binlog 模式只能使用 ROW 模式,且引入了新的同步服务,增加了开发量以及维护成本,也增大了 ES 同步的风险。



    # 方案 2:直接通过 ES API 将数据写入到 ES 集群中。



    优点:简洁明了,能够灵活的控制数据的写入;

    缺点:与业务耦合严重,强依赖于业务系统的写入方式。



    考虑到订单系统 ES 服务的业务特殊性,对于订单数据的实时性较高,显然监听 Binlog 的方式相当于异步同步,有可能会产生较大的延时性。且方案 1 实质上跟方案 2 类似,但又引入了新的系统,维护成本也增高。所以订单中心 ES 采用了直接通过 ES API 写入订单数据的方式,该方式简洁灵活,能够很好的满足订单中心数据同步到 ES 的需求。



    由于 ES 订单数据的同步采用的是在业务中写入的方式,当新建或更新文档发生异常时,如果重试势必会影响业务正常操作的响应时间。



    所以每次业务操作只更新一次 ES,如果发生错误或者异常,在数据库中插入一条补救任务,有 Worker 任务会实时地扫这些数据,以数据库订单数据为基准来再次更新 ES 数据。通过此种补偿机制,来保证 ES 数据与数据库订单数据的最终一致性。
    ayonel
        3
    ayonel  
    OP
       2019-09-16 15:26:35 +08:00
    @Rush9999 感谢。我们的时效性要求不是非常高,还是不希望侵入现有代码逻辑
    Raymon111111
        4
    Raymon111111  
       2019-09-16 15:29:27 +08:00
    一致性的话可以延迟检查
    ayonel
        5
    ayonel  
    OP
       2019-09-16 15:29:34 +08:00
    @iluhcm 方案大致是这样,就是不知道如何保证一致性,哪怕最终一致。假设对同一条记录的两条 binlog 消息:
    1: 增
    2: 删
    如果不做幂等消费,有可能就是先删后增;或者如果删除失败,也会导致这条记录永远存在 es 中
    iluhcm
        6
    iluhcm  
       2019-09-16 15:31:48 +08:00
    @ayonel #5 用消息就是为了保证消费的顺序以及 ack 的。
    lihongjie0209
        7
    lihongjie0209  
       2019-09-16 15:36:32 +08:00
    消息队列慢慢写
    ayonel
        8
    ayonel  
    OP
       2019-09-16 15:47:15 +08:00
    @iluhcm 感谢大佬,我再研究下消息队列的 ack
    xuanbg
        9
    xuanbg  
       2019-09-16 15:49:06 +08:00
    这真是个好问题!我们的方案是用消息队列异步更新 ES 数据,写起来比较麻烦。因为 ES 里面的数据和 MySQL 的数据结构是不一致的所以不能通过监听 Binlog 来实现。
    ayonel
        10
    ayonel  
    OP
       2019-09-16 20:34:54 +08:00
    @xuanbg 我现在的初步想法是,通过监听 binlog 的事件类型,做相应的对 ES 的操作,中间需要处理逻辑。
    promise2mm
        11
    promise2mm  
       2019-09-17 11:27:53 +08:00
    binlog 方式侵入小, 问题是会有同步延时问题,业务上能接受延时就行

    现成方案:阿里 canal
    ayonel
        12
    ayonel  
    OP
       2019-09-17 12:08:40 +08:00
    @promise2mm binlog 同步这些公司有现成的中间件,我核心关注的是如何保证数据一致。
    zeraba
        13
    zeraba  
       2019-09-17 12:46:51 +08:00 via Android
    5.6 以上开启 gtid 没有 gtid 就自己存储 binlog 的位置信息 file+pos 现成的也有很多轮子去持久化这个东西
    kiddingU
        14
    kiddingU  
       2019-09-17 14:16:07 +08:00
    go-mysql-es https://github.com/siddontang/go-mysql-elasticsearch 可以看看这个轮子,pingcap 的唐刘写的
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     2909 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 25ms UTC 13:47 PVG 21:47 LAX 06:47 JFK 09:47
    Do have faith in what you're doing.
    ubao snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86