1. 程式人生 > >如何構建一個高可用的IM系統

如何構建一個高可用的IM系統

一、概念

讀擴散
顧名思義就是把讀放大了,增加了讀的複雜度,相對的就減少了寫的複雜度;每次會話中產生的訊息,只需要寫一次庫就可以,接收端從這個庫里拉取訊息。對於群訊息的場景,能夠大大降低訊息寫入的次數,一條群訊息只需要寫一次即可;接收端需要對每個會話都拉取一次才能獲取全部訊息,讀被大大的放大了,併產生很多無效的讀,因為不是每個會話都有新訊息。



寫擴散
顧名思義就是把寫放大了,增加了寫的複雜度,相對的就減少了讀的複雜度;每次會話中的訊息,會產生多次寫;對於群訊息的場景,寫入會被更加的放大,如果這個群有N個參與者,那每條訊息需要額外的寫N次,即把訊息拆開到人,並分別儲存;寫擴散,在接收端訊息同步邏輯會非常簡單,只需要從庫裡讀取一次即可,大大降低了訊息所需要讀的壓力;缺點就是寫被放大了。

群訊息模型一般使用寫擴散模型,也就是說發到群裡的一條訊息會給群裡的每個人都存一份,通過犧牲空間來換取了每個人拉取群訊息的效率。

擴充套件閱讀:http://blog.csdn.net/AAA821/article/details/72550767

二、常用協議

XMPP協議
簡單的來說就是使用XML格式進行傳送接收訊息處理的協議。
官網:https://xmpp.org/
GTalk是基於XMPP協議實現的。

MQTT協議
是一種基於釋出/訂閱模式的“輕量級”通訊協議,該協議構建於TCP/IP協議上;最大的優點是以極少的程式碼和頻寬,為連線遠端裝置提供可靠的訊息服務。
MQTT: http://mqtt.org/

FaceBook 的Messager 是基於MQTT實現的。

私有協議
通過自己定義協議格式的方式實現,需要考慮的全面的一些,工作量比較大。
微信是使用的私有協議。

protobuf協議
簡單,快,小,比使用 xml, json 進行資料交換快許多,由於其靈活性和方便有很多人使用其封裝訊息結構,實現訊息系統。


三、IM系統需要支援的功能

1)使用者一對一單聊
2)使用者群聊
3)使用者多個終端訊息同步
4)使用者訊息通知推送

也可以利用訊息系統的通道實現一些控制類訊息的推送,提示客戶端更新資料等。

四、訊息系統模型


五、訊息系統架構


Client:     MQTT Client SDK,開發者基於SDK開發客戶端,Paho官方網站,使其支援訊息的接收和傳送。 LVS/Haproxy:      作為HA層,實現後端系統的高可用。 接入層:     1)MQTT代理:支援釋出訂閱模式的MQTT訊息伺服器;通過這個代理服務,接收客戶端傳送過來的MQTT協議格式的訊息,還可以把MQTT協議格式的訊息釋出給客戶端。     2)Nginx: HTTP協議代理伺服器,歷史訊息的獲取通過http請求獲取。 如果有新的協議格式的訊息型別接入,只需要在接入層擴容新的訊息代理服務即可。 MQ:佇列服務,比如:RabbitMQ佇列服務、Kafka佇列服務等。 業務層: 1)p_logic:把MQTT協議的資料轉化為業務資料,並投遞到MQ佇列裡,然後給客戶端返回 ack。先投遞到佇列裡的目的是先接收資料落地到高可用的高效能的系統裡,提高系統的效能,(採用了郵箱系統的開源軟體Postfix的一些設計思想) 2)s_logic: 訊息業務處理服務,解析訊息業務資料,比如:入庫,群訊息拆分,轉投等功能。 3)通知服務、APNS服務等都屬於訊息系統裡的元件,可以根據實際需要新增,比如:APNS服務,是實現蘋果手機的訊息推送服務。 整個業務層藉助MQ佇列進行訊息週轉,實現各個元件的見協同工作。 資料層: 1)Redis: 快取一些臨時性的資料。 2)Mysql: 訊息儲存系統,儲存所有的訊息。 3)檔案儲存:訊息聊天裡支援傳送檔案,所有的檔案儲存到這個系統裡。

六、訊息傳送流程

1)客戶A傳送訊息到客戶B
討論: 1、如何保證訊息的有效性?     儲存訊息的時候,儲存一個seqID,客戶端根據seqID進行排序。
2、客戶端存在的一個場景:     在弱網或者無網的情況,檢視已經收到本地的訊息,無論狀態是否同步到服務端成功,訊息計數都要清零,不能說使用者看了訊息,還顯示未讀狀態。如何保證多端訊息計數的一致性?
3、訊息如何儲存?資料庫如何設計?     可以根據寫擴散模型設計表結構,設計表結構要注意到如何實現分庫分表。
待補充。。。。