為什么使用 MQ?
-
解耦
一個系統(tǒng)或者模型,調(diào)用多個系統(tǒng)或者模塊,互相調(diào)用非常復雜,維護也很麻煩,但是當不需要同步調(diào)用情況時,用MQ解耦是一個選擇。
各個業(yè)務系統(tǒng)在未使用MQ時,在需要相互傳輸數(shù)據(jù)時,耦合性就會很高,從而造成相互合作比較麻煩,使用MQ可以降低耦合性,從而只關(guān)心自己的業(yè)務。
-
異步
互聯(lián)網(wǎng)用戶等待時間一般要求200ms以內(nèi)。
當系統(tǒng)后臺操作執(zhí)行時間較長,系統(tǒng)反應時間很慢從而影響到了客戶的體驗。當使用MQ后,可以提升系統(tǒng)的響應時間,相應的復雜操作可以由后臺執(zhí)行無需等待。
-
削峰
當數(shù)據(jù)量一瞬間非常大時,如果后臺涉及到使用sql,大于5000次/s可能就會造成系統(tǒng)宕機,所以需要使用MQ進行防止此類情況發(fā)生,高峰期過后MQ中堆積的數(shù)據(jù)也會很快被消費掉。
使用MQ可能會存在的問題
-
系統(tǒng)的可用性降低
當MQ故障,整個系統(tǒng)就會崩潰。
-
系統(tǒng)的復雜性變高
引入MQ導致系統(tǒng)考慮的問題增多。
-
一致性問題
MQ的技術(shù)選型
現(xiàn)在可供選擇的MQ類型有ActiveMQ、RabbitMQ、RocketMQ、Kafka。
相關(guān)區(qū)別如下表格:
| 特性 | ActiveMQ | RabbitMQ | RocketMQ | Kafka |
|---|---|---|---|---|
| 單機吞吐量 | 萬級 | 萬級 | 10萬級 | 10萬級 一般配合大數(shù)據(jù)類的系統(tǒng)來進行實時數(shù)據(jù)計算,日志采集等場景 |
| topic數(shù)量對吞吐量的影響 | topic可以達到幾百,幾千的級別,吞吐量會小幅度下降,這個是RocketMQ的一大優(yōu)勢,在同等機器下,可以支撐大量的topic | topic從幾十個到幾百個的時候,吞吐量會大復度下降。所以在同等機器下,kafka盡量保證topic數(shù)量不要過多。 | ||
| 時效性 | ms | 微妙 | ms | ms |
| 可用性 | 高,基于主從架構(gòu)實現(xiàn)高可用性 | 高,基于主從架構(gòu)實現(xiàn)高可用 | 非常高,分布式架構(gòu) | 非常高 |
| 消息可靠性 | 有較低的概率丟失數(shù)據(jù) | 經(jīng)過參數(shù)優(yōu)化可以做到0丟失 | 經(jīng)過參數(shù)優(yōu)化可以做到0丟失 | |
| 功能支持 | MQ領域的功能極其完備 | 基于erlang開發(fā),所以并發(fā)行非常好,性能好,延遲低 | MQ功能較為完善,還是分布式的,擴展性好 | 功能比較簡單,主要支持簡單的MQ功能,在大數(shù)據(jù)領域是事實上的標準 |
| 優(yōu)劣勢總結(jié) | 優(yōu)點:非常成熟,功能強大,在業(yè)內(nèi)曾大量公司以及項目中使用。缺點:社區(qū)內(nèi)以及國內(nèi)應用越來越少,維護頻率很低,幾個月一次。主要用于解耦和異步,較少用于大規(guī)模吞吐的場景。 | 優(yōu)點:erlang語言開發(fā),性能好,延遲低。吞吐量過萬,開源提供的管理界面非常棒,社區(qū)比較活躍,每個月都會發(fā)布幾個版本。 缺點:erlang開發(fā),國內(nèi)鮮有幾個公司可以對erlang源碼級別研究和定制。 | 優(yōu)點:阿里出品java系的,可以閱讀源碼并定制,社區(qū)活躍度一般,文檔相對簡單。缺點:萬一這個技術(shù)被拋棄,社區(qū)放棄更新,需要自身具備當出現(xiàn)bug時候可以主動修復的實力。 |
不推薦使用activeMQ,因為沒有經(jīng)過大規(guī)模吞吐量場景的驗證,社區(qū)也不是很活躍。
越來越多公司在使用RocketMQ,確實不錯,但是需要考慮萬一社區(qū)拋棄的風險,使用RabbitMQ,社區(qū)活躍人員為散戶,不會黃掉.
如何實現(xiàn)高可用性
RabbitMQ
普通集群模式:
- 可能會在rabbitMQ集群內(nèi)部產(chǎn)生大量的數(shù)據(jù)傳輸。
- 可用性幾乎沒有保障。
鏡像集群模式:
每個節(jié)點都會存儲全部queue信息。可以保證高可用性。
當一個節(jié)點宕機,可以在其他節(jié)點消費或生產(chǎn)到消息。
如何配置鏡像集群模式:
rabbitMQ有控制臺,在控制臺增加一個策略,鏡像集群模式策略,指定的時候可以要求數(shù)據(jù)同步到所有節(jié)點,也可以要求同步到某些節(jié)點。
Kafka
多個broker組成,每個broker是一個節(jié)點;創(chuàng)建一個topic,這個topic可以劃分為多個partition,每個partition可以存在于不同的broker上,每個partition就放一部分數(shù)據(jù)。
這就是天然的分布式消息隊列,就是一個topic的數(shù)據(jù),分散放在多個機器上,每個機器就放一部分數(shù)據(jù)。
實際上rabbitmq之類的,并不是分布式消息隊列,他就是傳統(tǒng)的消息隊列,只不過提供了一些集群,HA的機制而已,無論怎么玩,rabbitmq一個queue的數(shù)據(jù)都是放在一個節(jié)點內(nèi),鏡像集群下,也是每個節(jié)點都放在這個queue的完整數(shù)據(jù)。
kafka0.8后提供了HA機制,就是replica副本機制,每個partition的數(shù)據(jù)都會同步到其他機器,形成自己多個replica副本。然后所有replica會選舉一個leader出來,然后生產(chǎn)和消費和這個leader打交道,然后其他副本就是follower。讀的時候就直接讀leader數(shù)據(jù)即可。
如果一個broker宕機了,沒事,那么broker上面的partition在其他機器上都有副本的,如果這上面有某個partition的leader,那么此時會重新選舉一個新的leader出來。繼續(xù)讀寫這個leader就可以了。這個就是高可用性。