• 从解决一个精卫数据同步问题想到的


    今天,同事武杨发现使用精卫做一个商品排期表的数据同步有问题,问题表现在重新排期的商品在一个终搜查询系统里面查不到记录了。

    1、分析精卫中间件的数据同步机制,它是分析mysql binlog ,解析成RowChangeEvent以后,包装成消息通过消息中间件Meta发送消息到消息网关

    MetaServer,然后再由消息订阅者消费消息,解析消息中的RowChangeEvent以后,同步到搜索系统的。

    2、而从业务逻辑上看,排期操作是先逻辑删除旧的排期记录,再插入一条新的排期记录,update和insert是在一个事务的。 示意如下:

    set autocommit =0 ;

    #这条update操作因为有 KEY `idx_iod_jid` (`ju_id`,`is_deleted`,`online_end_time`) 这个索引的存在保证了A商品的排期不会影响到B商品,

    #即采用了行锁。

    update item_online_detail set is_deleted=1 where is_deleted=0 and ju_id in (?)

    insert into item_online_detail (?,?,...,?)

    commit; 

    而武杨查看日志,发现insert 和update操作有乱序 。造成插入的记录,被错误的delete了。

    3、进一步分析精卫中间件,结合源码发现精卫在提取binlog(DbExtractor) 和消费binlog时(HdfsApplier),可以配置多线程,而精卫通过把一行记录hash到一个线程,来保证一行记录的处理不会乱序。而消息中间件Meta,则在消息发送时一个线程的消息发送到一个分区,消息订阅时一个分组中的一台机器负责一个分区的消息,来保证顺序。

    最后发现问题是在于在数据提取时(DbExtractor)配置了多线程,而对记录hash到binlog提取线程的操作使用了item_online_detail表的id,而不是ju_id,

    而每次排期操作的id是会变的,这就导致对一个ju_id的操作会交给不同的线程处理而导致乱序。而且武杨在快速多次对同一商品进行排期时重现了这一问题。

    总结原因:1、可能我们对系统的压力测试还要做充分一些,才能发现这种问题。2、对中间件的使用还要更慎重,少踩雷。 

  • 相关阅读:
    C++内存管理
    多线程和多进程的区别(C++)
    如何用C语言封装 C++的类,在 C里面使用
    C/C++将一个整型数组拼接成一个字符串
    C代码中如何调用C++ C++中如何调用C
    Application对象的使用-数据传递以及内存泄漏
    《鸟哥的Linux私房菜》读书笔记二
    《鸟哥的Linux私房菜》读书笔记一
    greenDaoMaster的学习研究
    Handler 引起的内存泄露
  • 原文地址:https://www.cnblogs.com/dongqingswt/p/3095974.html
Copyright © 2020-2023  润新知