orderly:
1、SUSPEND_CURRENT_QUEUE_A_MOMENT:在本地重試,先判斷重新消費次數有沒有達到最大值(consumer定義的時候傳入,不傳為Integer最大值),如果沒達到,重試次數+1,放入消費池,1秒(默認)之后再消費,
直到達到最大消費次數。發送到重試隊列(這個時候必然會進入死信隊列,因為broker收到之后拿來比較的最大消費次數,也是consumer定義的時候傳入的,是sendMessageBack方法,
用defaultMQPushConsumer.getMaxReconsumeTimes()取出來的)。所以用orderly消費,需要特別注意不要無限制重試的問題
2、上面討論的是每批取出的消息數量是1的情況,如果每批取出數量大於1,SUSPEND_CURRENT_QUEUE_A_MOMENT這個狀態代表的是當前批次的所有消息消費不成功,達到最大重試次數后,發送回重試隊列,如果其中有一條沒有發送成功,整批消息本地重試,
這種設計在極端情況下,也是沒辦法保證消息的有序性的。
concurrently:
3、在返回值是CONSUME_SUCCESS的時候,廣播模式是不管消費成功與否的,集群模式下,一批消息中,可以在context中,標記消費成功到第幾個(ackIndex,RECONSUME_LATER的ackIndex為-1,意味着所有都是失敗的),
之后的就是消費失敗的,這些失敗的,如果能發送回重試隊列,也視為消費成功(重試次數會+1),否則就提交到線程池中,5秒(注意這里和orderly不同)后再消費。至於offstore中確認的offset,比如1-6條消息,
消費了1、2、3、5,offset就是3,連續的最大值。但是pullResult中的,會是7,往后面拉取。還要注意的是,這里發回給重試隊列,不是用的orderly的send方法,而是consumerSendMessageBack方法,
這個方法里會自定義最大重試次數為16,所以這個時候如果一直消費不成功,是不會像orderly默認的那樣,無限制的消費的。
4、之所以可以延遲消費,是因為使用了delayTimeLevel這個屬性,如果message的property這個標志大於0的話,broker收到消息,會放到RMQ_SYS_SCHEDULE_TOPIC這個topic中,ScheduleMessageService
定時取出,然后重新putMessage,放入正確topic--messageQueue中
5、上面討論的,1-6中,1-3連續消費成功(或者成功發送回重試隊列),offset標記為3,先存在本地,再同步到遠程關聯到隊列id+consumerGroup中,如果遇到20秒一次的rebalance,會從4重新拉取。所以這也是重復消費的一個原因,可見重復消費是無處不在的。