東莞外貿(mào)優(yōu)化公司東莞搜索優(yōu)化十年樂云seo
應(yīng)一些小伙伴們的私信,希望可以介紹一下RocketMQ的基礎(chǔ),那么我們現(xiàn)在就從0開始,進(jìn)入RocketMQ的基礎(chǔ)學(xué)習(xí)及概念介紹,為學(xué)習(xí)和使用RocketMQ打好基礎(chǔ)!
RocketMQ是一款快速地、可靠地、分布式、容易使用的消息中間件,由Alibaba開發(fā),其前身是 Metaq,Metaq 可以看成是linkedin的Kafka(scala)的java版本,并對(duì)其增加了事務(wù)的支持。
RocketMQ為Metaq3.0,相比于原始kafka,其擅長(zhǎng)點(diǎn)出了原始的 log collecting之外,還增加諸如HA、事務(wù)等特性,使得從功能上可以替代傳統(tǒng)大部分 MQ。
- 可靠的FIFO和嚴(yán)格的消息順序
- Pub/Sub 和 P2P 消息模型
- 單隊(duì)列容納百萬消息的能力
- 拉(Pull)和推(push)隊(duì)列
- 各種消息協(xié)議,如 JMS,MQTT 等
- 分布式集群,支持容錯(cuò)
- Docker images for isolated testing and cloud Isolated clusters
- 豐富的配置和監(jiān)控功能的管理
Topic 是一個(gè)主題。一個(gè)系統(tǒng)中,我們可以將消息劃成 Topic ,這樣,將不同的消息發(fā)送到不同的 queue。
-
一個(gè)topic下,我們可以設(shè)置多個(gè)queue,每個(gè)queue就是我們平時(shí)所說的消息隊(duì)列;
-
因?yàn)閝ueue是完全從屬于某個(gè)特定的topic的,所以當(dāng)我們要發(fā)送消息時(shí),總是要指定該消息所屬的topic是什么。
-
通過equeue就能知道該topic下有幾個(gè)queue了,但是到底發(fā)送到哪個(gè)queue呢?比如topic下有4個(gè)queue,那對(duì)于這個(gè)topic下的消息,發(fā)送時(shí),到底該發(fā)送到哪個(gè)queue呢?
-
目前,equeue的做法是在發(fā)送一個(gè)消息時(shí),需要用戶指定這個(gè)消息對(duì)應(yīng)的topic以及一個(gè)用來路由的一個(gè)object類型的參數(shù)。
-
equeue會(huì)根據(jù)topic得到所有的queue,然后根據(jù)該object參數(shù)通過hash code然后取模queue的個(gè)數(shù)最后得到要發(fā)送的queue的編號(hào),從而知道該發(fā)送到哪個(gè)queue。
-
這個(gè)路由消息的過程是在發(fā)送消息的這一方做的,也就是下面要說的producer。之所以不在消息服務(wù)器上做是因?yàn)檫@樣可以讓用戶自己決定該如何路由消息,具有更大的靈活性。
消息隊(duì)列的生產(chǎn)者。我們知道,消息隊(duì)列的本質(zhì)就是實(shí)現(xiàn)了publish-subscribe的模式,即生產(chǎn)者-消費(fèi)者模式。生產(chǎn)者生產(chǎn)消息,消費(fèi)者消費(fèi)消息。所以這里的Producer就是用來生產(chǎn)和發(fā)送消息的。
消息隊(duì)列的消費(fèi)者,一個(gè)消息可以有多個(gè)消費(fèi)者。
消費(fèi)者分組,這可能對(duì)大家來說是一個(gè)新概念。之所以要搞出一個(gè)消費(fèi)者分組, 是為了實(shí)現(xiàn)下面要說的集群消費(fèi)。一個(gè)消費(fèi)者分組中包含了一些消費(fèi)者,如果這些消費(fèi)者是要集群消費(fèi),那這些消費(fèi)者會(huì)平均消費(fèi)該分組中的消息。
-
equeue中的broker負(fù)責(zé)消息的中轉(zhuǎn),即接收producer發(fā)送過來的消息,然后持久化消息到磁盤,然后接收consumer發(fā)送過來的拉取消息的請(qǐng)求,然后根據(jù)請(qǐng)求拉取相應(yīng)的消息給consumer。
-
所以,broker可以理解為消息隊(duì)列服務(wù)器,提供消息的接收、存儲(chǔ)、拉取服務(wù)。
-
broker對(duì)于equeue來說是核心,它絕對(duì)不能掛,一旦掛了,那producer,consumer就無法實(shí)現(xiàn)publish-subscribe了。
-
使用CPU資源來換取網(wǎng)卡流量資源;
-
FilterServer與Broker部署在同一臺(tái)機(jī)器,數(shù)據(jù)通過本地回環(huán)通信,不走網(wǎng)卡;
-
一臺(tái)Broker部署多個(gè)FilterServer,充分利用CPU資源,因?yàn)閱蝹€(gè)JVM難以全面利用高配的物理機(jī)CPU資源;
-
因?yàn)檫^濾代碼使用Java編寫,應(yīng)用幾乎可以做任意形式的服務(wù)器端消息過濾,例如通過Messgae Header進(jìn)行過濾,甚至可以按照Message Body進(jìn)行過濾;
-
使用Java語言進(jìn)行作為過濾表達(dá)式是一個(gè)雙刃劍,方便了應(yīng)用的過濾操作,但是帶來了服務(wù)器端的安全風(fēng)險(xiǎn)。需要應(yīng)用來保證過濾代碼安全,例如在過濾程序中盡可能不做申請(qǐng)大內(nèi)存,創(chuàng)建線程等操作,避免Broker服務(wù)器發(fā)生資源泄露。
-
SEND_OK:消息發(fā)送成功;
-
FLUSH_DISK_TIMEOUT:消息發(fā)送成功,但是服務(wù)器刷盤超時(shí),消息已經(jīng)進(jìn)入服務(wù)器隊(duì)列,只有此時(shí)服務(wù)器宕機(jī),消息才會(huì)丟失;
-
FLUSH_SLAVE_TIMEOUT:消息發(fā)送成功,但是服務(wù)器同步到slave時(shí)超時(shí),消息已經(jīng)進(jìn)入服務(wù)器隊(duì)列,只有此次服務(wù)器宕機(jī),消息才會(huì)丟失;
-
SLAVE_NOT_AVAILABLE:消息發(fā)送成功,但是此時(shí)slave不可用,消息已經(jīng)進(jìn)入服務(wù)器隊(duì)列,只有此時(shí)服務(wù)器宕機(jī),消息才會(huì)丟失;
集群消費(fèi)是指,一個(gè)consumer group下的consumer,平均消費(fèi)topic下的queue。
- 假如一個(gè)topic下有4個(gè)queue,然后當(dāng)前有一個(gè)consumer group,該分組下有4個(gè)consumer,那每個(gè)consumer就被分配到該topic下的一個(gè)queue,這樣就達(dá)到了平均消費(fèi)topic下的queue的目的。
- 如果consumer group下只有兩個(gè)consumer,那每個(gè)consumer就消費(fèi)2個(gè)queue。
- 如果有3個(gè)consumer,則第一個(gè)消費(fèi)2個(gè)queue,后面兩個(gè)每個(gè)消費(fèi)一個(gè)queue,從而達(dá)到盡量平均消費(fèi)。
應(yīng)該盡量讓consumer group下的consumer的數(shù)目和topic的queue的數(shù)目一致或成倍數(shù)關(guān)系。這樣每個(gè)consumer消費(fèi)的queue的數(shù)量總是一樣的,這樣每個(gè)consumer服務(wù)器的壓力才會(huì)差不多。當(dāng)前前提是這個(gè)topic下的每個(gè)queue里的消息的數(shù)量總是差不多多的。這點(diǎn)我們可以對(duì)消息根據(jù)某個(gè)用戶自己定義的key來進(jìn)行hash路由來保證。
廣播消費(fèi)是指一個(gè)consumer只要訂閱了某個(gè)topic的消息,那它就會(huì)收到該topic下的所有queue里的消息,而不管這個(gè)consumer的group是什么。所以對(duì)于廣播消費(fèi)來說,consumer group沒什么實(shí)際意義。consumer可以在實(shí)例化時(shí),我們可以指定是集群消費(fèi)還是廣播消費(fèi)。
對(duì)于集群消費(fèi)和廣播消費(fèi),消費(fèi)進(jìn)度持久化的地方是不同的,集群消費(fèi)的消費(fèi)進(jìn)度是放在broker,也就是消息隊(duì)列服務(wù)器上的,而廣播消費(fèi)的消費(fèi)進(jìn)度是存儲(chǔ)在consumer本地磁盤上的。
- *由于一個(gè)queue的消費(fèi)者可能會(huì)更換,因?yàn)閏onsumer group下的consumer數(shù)量可能會(huì)增加或減少,然后就會(huì)重新計(jì)算每個(gè)consumer該消費(fèi)的queue是哪些,所以,當(dāng)出現(xiàn)一個(gè)queue的consumer變動(dòng)的時(shí)候,新的consumer如何知道該從哪里開始消費(fèi)這個(gè)queue呢?
如果這個(gè)queue的消費(fèi)進(jìn)度是存儲(chǔ)在前一個(gè)consumer服務(wù)器上的,那就很難拿到這個(gè)消費(fèi)進(jìn)度了,因?yàn)橛锌赡苣莻€(gè)服務(wù)器已經(jīng)掛了,或者下架了,都有可能。而因?yàn)閎roker對(duì)于所有的consumer總是在服務(wù)的,所以,在集群消費(fèi)的情況下,被訂閱的topic的queue的消費(fèi)位置是存儲(chǔ)在broker上的,存儲(chǔ)的時(shí)候按照不同的consumer group做隔離,以確保不同的consumer group下的consumer的消費(fèi)進(jìn)度互補(bǔ)影響。
廣播消費(fèi),由于不會(huì)出現(xiàn)一個(gè)queue的consumer會(huì)變動(dòng)的情況,所以我們沒必要讓broker來保存消費(fèi)位置,所以是保存在consumer自己的服務(wù)器上。
消費(fèi)進(jìn)度是指,當(dāng)一個(gè)consumer group里的consumer在消費(fèi)某個(gè)queue里的消息時(shí),equeue是通過記錄消費(fèi)位置(offset)來知道當(dāng)前消費(fèi)到哪里了。以便該consumer重啟后繼續(xù)從該位置開始消費(fèi)。
比如一個(gè)topic有4個(gè)queue,一個(gè)consumer group有4個(gè)consumer,則每個(gè)consumer分配到一個(gè)queue,然后每個(gè)consumer分別消費(fèi)自己的queue里的消息。
equeue會(huì)分別記錄每個(gè)consumer對(duì)其queue的消費(fèi)進(jìn)度,從而保證每個(gè)consumer重啟后知道下次從哪里開始繼續(xù)消費(fèi)。
實(shí)際上,也許下次重啟后不是由該consumer消費(fèi)該queue了,而是由group里的其他consumer消費(fèi)了,這樣也沒關(guān)系,因?yàn)槲覀円呀?jīng)記錄了這個(gè)queue的消費(fèi)位置了。
消費(fèi)位置和consumer其實(shí)無關(guān),消費(fèi)位置完全是queue的一個(gè)屬性,用來記錄當(dāng)前被消費(fèi)到哪里了。另外一點(diǎn)很重要的是,一個(gè)topic可以被多個(gè)consumer group里的consumer訂閱。
不同consumer group里的consumer即便是消費(fèi)同一個(gè)topic下的同一個(gè)queue,那消費(fèi)進(jìn)度也是分開存儲(chǔ)的。也就是說,不同的consumer group內(nèi)的consumer的消費(fèi)完全隔離,彼此不受影響。
分享資源
獲取以上資源請(qǐng)?jiān)L問開源項(xiàng)目 點(diǎn)擊跳轉(zhuǎn)