如何保证消息可靠性的?
如何保证消息可靠性的?
提示
题眼: 三端独立负责,强调人的重要性
消息队列的可靠性一般指两种,一个是消息本身可靠,另一个是这个中间件服务的可靠。因此,回答的时候,务必要审题,审题。
重要
参考答案:
消息的可靠性,一般都是分三个方面。首先是发送端保证已经发出,然后消息中间件负责落地并且不会因为服务挂掉导致消息丢失,最后消费端保证被正确消费。拿我们常用的 kafka 举例:
我们服务在调用 kafka 的客户端发送消息的时候,有一个 ACK 机制,一般是收到 OK 信息后,就认为消息已经成功发出去了。如果超时或者没有收到,就需要重试一下,如果重试 3 次以上,都是失败的,那么就要写一条错误日志,触发服务告警,这种一般都是很严重的线上冒烟点,需要人工排查,而且还得快。 这种方法有个问题,就是重试可能导致消息重复,需要消费端做下消息幂等。
kafka 在收到消息后,他自身有一个 ACK 配置,可以调整 副本同步 ISR,一般都是主机加部分备机确定数据落地就可以返回。然后 kafka 在这里还有一个特点,他写数据的时候用的也是 WAL 机制,只要日志写入就认为数据已经落地了。如果是集群出问题的话,kafka 还会自动选举,保证可用。
最后的话,就是我们消费的时候,需要在代码层面做好规范。我们之前有过这种问题,就是收到消息后,没有等业务处理完,就直接返回消息队列 OK,然后业务出错,消息丢失这种 BUG。所以,一般情况下,都是等业务处理完,再返回消息队列 ACK。但是这样做可能会存在一些问题,比如说业务一直报错,队列可能会出现积压,另一个是会降低消费速率,因为有的业务执行也是比较耗时的。
像这种的话,我们这边的技术老大做了一个异步的封装函数,我看过他的源码,其实就做了两件事,第一个是收到消息后,先写一个 info 日志,然后异步走业务流程,如果多次都是失败,就写入到死信队列,发告警。然后可以根据日志信息排查问题,再处理掉。
相关信息
引申:
- 此题等价于 如何保证消息不丢失的?
- 如果一直重试,陷入死循环怎么办?
