队列服务的ACK机制
-
Kafka
- 自动提交偏移量(每隔5s提交一次)
- 主动提交偏移量
-
Rabbitmq
- 默认支持ACK
- 没有超时时间,只有断开连接,才会判定该消息未收到ACK确认
- 分为自动ACK(默认收到ACK)和手动ACK模式(需要主动提交ACK)
- 方法一:channel.basicAck(long deliveryTag, boolean multiple)
如果消费者没发送ACK,没有超时限制,rabbitmq也不会重复投递,只有消费者的 TCP 连
接 或者 channel 关闭了,rabbitmq才会重复投递!
方法二:channel.basicNack(long deliveryTag, boolean multiple, boolean requeue)
代表消费者拒绝一条或者多条消息。basicNack 算是 basicReject 的一个扩展,因为
basicReject 不能一次拒绝多条消息。
方法三:channel.basicReject(long deliveryTag, boolean requeue)
代表消费者拒绝这条消息,语义上表示消费者没有处理当前消息。
对于 basicNack 和 basicReject ,如果参数 boolean requeue 传入 false,消息还是会从队
列里面删除。 - 参数:
deliveryTag: 消息体上会带上delivery tag,这个值会唯一标识本次投递,在同一通道上,此值是唯一的,消费者端在应答消息时,带上此参数,告诉RabbitMQ某次投递已经正确应答
multiple: 是否使用批量确认,如果此属性为true,则消息标签小于当前deliveryTag的所有消息都会被主动积极确认,不了解此属性最好使用false。
requeue :是否重新入队,如果此属性为true,消息会被重新放置回去对应队列(如果可能的话,会放回到原来的位置),如果此属性为false,消息直接被丢弃。
属性requeue如果设置为true,需要谨慎设计程序的逻辑,否则很有可能导致消息一直重复消费失败并且重复重新入队,表现为消费者线程出现死循环逻辑,耗尽服务器CPU资源。
-
Redis
- 每个Stream都可以挂多个消费组,每个消费组会有个游标last_delivered_id在Stream数组之上往前移动,表示当前消费组已经消费到哪条消息了;每个消费组(Consumer Group)的状态都是独立的,相互不受影响。也就是说同一份Stream内部的消息会被每个消费组都消费到
- 同一个消费组(Consumer Group)可以挂接多个消费者(Consumer),这些消费者之间是竞争关系,任意一个消费者读取了消息都会使游标last_delivered_id往前移动。每个消费者者有一个组内唯一名称。
- 消费者(Consumer)内部会有个状态变量pending_ids,它记录了当前已经被客户端读取的消息,但是还没有ack。如果客户端没有ack,这个变量里面的消息ID会越来越多,一旦某个消息被ack,它就开始减少。
网友评论