如果讓你設計一個高並發的消息中間件,你會怎麼做?
寫在前面
很多小夥伴去大廠面試,幾乎都會遇到一些開放式的題目,這些開放式的題目沒有固定的答案,但是它能夠實實在在的體現面試者較為真實的系統設計能力和技術功底。如果你回答的比較完美,那麼,通過這種開放式題目,就能夠讓你從眾多的面試者中脫穎而出。今天,我們就一起來聊聊,去大廠面試時,一個較為常見的開放式題目:如果讓你設計一個高並發的消息中間件,你會怎麼做?
消息中間件涉及的知識點
要想設計一個具有高並發的消息中間件,那麼首先就要了解下消息中間件涉及哪些具體的知識點。通常,設計一個良好的消息中間件最少需要滿足如下條件:
- 生產者、消費者模型。
- 支援分散式架構。
- 數據的高可用。
- 消息數據不丟失。
接下來,我們就針對消息中間件來分別談談這些技術點。
生產者消費者模型
相信很多小夥伴對於生產者和消費者模型都比較了解了,簡單的說:就是消息中間件能夠使其他應用來生產消息,也能夠使其他應用來消費相應的消息。
對於生產者和消費者模型,我們需要考慮的問題點就比較多了。接下來,我就一步步來引導大家進行思考。
首先,我們來思考這樣一個問題: 如果生產者生產了消息,那麼消息中間件應該怎樣存儲相應的數據呢? 存儲在記憶體? 存儲在磁碟? 還是同時存儲在記憶體和磁碟中呢?
如果是將消息數據同時存儲在記憶體和磁碟中,我們又該如何處理這些數據呢? 是生產者將消息投遞到消息中間件之後,我們就立刻將數據寫入磁碟?還是說數據先駐留到記憶體,然後每隔一段時間刷到磁碟上? 如果是每隔一段時間刷到磁碟上,那我們又要考慮磁碟文件的切分問題,也就是說,需要將消息數據分成多少個磁碟文件?(總不能把所有的數據放到一個磁碟文件中吧)。如果是需要切分成多個磁碟文件,那切分的規則又是什麼呢?
上面這些問題都是我們在設計一個消息中間件時需要考慮的問題。然而,這還只是一小部分問題。如果想在面試時脫穎而出,那就還需要繼續往下看,還有一些重要的問題點需要注意。
如果文件按照一定的規則切分到多個磁碟文件中了,那是不是還需要管理元數據來標識數據的具體消息(就像是Hadoop中的NameNode節點中存儲著DataNode的元數據資訊,NameNode節點通過這些元數據資訊就能夠更好的管理DataNode節點)?這些元數據可以包括:消息數據的偏移量、也可以是消息數據的唯一ID。
考慮完數據的存儲問題,我們還需要考慮的是:消息中間件是如何將數據投遞到對應的消費者的?
在設計生產者和消費者時,還一個很重要的問題需要我們考慮:我們在設計消息中間件時,採用的消費模式是什麼?會不會將數據均勻的分配給消費者?還是會通過一些其他的規則將數據投遞到消費者?
支援分散式架構
如果我們設計的消息中間件,每天會承載TB級別的數據高並發和高吞吐量的寫入操作。這裡,我們就需要考慮將消息中間件設計成分散式架構。
在設計分散式架構時,我們還需要考慮將存儲的比較大的數據,做成分片存儲,對數據進行分片等操作。
除了這些,我們還需要考慮另外一個核心問題:對於消息中間件來說,需要支援自動擴容操作。
還有就是是否支援數據分片,如何實現數據分片的擴容和自動數據負載均衡遷移等。
數據的高可用
一般互聯網應用的高可用,是通過本地堆記憶體,分散式快取,和一份數據在不同的伺服器上都搞一個副本來實現的。此時,任何一個存儲節點宕機,都不會影響整體的高可用。我們在設計消息中間件時也可以參考這個思路。
消息數據不丟失
此時,我們就需要提供手動ACK的機制,也就是說:當消費者真正消費消息完畢後,向消息中間件返回「 處理完成」 的標識,消息中間件刪除相應的已處理的消息。
但是,細化的話,這裡,我們就需要兩套ACK機制:
- 一種ACK對應的是生產端。如果一直沒有接收到ACK消息,則需要通過生產者來重新發送一條消息來保證生產消息成功。
- 另一種ACK對應的是消費端。一旦一條消息消費並處理成功,必須返回一個ack給消息中間件,然後消息中間件才能刪除這條消息。否則一旦消費者宕機,就必須重發這條消息給其他的消費者實例,保證消息一定會被處理成功。
今天,我們沒有聊具體的業務點,而是從整體上考慮:如果實現一個消息中間件,需要我們注意的各項知識點和專業技能!好了,今天就到這兒吧,我是冰河,我們下期見大家有啥問題可以在下方留言,也可以加我微信:sun_shine_lyz,我拉你進群,一起交流技術,一起進階,一起牛逼~~