消息队列怎么处理消息丢失问题

rabbitmq处理办法

1,生产者丢失数据

生产者由于网络问题,数据刚发出去就断掉了

解决办法:

1),开启tabbitmq事务,如果消息没有被rabbitmq接收到就回滚事务,继续重试,否则就提交事务,但这种效率较慢

2),开启confirm模式,这是每个消息都会被分配一个id,如果消息被rabbitmq成功接收,会返回ack消息,如果消息没有被rabbitmq处理,会回调一个nack接口告诉你处理失败,然后你可以重试。这种方式优点是异步的,发送完这个消息后可以继续发送下一个消息;

2,rabbitmq丢失数据

为了防止rabbitmq丢失数据,必须开通rabbitmq数据持久化,将数据写入磁盘,这样哪怕rabbitmq宕机了,重启后也能读取磁盘内的数据;

持久化方式:

1),第一个是创建queue的时候将其设置为持久化的,这样就可以保证rabbitmq持久化queue的元数据,但是不会持久化queue里的数据

2),第二个是发送消息的时候将消息的deliveryMode设置为2,就是将消息设置为持久化的,此时rabbitmq就会将消息持久化到磁盘上去。必须要同时设置这两个持久化才行,rabbitmq哪怕是挂了,再次重启,也会从磁盘上重启恢复queue,恢复这个queue里的数据。

注意:持久化必须和confirm结合起来使用,数据必须被写入磁盘后才会返回给生产这ack,否则如果数据还没持久化rabbitmq就挂了,还是会丢失消息;

3,消费者丢失数据

消费者刚刚接收消息,但还没来得及处理就挂了,而rabbitmq认为你已经消费了,那消息就丢失了

解决办法:

1),调用rabbitmq提供的ack机制(开启重试默认3次),并把ack调为手动调用,就是消费者每次消费消息成功会去调用一个api接口,返回rabbitmq   一个ack消息,通知他消费完成,如果没有返回ack,rabbitmq会认为这个消息还没被消费,会继续分配给下个消费者消费;

 

kafuka处理办法

1,生产者丢失数据

设置了ack=all,一定不会丢,要求是,你的leader接收到消息,所有的follower都同步到了消息之后,才认为本次写成功了。如果没满足这个条件,生产者会自动不断的重试,重试无限次。

2,rabbitmq丢失数据

 比较常见的一个场景,就是kafka某个broker宕机,然后重新选举partiton的leader时。大家想想,要是此时其他的follower刚好还有些数据没有同步,结果此时leader挂了,然后选举某个follower成leader之后,他不就少了一些数据?这就丢了一些数据啊。

所以此时一般是要求起码设置如下4个参数:

1.给这个topic设置replication.factor参数:这个值必须大于1,要求每个partition必须有至少2个副本

2.在kafka服务端设置min.insync.replicas参数:这个值必须大于1,这个是要求一个leader至少感知到有至少一个follower还跟自己保持联系,没掉队,这样才能确保leader挂了还有一个follower吧

3.在producer端设置acks=all:这个是要求每条数据,必须是写入所有replica之后,才能认为是写成功了

4.在producer端设置retries=MAX(很大很大很大的一个值,无限次重试的意思):这个是要求一旦写入失败,就无限重试,卡在这里了

  生产环境就按照上述要求配置的,这样配置之后,至少在kafka broker端就可以保证在leader所在broker发生故障,进行leader切换时,数据不会丢失

3,消费者丢失数据

唯一可能导致消费者弄丢数据的情况,就是说,你那个消费到了这个消息,然后消费者那边自动提交了offset,让kafka以为你已经消费好了这个消息,其实你刚准备处理这个消息,你还没处理,你自己就挂了,此时这条消息就丢咯。

  大家都知道kafka会自动提交offset,那么只要关闭自动提交offset,在处理完之后自己手动提交offset,就可以保证数据不会丢。但是此时确实还是会重复消费,比如你刚处理完,还没提交offset,结果自己挂了,此时肯定会重复消费一次,自己保证幂等性就好了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章