為什么說使用MQ會(huì)更優(yōu)雅?

我們來討論MQ,首先我們需要問下自己我們?yōu)槭裁匆褂肕Q?MQ為我們解決了哪些問題?
日常應(yīng)用解決的是我們系統(tǒng)耦合的問題,如下舉出外面場景 訂單和派送系統(tǒng)

image.png

使用RPC 也會(huì)存在一些耦合一方系統(tǒng)修改或者調(diào)整,另一方也要跟著調(diào)整;

image.png

通過隊(duì)列傳遞消息,雙方都是可以做到異步處理,且無耦合

加入公司決定自研MQ,那么如果你是架構(gòu)設(shè)計(jì)組成員的話,你會(huì)從哪些方面考慮去設(shè)計(jì)一款高性能高可用的MQ呢?

1.首先是協(xié)議
因?yàn)槿魏瓮ㄟ^網(wǎng)絡(luò)收發(fā)數(shù)據(jù),肯定是要協(xié)議的指定;
比如說瀏覽器的http協(xié)議,只不過http協(xié)議有點(diǎn)重量級(jí)了,消息頭以及消息體字節(jié)數(shù)較大
不適用與輕量級(jí)的MQ消息傳遞;且http是短連接,不適合業(yè)務(wù)量較大的mq場景,此時(shí)頻繁建立鏈接也是比較耗時(shí)的;
因此需要知道何時(shí)的協(xié)議,市面上的協(xié)議比如MQTT amqp,OpenWire...

2.消息的存取和持久化(刷盤規(guī)則)

我們分析一下消息存儲(chǔ)時(shí)機(jī),以及存儲(chǔ)的規(guī)則
1.可以這樣優(yōu)化 消息總是先在內(nèi)存-->緩存到指定大小再寫到磁盤文件
2.如果保證消息正常寫入,使用確認(rèn)重試機(jī)制,如果生產(chǎn)者發(fā)送消息,mq沒有收到消息會(huì)重試;
3.如何保證寫入與讀取的高效(不使用jvm內(nèi)存,直接使用os的內(nèi)存)


image.png

如圖如果我們會(huì)多出2次拷貝,既浪費(fèi)性能又浪費(fèi)空間;

3.消息的分發(fā)策略
1.消息發(fā)送到哪個(gè)mq,消費(fèi)者是主動(dòng)pull還是mq push
2.消息收發(fā)確認(rèn)機(jī)制(保證mq收到消息,消費(fèi)者正確收到消息)

4.mq的高可用
我們的mq server如何高可用
從以下幾個(gè)角度
1.能不能有備份
1.1可以一主多從,同步模式可以有異步或者同步 類似于db的數(shù)據(jù)冗余備份


image.png

1.2 多主多從的集群模式

image.png

2 分片和副本

image.png

原本一份數(shù)據(jù)現(xiàn)在分成3分,分布在不同server示例上,每個(gè)分片也有自己的副本,及時(shí)當(dāng)前分片主節(jié)點(diǎn)掛了,也會(huì)選出在其他節(jié)點(diǎn)的salve1節(jié)點(diǎn)作為新的節(jié)點(diǎn)保證了高可用;slave和master保持異步或者同步數(shù)據(jù);

這樣的設(shè)計(jì)比如ES或者M(jìn)ongo都會(huì)有看到;

4.如何做到支持高并發(fā)
1.首先網(wǎng)絡(luò)通訊使用Nio的異步通訊,支持海量數(shù)據(jù)處理(很多中間件也是使用前面文章的netty作為高性能的通信框架);
2.合適的數(shù)據(jù)刷盤機(jī)制,使用合適的索引機(jī)制,類似于mysql索引;
3.讀寫的零拷貝,不使用jvm內(nèi)存
4.動(dòng)態(tài)方便的擴(kuò)容

至此以上是總結(jié)的mq的一些通用設(shè)計(jì)點(diǎn);下面我們來看下具體的MQ的設(shè)計(jì)架構(gòu),我們會(huì)拿Rabbitmq和Kafka作為對(duì)比,并總結(jié)一下MQ設(shè)計(jì)的一些共通的設(shè)計(jì)要點(diǎn);

kafka架構(gòu)


image.png

架構(gòu)圖中涉及到涉及概念
broker : server實(shí)例,多個(gè)實(shí)例組成集群
topic: 類似于傳統(tǒng)mq的隊(duì)列
partion: 分區(qū)相當(dāng)于將topic的一整份大數(shù)據(jù)分成多個(gè)分區(qū)存儲(chǔ)在多個(gè)實(shí)例上;
replica: pation數(shù)據(jù)的冗余副本,分布在其他節(jié)點(diǎn)實(shí)例;
consumer:消息發(fā)送者采用pull推送
consumer group:消費(fèi)分組 一個(gè)partion只能被consumer group的一個(gè)消費(fèi)者消費(fèi);
producer:采用push推送到broker上

kafka消息的分發(fā)策略:

具體發(fā)送哪個(gè)topic和partion的,由生產(chǎn)者決定;
具體的消息格式類似于key _value格式
輪詢:
如果key為null,會(huì)采用輪休的策略發(fā)送到對(duì)應(yīng)partion;
hash:
如果key不為null,采用hash策略;
所以在一個(gè)partition內(nèi)要保證消息的有序性,需要設(shè)置指定的key;

kafka消息的持久化策略:

普遍任務(wù)寫文件比內(nèi)存慢很多;但如果采用順序讀寫,可以達(dá)到
百兆/s,甚至比內(nèi)存還快,但如果是隨機(jī)讀寫的話只能達(dá)到100kb/s;
所以kafka采用順序讀寫的文件流;
1.kafka數(shù)據(jù)存儲(chǔ)從os 內(nèi)存->磁盤,沒有采用jvm內(nèi)存中轉(zhuǎn),
1.原因是先寫到j(luò)vm在寫到os內(nèi)存,會(huì)多一次拷貝,且內(nèi)存空間會(huì)多一倍以上
2.jvm gc機(jī)制,很難保證消息正確寫出;

我們看下具體消息格式


image.png

我們看到一個(gè)partition消息文件分為log和index文件;都是以offerset(每條消息都會(huì)分片對(duì)應(yīng)的消息id)
所以我們只要根據(jù)index就可以以最快的速度查詢到消息文件

消息格式如下
消息長度: 4 bytes (value: 1 + 4 + n)
版本號(hào): 1 byte
CRC校驗(yàn)碼: 4 bytes
具體的消息: n bytes

image.png

總結(jié)以上:
kafka高效的原因
1.協(xié)議:簡易的消息格式類似于mqtt和amqp;沒有復(fù)雜的消息傳輸格式;
網(wǎng)絡(luò)基于netty消息傳遞,使用零拷貝機(jī)制,實(shí)現(xiàn)消息的高效傳輸;
2.分發(fā)策略
采用發(fā)布確認(rèn)機(jī)制(ack機(jī)制);保證消息可靠收發(fā);
3.消息持久化
基于順序存儲(chǔ)的文件日志儲(chǔ)存,不使用jvm內(nèi)存的零拷貝機(jī)制,
文件寫入采用順序追加機(jī)制,高效的實(shí)現(xiàn)文件寫入和讀??;
4.高可用設(shè)計(jì)
采用分區(qū)(可以水平擴(kuò)展)同時(shí)提高partition讀寫能力;
使用replica同步機(jī)制,當(dāng)節(jié)點(diǎn)故障,利用zk的臨時(shí)節(jié)點(diǎn)機(jī)制,選出新的主節(jié)點(diǎn);

使用kafka可以從以上幾點(diǎn)優(yōu)化配置;

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容