一般mq能夠保證先到隊列的消息按照順序分發給消費者消費來保證順序,可是一個隊列有多個消費者消費的時候,那將失去這個保證,由於這些消息被多個線程併發的消費。可是有的時候消息按照順序處理是很重要的,那咱們該如何來保證消息的順序呢,下面將從activemq和rocketmq來看看,它們是如何來保證消息的順序問題的?咱們還能夠有別的處理方案麼?網絡
Activemq處理方案session
一、利用Activemq的高級特性:consumer之獨有消費者(exclusive consumer)併發
在ActiveMQ4.x中能夠採用Exclusive Consumer,broker會從queue中,一次發送消息給一個消費者,這樣就避免了多個消費者併發消費的問題,從而保證順序,配置以下:負載均衡
queue = new ActiveMQQueue("TEST.QUEUE?consumer.exclusive=true"); consumer = session.createConsumer(queue);
圖1
獨佔消息就是在有多個消費者同時消費一個queue時,能夠保證只有一個消費者能夠消費消息,這樣雖然保證了消息的順序問題,不過也帶來了一個問題,就是這個queue的全部消息將只會在這一個主消費者上消費,其餘消費者將閒置,達不到負載均衡分配,而實際業務咱們可能更多的是這樣的場景,好比一個訂單會發出一組順序消息,咱們只要求這一組消息是順序消費的,而訂單與訂單之間又是能夠並行消費的,不須要順序,由於順序也沒有任何意義,有沒有辦法作到呢?答案是能夠的,下面就來看看activemq的另外一個高級特性之messageGroup。分佈式
二、利用Activemq的高級特性:messageGroupsspa
Message Groups特性是一種負載均衡的機制。在一個消息被分發到consumer以前,broker首先檢查消息JMSXGroupID屬性。若是存在,那麼broker會檢查是否有某個consumer擁有這個message group。若是沒有,那麼broker會選擇一個consumer,並將它關聯到這個message group。此後,這個consumer會接收這個message group的全部消息,直到:線程
圖2
配置以下:code
bytesMessage.setStringProperty("JMSXGroupID", "constact-20100000002"); bytesMessage.setIntProperty("JMSXGroupSeq", -1);
如上圖所示,同一個queue中,擁有相同JMSXGroupID的消息將發往同一個消費者,解決順序問題,不一樣分組的消息又能被其餘消費者並行消費,解決負載均衡的問題,一箭雙鵰啦!server
Rocketmq處理方案blog
那rocketmq又是如何保證消息順序消費的問題呢?
Rocketmq跟傳統的MQ有一點區別,這裏有必要講一下topic的概念,Topic是RocketMQ中的一個重要概念,RocketMQ的各組件都是圍繞着Topic創建起對應關係的,在RocketMQ官方文檔和本文中, Topic在不一樣的語境下被賦予了兩種不一樣的語義:
1)消息的Topic屬性值:在描述Consumer的訂閱設置信息或消息的屬性時。
2)Topic屬性爲某個值的消息(單個消息或消息集合):在描述Broker,Producer和Consumer的對應關係,Queue以及負載均衡策略時。
topic和queue的對應關係是一個topic擁有多個queue,當producer往broken發送消息時,消息會存儲在topic下的不一樣隊列中,而一個隊列只會被一個consumer消費,這樣消息戶被均衡負載到不一樣的隊列下,也就是會被多個消費者並行消費,順序就沒法保證了。該怎麼辦呢?答案是把須要順序消費的消息發送到同一臺broker server下的同一個隊列,而這些消息也只會被同一個消費者消費,這樣就能夠保證嚴格的順序了,以下圖:
一、消息要有順序,首先得保證producer發送消息有順序,如上圖msg1,msg2,msg3發送到queue0是要有順序的,只要producer等待前面的消息發送成功,在發送後面的消息就徹底能夠保證了,
二、假設msg1發送給consumer1,消費沒有響應,該怎麼辦呢?是繼續發送msg2仍是從新發送msg1,通常爲了保證消息必定被消費,確定會選擇重發msg1到下一臺消費者consumer2。
三、消費端1沒有響應Server時有兩種狀況,一種是msg1確實沒有到達(數據在網絡傳送中丟失),另一種消費端已經消費msg2且已經發送響應消息,只是MQ Server端沒有收到。若是是第二種狀況,重發msg1,就會形成msg1被重複消費。也就引入了消息重複問題,那就要冪等了。
Rocketmq一樣作到了保證消息的順序狀況下,均衡消費的消費消息。
綜上,我看到,在分佈式系統中,要想消息有順序的被消費,不管是Activemq仍是Rocketmq都要想辦法讓有順序的消息被同一消費者消費,而不是併發的消費,在消費者消費成功後,接着纔會消費下一個消息,這樣就能夠保證了嚴格的順序。