MQ随记(2)

2019-02-14  本文已影响0人  喧嚣城外
如何保证消息不会被重复消费(保证消息消费时的幂等性)
kafka

遇到的坑:
消费者不是消费完就提交offset的,而是定时定期提交。
消费者如果在准备提交offset时,但是还未提交,消费者被重启了,那么此时消费过的数据offset还没有提交,kafka也就不知道已经消费了哪些条消息,一旦消费者启动,就会重复消费。

幂等性:通俗的讲,就是一个数据或者一个请求,重复几次,确保对应数据不回改变,不能出错。

保证幂等性结合业务来思考,以下是几个思路:


如何确保消息可靠性传输(如何处理消息丢失问题)?
rabbitmq

1.写消息过程,消息都没到rabbitmq在网络传输过程中就丢失了,或者消息到了rabbitmq,但是内部出现错误没有保存下来。
2.rabbitmq接收到消息后先暂时存在内存中,结果消息还没有被消费,rabbitmq自己挂掉了,导致内存中的消息搞丢。
3.消费者消费到这个消息,还没有来得及处理,自己挂掉了,但是rabbitmq以为这个消息已经被消费掉了。

解决写消息丢失:

channel.confirm;
//发送消息
//回调接口
public void ack(String message){
}
public void nack(String massage){
    //重新发送
}

rabbitmq生产者这块如果要保证消息不丢失,一般是用connfirm机制,异步的模式,你发送消息后不回阻塞,直接发下一个,吞吐量高一些。

解决mq自身丢失问题:
开启消息持久化。

解决消费者丢失问题:
关闭autoAck机制,每次自己确定处理完再发送ack给rabbitmq。

kafka

消费端弄丢数据:
唯一可能导致消费者弄丢数据的情况,也就是说,你那个消费到了这个消息,然后消费者那边自动提交了offset,让kafka以为已经消费好了这个消息,但是在准备处理时,消费端挂了,此时消息丢失。
解决方法:kafka会自动提交offset,那么只要关闭自动提交offset,在处理完后自己手动提交offset,就可以保证数据不丢失,但是此时还是会遇到重复消费问题,自己保证幂等性即可。

kafka弄丢了数据:
kafka某个broker宕机,然后重新选举出来的partiton的leader时。如果此时其他follower刚好还有些数据没有同步,结果此时leader挂了,然后选举出某个follower成了leader,就造成数据丢失。
所以此时一般 要求设置一下 4个参数。

生产者会不会丢失数据:
如果按上述思路配置ack=all,一定不会丢失,因为leader接收到消息,所有follower都同步到了消息之后,才认为本次写入成功,如果没有满足这个条件,生产者会自动不断重试,重试无限次。


如何保证消息消费顺序正确
rabbitmq如何保证
给每个消费者开一个queue 图片02.png
kafka如何保证

写入一个partition是有顺序的,生产者在写时,可以指定一个key,比如说指定某个订单id作为key,这个订单相关数据一定会被分发到一个partition中去。
partition只能被一个消费者消费。
可确保消费者以顺序取出。
但是可能会出现问题:
消费者内部多线程,消费者内部可能造成顺序不一致。


图片02.png
如何解决消息队列的延时以及过期失效时间?消息队列满了以后怎么处理?有几百万消息持续积压了几个小时,怎么解决?
如果消息积压了几百万或者上千万数据,及时消费者恢复了,也需要大概1小时时间才可以恢复过来。

一般这个时候就需要紧急扩容了,具体操作及思路如下:

第二个坑(设置消息过期时间)

等过了高峰期后,这个时候开始写程序,将丢失的那批数据,写一个临时程序,一点点查出来,然后重新灌入mq里,进行补偿。

第三个坑(mq快满了)

如果走的方式是消息积压在mq里,那么如果你很长时间都没有处理掉,此时导致mq都快写满了,临时写程序,消费一个丢弃一个,尽快消费掉所有消息,然后写程序进行补偿。


如何设计一个消息队列的架构
上一篇下一篇

猜你喜欢

热点阅读