有一个消息同步的问题请教各位 dalao - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
请不要在回答技术问题时复制粘贴 AI 生成的内容
blessingcr
V2EX    程序员

有一个消息同步的问题请教各位 dalao

  •  
  •   blessingcr 325 天前 1975 次点击
    这是一个创建于 325 天前的主题,其中的信息可能已经有所发展或是发生改变。

    背景:

    • A 系统是一个面向用户的 saas 系统,用户的所有操作都会在 A 系统上操作。
    • B 系统是一个独立的系统,A 系统的几乎所有核心操作都需要转发到 B 系统,等 B 系统通过以后,再重新下发到 A 系统做其他操作。

    目前存在问题:

      1. AB 系统通信使用 HTTPS, 有时会有多个消息,有相对应的顺序关系,比如有一个商品上架请求,再有一个商品库存变更请求,如果 B 系统下发给 A 系统时,A 先收到了库存变更,再收到上架,第一个库存变更就会失败。
      1. 虽然通信使用 HTTPS , 但是其实很多操作都是 A 系统的 MQ 处理后,HTTPS 到 B 系统,B 系统放 MQ ,然后 B 系统处理,即便业务中先调用的接口也不一定 B 系统先收到。
      1. 如果 A 系统消费失败某个消息,不好重试。
      1. A 系统是一个 saas 系统,每个租户都会收到一次 B 系统给他发的信息(因为后期考虑独立化部署,B 系统都发给每一个租户),压力比较大

    思考的解决方案:

      1. 一个是考虑用区块链,B 系统每次把内容丢到链上,A 系统慢慢消费,这样顺序可以保证,但是如果不用智能合约的话这个开发成本很高,如果用的话我司没有非常专业的合约开发,我这种半吊子怕到时生产有问题解决不了。
      1. 第二种就是考虑直接 mq 通信,但是这样其实也没有解决消息先后的问题,两个系统都是微服务,除非 mq 强制顺序,但这样性能过差

    想问问各位 dalao 有没有合适的解决方案,或者有什么中间件云服务能解决此类问题,thk~

    23 条回复    2024-11-22 13:24:44 +08:00
    codegenerator
        1
    codegenerator  
       325 天前   1
    干掉 b
    chen11
        2
    chen11  
       325 天前
    用 MQ 不能保证消息的顺序性?为啥
    giao123
        3
    giao123  
       325 天前   1
    用长连接,B 处理完再返回给 A ,A 才能发下一个
    bcllemon
        4
    bcllemon  
       325 天前   1
    MQ 单一消费者, 根据一定的业务规则分片, 保证针对一个业务规则的数据是串行的
    blessingcr
        5
    blessingcr  
    OP
       325 天前
    @codegenerator 干掉我比较容易 QAQ
    blessingcr
        6
    blssingcr  
    OP
       325 天前
    @bcllemon 性能过差了 QAQ
    blessingcr
        7
    blessingcr  
    OP
       325 天前
    @giao123 两个系统都是微服务架构,长链接这不好吧
    bubble21
        8
    bubble21  
       325 天前   1
    没必要上链,代价太大,保证顺序可以用 redis ,或者自己单独维护一个有序队列(C 写一个,性能也不差)
    blessingcr
        9
    blessingcr  
    OP
       325 天前
    @chen11 因为 mq 真不能保证顺序,无论生产顺序和消费顺序我们都不能保证
    murmur
        10
    murmur  
       325 天前   1
    不要考虑区块链,区块链是比集群更大的冗余,目前看区块链解决不了任何国内的合法问题
    helone
        11
    helone  
       325 天前   1
    我们之前遇到过下发消息给移动端有点类似

    集群也是多台机器同时消费 MQ 再下发给移动端的,移动端接收可能乱序的问题,只是在消息体里加一个 step 控制顺序,移动端每次执行时判断是否大于上次的 step ,如果小于就默认忽略,但是我们的业务场景可以忽略前面的指令
    crysislinux
        12
    crysislinux  
       325 天前 via Android   1
    消息在 A 的 mq 里是有序的,那么 A
    在处理消息之前就推到 B 的 mq 里,消息内容可以是只要 id ,那么在 B 里也是同样的顺序,A 处理完之后就发请求到 B ,B 把结果写到数据库。B 在处理 mq 的消息的时候就去读库查结果,要是当前消息还没结果,就停着等。
    8355
        13
    8355  
       325 天前   1
    kafka 分区解决排序问题?
    sngxx
        14
    sngxx  
       325 天前   1
    4L 的方案可以啊,你不是 A 、B 内部本来就用到了 mq 么,怎么再加个 mq 就性能不够了
    aarontian
        15
    aarontian  
       325 天前   1
    不符合中文语法和表达习惯的语句实在有点多,理解起来有点困难。。

    如果没理解错的话,这不是支持顺序消息的 mq 能解决的问题么,主流 mq 应该都支持?根据业务主键决定投递到哪个队列,一个操作序列内局部有序。如果这都觉得性能差( queue 和 consumer 足够多还能差?),那我觉得问题是需求带来的,不是顺序消息本身带来的。
    lovelive1024
        16
    lovelive1024  
       325 天前   1
    按照你的描述至少同一个商品只能是单线程执行,否则就算是按照顺序消费了,两个服务同时操作一个商品也可能有问题
    提供一个思路,根据算法(比如 hash ,或者自定义)计算商品 id ,再根据结果发送到对应服务进行消费,保证同一个商品只在一个服务,这样就可以保证顺序了
    blessingcr
        17
    blessingcr  
    OP
       325 天前
    @helone 是个好方法,但我们的消息不能丢 QAQ
    @murmur Y? 因为我把区块链理解为一本公开的账本,大家按照同样逻辑操作到同样高度的时候,保证了数据的一致和可靠,能辛苦解答一下吗

    @sngxx 这个单一消费者性能过差了,如果不是单一消费者,服务多节点的时候,假设系统 B 可以做到 mq 的顺序,他保证了 mq 内消息的顺序,但是因为 B 系统和 A 系统用了 HTTPS 通信,所以 B 系统在消费 B 系统的 MQ 消息发送给 A 的时候,A 接收就已经没有顺序了。如果 AB 用 MQ 通信,则 A 系统在接收消息(假设消息已经由 B 系统做好了 hash 和规则分片)的时候,多个消费节点需要手动指定他需要的处理的 partition ,且这时要保证严格顺序,每一个 partition 只能有一个消费者。阿里嘎多
    @aarontian 同上,阿里嘎多
    @8355 同上,阿里嘎多
    blessingcr
        18
    blessingcr  
    OP
       325 天前
    @ily433664 这个消费者的同一个服务下多节点有办法保证顺序吗?这个服务起多少个节点由 K8S 控制,非人为控制的
    sujin190
        19
    sujin190  
       324 天前   1
    @blessingcr #17 吞吐、延时和一致性,区块链这货一致性完全就是靠牺牲吞吐和延时来得到的,而且并不能达到保持时序的作用,区块链的逻辑完全就是按照收到消的顺序提交,然后谁得到的确认多谁有限,没说保证消息时序

    kafka 分区保证时序是最容易实现的了,性能不够也可以考虑 mq 分队列啊,逻辑虽然都是一个分区或者一个队列只能有一个消费者来保证时序,但是 mq 的队列数量可以多一些

    此外也可以加分布式锁,和多线程编程解决时序一致逻辑一样,其性能损失和冲突率有关,看你这描述,saas 系统的动作都是人产生的,冲突概率应该极低才对,加锁的性能损失可以不计了,加锁也可以放在消息队列后面,那消息队列就可以不用考虑使用分区保证顺序了
    blessingcr
        20
    blessingcr  
    OP
       324 天前
    @sujin190 确认了一下,这个我们在 A 系统可以做到说他确认了再给他发下一个,因为只是同一个商品流程在某一操作过程中的上链,A 系统可以自己做分布式锁,保证某一商品在上链过程中的顺序。因为我理解链上只需要保证生产的顺序,这个比较好保证,最差情况等 ack 了再发下一个,得益于这个是个区块链,消费的顺序一定是固定的。

    kafka 分区 加分布式锁这个确实好像也可以,是一个方案,我晚点想想画画图
    aarontian
        21
    aarontian  
       324 天前
    我依然认为分 partition 能解决所谓的性能问题,不知道你们是什么样的业务解决不了,除非连每个业务 flow 的 id 都没法分,那就是场景本身的问题了。

    算了跳过性能问题,“一个 partition 只能对应一个消费者”这难道不是默认行为么? partition 和 consumer 多对一,跟是不是顺序消息没有关系,感觉你对 mq 有深刻的误解。。(当然也可能是我没懂你的顾虑)
    siweipancc
        22
    siweipancc  
       324 天前 via iPhone
    你这个队列解决不了,除非你规定一个序列跟计数器,计数不对扔回去队列
    litchinn
        23
    litchinn  
       323 天前
    Aeron ,但是门槛有点高
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     2439 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 28ms UTC 01:15 PVG 09:15 LAX 18:15 JFK 21:15
    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