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,结果自己挂了,此时肯定会重复消费一次,自己保证幂等性就好了。