大佬们,你们公司普通业务里 mq 有做消息可靠性吗?怎么做的 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
请不要在回答技术问题时复制粘贴 AI 生成的内容
WillingXyz
V2EX    程序员

大佬们,你们公司普通业务里 mq 有做消息可靠性吗?怎么做的

  •  
  •   WillingXyz 2021-03-24 16:56:51 +08:00 7319 次点击
    这是一个创建于 1666 天前的主题,其中的信息可能已经有所发展或是发生改变。
    普通业务 比如 修改内容后发送 mq 同步到 es 。
    经历的公司里都不管消息是否发送成功,失败就失败了
    32 条回复    2021-03-26 10:03:39 +08:00
    Jooooooooo
        1
    Jooooooooo  
       2021-03-24 17:02:12 +08:00
    那是很明显数据不重要, 丢一些没关系.

    一般这种如果要求一定成功会用失败补偿 /延迟校验 /双通道发送之类的方法减少数据丢失的可能.
    joApioVVx4M4X6Rf
        2
    joApioVVx4M4X6Rf  
       2021-03-24 17:04:56 +08:00
    纳尼? rabbitmq 有持久化啊
    vitoliu
        3
    vitoliu  
       2021-03-24 17:12:52 +08:00
    写入重试,打好日志。
    再写一个分时段同步 db 数据到 es 的工具。
    MQ 出问题了直接调接口补数据。
    WillingXyz
        4
    WillingXyz  
    OP
       2021-03-24 17:15:23 +08:00
    @v2exblog 是发送的时候,异步发送
    WillingXyz
        5
    WillingXyz  
    OP
       2021-03-24 17:16:57 +08:00
    @Jooooooooo 怎么衡量重不重要呢?比如一些数据同步到 es 失败就搜索不到,感觉也挺重要
    Jooooooooo
        6
    Jooooooooo  
       2021-03-24 17:21:52 +08:00
    @WillingXyz 指标定义可以用是否会产生资金损失 /是否会产生客诉 /是否会对目标用户产生负面影响等方面评估, 然后做这些容灾也是需要花钱的, ROI 就得你们自己评估了. 是丢了这些数据造成的损失大, 还是做这些容灾手段付出的成本大.
    securityCoding
        7
    securityCoding  
       2021-03-24 17:45:01 +08:00   5
    有做的,订单类业务 mq 丢失后续业务流程全部挂了 ,说说我用的方案吧
    rocketmq 用的比较多,拿 rocketmq 来说吧
    1. producer client 设置自动重试 3 次,注意发送重试是立即重试(循环),默认 timeOut 是 3 秒
    2. producer.send(Message msg,SendCallback sendCallback) 这种是异步发送,但是有 callback 业务可以实时感知发送结果
    2. callback 记录日志 ,并捕捉 callback 异常消息持久化至 db(拼接好完整的重试消息 body)
    3. 定时器每隔 5 秒扫描一遍待重试的消息,超过最大次数(3)则发送至告警平台人工介入
    securityCoding
        8
    securityCoding  
       2021-03-24 17:50:09 +08:00
    还有一种方案是 rmq 的事务消息 , 落库前发送一条事务消息 , rmq 会自动来询问注册的回调 listener 消息是否可以发送 , 事务状态一直是 waitting 的话 rmq 会周期性的来回调 listener ,只是时间周期是固定的
    timethinker
        9
    timethinker  
       2021-03-24 18:01:38 +08:00
    一般涉及到消息发送都基本上是异步流程了,建议在一个本地事务中将需要发送的消息写入到一个“消息发送表”内,另一个线程定时扫描这张表,然后将消息发送出去,发送完成就可以删掉或标记为已处理,发送失败记录失败次数和异常等原因。
    wmhack
        10
    wmhack  
       2021-03-24 20:25:39 +08:00
    @securityCoding 2. 后面两步,是不是可以简化成:只记录日志,日志里包含重试消息的 body,然后用钉钉告警出来呢?
    securityCoding
        11
    securityCoding  
       2021-03-24 20:35:41 +08:00
    @wmhack 可以的 , 无非是自动与手动的区别.
    我的场景是电商订单 , 尽可能的希望这种异常场景程序能自愈而不是直接人工介入
    misaka19000
        12
    misaka19000  
       2021-03-24 20:50:00 +08:00
    同步失败重做啊
    tedzhou1221
        13
    tedzhou1221  
       2021-03-24 20:50:22 +08:00
    上市公司项目,MQ 都只用来发短信、微信。服务调用基本都是同步。这样都能活得下出,消息可不可靠不影响,哈哈
    neoblackcap
        14
    neobackcap  
       2021-03-24 23:05:40 +08:00
    mq 不能保证其可靠性,但是这消息又很重要,那么就应该实现分布式事务。
    一步出错就回滚,日志记录错误。然后慢慢修正错误提高性能
    xiang0818
        15
    xiang0818  
       2021-03-24 23:18:32 +08:00
    消息重试了解下
    Ptu2sha
        16
    Ptu2sha  
       2021-03-24 23:24:28 +08:00
    只要的肯定加确认和重试 都失败进入日志 后期处理
    xuanbg
        17
    xuanbg  
       2021-03-25 03:19:30 +08:00
    死信队列用起来
    fuxiuyin
        18
    fuxiuyin  
       2021-03-25 03:48:34 +08:00 via iPhone
    我觉得这个问题应该分成三个,一个是发送者发送到消息队列可不可靠,一个是消息队列发送给接收者可不可靠,第三个是接收者接收了之后处理的可不可靠。第二个问题不用担心,可以简单相信消息队列保证了“至少一次”。第一个问题简单解决就是发送者先写一个数据库,然后一个线程发,或者发送者弄成全异步的,通过 Task 来 track 一条消息。第三个问题就直接接收者全处理完了再给 mq 回 ack,或者接收者先写个 db 回个 ack 再慢慢处理。这个问题的重点在于不要让消息 lose track,一直能够 track 到就不怕细小的问题,因为随时可以有人来查看恢复。比如,发送流程都很好,接收者成功收到以后挂了,然后消息丢了就不好办了。mq 是一个异步和解耦组件,异步了就要在发送者和接收者都保存一些信息。同步状态下只发送端保存,接收端挂了就挂了,发送端保存了还知道接收者处理哪条消息的时候挂了,于是重来就行了。多说一句,其实点对点的发送接收做异步的话也不一定非得用 mq 啦,可以学异步 rpc 那样发 promise 。发送端发个 promise 就走,接收端把 promise 放到监听对列。发送端啥时候闲了,或者 promise 太多了,或者其他线程,去发 promise 的实际内容,接收端等哪个 promise 好了就处理好的那个。
    fuxiuyin
        19
    fuxiuyin  
       2021-03-25 03:54:58 +08:00 via iPhone
    @fuxiuyin 发出去了发现最后那个少了一点,要求接收端给回应的话,就是两边互发 promise 。发送端发个 promise,接收端收到以后回个结果的 promise,然后两边异步等 promise,balanala 。
    Duolingo
        20
    Duolingo  
       2021-03-25 06:39:18 +08:00 via Android
    Duolingo
        21
    Duolingo  
       2021-03-25 06:39:56 +08:00 via Android
    @v2exblog 不好意思,错误地 @了
    dbpe
        22
    dbpe  
       2021-03-25 09:16:28 +08:00
    说到补偿..我想知道..有没有一种可能(其实就是业务 Bug).就是 mq 端认为消息已达,但实际上数据库并没有变更...这种如何发现?(我听闻大公司有类似数据校验组?那么是不是类似这种去做的?
    supermoonie
        23
    supermoonie  
       2021-03-25 09:39:03 +08:00 via iPhone
    先入库,状态为待处理,生产者发送消息,消费者处理消息,消费者远程调用更新状态为已完成。定时任务查询未完成记录,并再次发送消息。消费者做幂等处理。
    E2gCaBAT5I87sw1M
        24
    E2gCaBAT5I87sw1M  
       2021-03-25 10:27:16 +08:00
    同步写消息表,异步读取 消息表 binlog,做消息消费。
    CoderGeek
        25
    CoderGeek  
       2021-03-25 11:39:12 +08:00
    我们都是事务消息
    brucedone
        26
    brucedone  
       2021-03-25 11:48:57 +08:00   2
    生产者 -> 超时重传,最大重试次数

    消息队列 -> 多点节,多副本,高可用

    消费者 -> ACK,使用唯一 ID,另外是消息幂等性
    demobin
        27
    demobin  
       2021-03-25 14:07:44 +08:00
    durable
    retry
    confirm
    mannual ack
    db
    batch job
    xxxyh
        28
    xxxyh  
       2021-03-25 15:20:30 +08:00
    26 楼加 1,生产者:重试加 ack,broker:多副本,消费者:db 持久化位移之后提交位移,如果是写 es 的话只保证不丢,不保证不重复,如果消费者的任务是写 mysql 的话,和位移的持久化放到一个事务,可以保证恰好一次
    xx6412223
        29
    xx6412223  
       2021-03-25 15:25:27 +08:00
    把 mq 当作一个服务,调用失败的话就报错呗,
    mq 有死信队列
    消费者发送 ack 。

    够用了
    bthulu
        30
    bthulu  
       2021-03-25 16:10:45 +08:00
    @xx6412223 这样不行的, 调用成功并不是代表真的成功了. 死信队列局限性很大的, 大多数网络异常, 死信队列都无能为力. 最简单的, 你先死循环发数据, 然后本地网络适配器里禁用网络再启用网络, 你会发现禁用瞬间, rabbitmq 并不能立即发现网络失效, 数据能照常发送. 要过一段时间, 通常是十几秒到几十秒, rabbitmq 才发现网络失效抛出异常. 那么这个十几秒到几十秒之间发出去的数据, rabbitmq 客户端认为发出去了, 而服务器并不会收到, 如何进死信队列?
    对 rabbitmq 来说, 只有服务端 ack 了的才算成功了, 服务 nack 的算发送失败,
    还有一种情况是, 长时间既未收到服务端 ack 信号又未收到服务端 nack 信号, 这种数据有可能发送成功了, 也有可能发送失败了.
    如果要求一条不丢, 那么在收到服务器 ack 信号时标记这条数据发出去了. 再新起一个守护线程, 定期将已发送但尚未未标记发送成功的数据重发一次.
    useben
        31
    useben  
       2021-03-25 21:54:17 +08:00
    一句话总结
    重试+重试队列+mq 持久化+ack+confirm+幂等性+打 log+定时补偿
    cheng6563
        32
    cheng6563  
       2021-03-26 10:03:39 +08:00
    发出去的同时往 db 存一个
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     5497 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 37ms UTC 06:35 PVG 14:35 LAX 23:35 JFK 02:35
    Do have faith in what you're doing.
    ubao msn 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