1
Jooooooooo 2021-03-24 17:02:12 +08:00
那是很明显数据不重要, 丢一些没关系.
一般这种如果要求一定成功会用失败补偿 /延迟校验 /双通道发送之类的方法减少数据丢失的可能. |
2
joApioVVx4M4X6Rf 2021-03-24 17:04:56 +08:00
纳尼? rabbitmq 有持久化啊
|
3
vitoliu 2021-03-24 17:12:52 +08:00
写入重试,打好日志。
再写一个分时段同步 db 数据到 es 的工具。 MQ 出问题了直接调接口补数据。 |
4
WillingXyz OP @v2exblog 是发送的时候,异步发送
|
5
WillingXyz OP @Jooooooooo 怎么衡量重不重要呢?比如一些数据同步到 es 失败就搜索不到,感觉也挺重要
|
6
Jooooooooo 2021-03-24 17:21:52 +08:00
@WillingXyz 指标定义可以用是否会产生资金损失 /是否会产生客诉 /是否会对目标用户产生负面影响等方面评估, 然后做这些容灾也是需要花钱的, ROI 就得你们自己评估了. 是丢了这些数据造成的损失大, 还是做这些容灾手段付出的成本大.
|
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)则发送至告警平台人工介入 |
8
securityCoding 2021-03-24 17:50:09 +08:00
还有一种方案是 rmq 的事务消息 , 落库前发送一条事务消息 , rmq 会自动来询问注册的回调 listener 消息是否可以发送 , 事务状态一直是 waitting 的话 rmq 会周期性的来回调 listener ,只是时间周期是固定的
|
9
timethinker 2021-03-24 18:01:38 +08:00
一般涉及到消息发送都基本上是异步流程了,建议在一个本地事务中将需要发送的消息写入到一个“消息发送表”内,另一个线程定时扫描这张表,然后将消息发送出去,发送完成就可以删掉或标记为已处理,发送失败记录失败次数和异常等原因。
|
10
wmhack 2021-03-24 20:25:39 +08:00
@securityCoding 2. 后面两步,是不是可以简化成:只记录日志,日志里包含重试消息的 body,然后用钉钉告警出来呢?
|
11
securityCoding 2021-03-24 20:35:41 +08:00
@wmhack 可以的 , 无非是自动与手动的区别.
我的场景是电商订单 , 尽可能的希望这种异常场景程序能自愈而不是直接人工介入 |
12
misaka19000 2021-03-24 20:50:00 +08:00
同步失败重做啊
|
13
tedzhou1221 2021-03-24 20:50:22 +08:00
上市公司项目,MQ 都只用来发短信、微信。服务调用基本都是同步。这样都能活得下出,消息可不可靠不影响,哈哈
|
14
neoblackcap 2021-03-24 23:05:40 +08:00
mq 不能保证其可靠性,但是这消息又很重要,那么就应该实现分布式事务。
一步出错就回滚,日志记录错误。然后慢慢修正错误提高性能 |
15
xiang0818 2021-03-24 23:18:32 +08:00
消息重试了解下
|
16
Ptu2sha 2021-03-24 23:24:28 +08:00
只要的肯定加确认和重试 都失败进入日志 后期处理
|
17
xuanbg 2021-03-25 03:19:30 +08:00
死信队列用起来
|
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 好了就处理好的那个。
|
19
fuxiuyin 2021-03-25 03:54:58 +08:00 via iPhone
@fuxiuyin 发出去了发现最后那个少了一点,要求接收端给回应的话,就是两边互发 promise 。发送端发个 promise,接收端收到以后回个结果的 promise,然后两边异步等 promise,balanala 。
|
20
codingadog 2021-03-25 06:39:18 +08:00 via Android
|
21
codingadog 2021-03-25 06:39:56 +08:00 via Android
@v2exblog 不好意思,错误地 @了
|
22
dbpe 2021-03-25 09:16:28 +08:00
说到补偿..我想知道..有没有一种可能(其实就是业务 Bug).就是 mq 端认为消息已达,但实际上数据库并没有变更...这种如何发现?(我听闻大公司有类似数据校验组?那么是不是类似这种去做的?
|
23
supermoonie 2021-03-25 09:39:03 +08:00 via iPhone
先入库,状态为待处理,生产者发送消息,消费者处理消息,消费者远程调用更新状态为已完成。定时任务查询未完成记录,并再次发送消息。消费者做幂等处理。
|
24
winnie2012 2021-03-25 10:27:16 +08:00
同步写消息表,异步读取 消息表 binlog,做消息消费。
|
25
CoderGeek 2021-03-25 11:39:12 +08:00
我们都是事务消息
|
26
brucedone 2021-03-25 11:48:57 +08:00 2
生产者 -> 超时重传,最大重试次数
消息队列 -> 多点节,多副本,高可用 消费者 -> ACK,使用唯一 ID,另外是消息幂等性 |
27
demobin 2021-03-25 14:07:44 +08:00
durable
retry confirm mannual ack db batch job |
28
xxxyh 2021-03-25 15:20:30 +08:00
26 楼加 1,生产者:重试加 ack,broker:多副本,消费者:db 持久化位移之后提交位移,如果是写 es 的话只保证不丢,不保证不重复,如果消费者的任务是写 mysql 的话,和位移的持久化放到一个事务,可以保证恰好一次
|
29
xx6412223 2021-03-25 15:25:27 +08:00
把 mq 当作一个服务,调用失败的话就报错呗,
mq 有死信队列 消费者发送 ack 。 够用了 |
30
bthulu 2021-03-25 16:10:45 +08:00
@xx6412223 这样不行的, 调用成功并不是代表真的成功了. 死信队列局限性很大的, 大多数网络异常, 死信队列都无能为力. 最简单的, 你先死循环发数据, 然后本地网络适配器里禁用网络再启用网络, 你会发现禁用瞬间, rabbitmq 并不能立即发现网络失效, 数据能照常发送. 要过一段时间, 通常是十几秒到几十秒, rabbitmq 才发现网络失效抛出异常. 那么这个十几秒到几十秒之间发出去的数据, rabbitmq 客户端认为发出去了, 而服务器并不会收到, 如何进死信队列?
对 rabbitmq 来说, 只有服务端 ack 了的才算成功了, 服务 nack 的算发送失败, 还有一种情况是, 长时间既未收到服务端 ack 信号又未收到服务端 nack 信号, 这种数据有可能发送成功了, 也有可能发送失败了. 如果要求一条不丢, 那么在收到服务器 ack 信号时标记这条数据发出去了. 再新起一个守护线程, 定期将已发送但尚未未标记发送成功的数据重发一次. |
31
useben 2021-03-25 21:54:17 +08:00
一句话总结
重试+重试队列+mq 持久化+ack+confirm+幂等性+打 log+定时补偿 |
32
cheng6563 2021-03-26 10:03:39 +08:00
发出去的同时往 db 存一个
|