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

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

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

    背景:

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

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

    如果没理解错的话,这不是支持顺序消息的 mq 能解决的问题么,主流 mq 应该都支持?根据业务主键决定投递到哪个队列,一个操作序列内局部有序。如果这都觉得性能差( queue 和 consumer 足够多还能差?),那我觉得问题是需求带来的,不是顺序消息本身带来的。
    ily433664
        16
    ily433664  
       35 天前   ❤️ 1
    按照你的描述至少同一个商品只能是单线程执行,否则就算是按照顺序消费了,两个服务同时操作一个商品也可能有问题
    提供一个思路,根据算法(比如 hash ,或者自定义)计算商品 id ,再根据结果发送到对应服务进行消费,保证同一个商品只在一个服务,这样就可以保证顺序了
    blessingcr
        17
    blessingcr  
    OP
       35 天前
    @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
       35 天前
    @ily433664 这个消费者的同一个服务下多节点有办法保证顺序吗?这个服务起多少个节点由 K8S 控制,非人为控制的
    sujin190
        19
    sujin190  
       35 天前   ❤️ 1
    @blessingcr #17 吞吐、延时和一致性,区块链这货一致性完全就是靠牺牲吞吐和延时来得到的,而且并不能达到保持时序的作用,区块链的逻辑完全就是按照收到消息的顺序提交,然后谁得到的确认多谁有限,没说保证消息时序

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

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

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

    算了跳过性能问题,“一个 partition 只能对应一个消费者”这难道不是默认行为么? partition 和 consumer 多对一,跟是不是顺序消息没有关系,感觉你对 mq 有深刻的误解。。(当然也可能是我没懂你的顾虑)
    siweipancc
        22
    siweipancc  
       35 天前 via iPhone
    你这个队列解决不了,除非你规定一个序列跟计数器,计数不对扔回去队列
    litchinn
        23
    litchinn  
       34 天前
    Aeron ,但是门槛有点高
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2635 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 15:35 · PVG 23:35 · LAX 07:35 · JFK 10:35
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.