每當網絡上爆出熱點新聞,混跡于各個社交媒體的小伙伴們全都開啟了討論模式。一條消息的產生是如何在群聊中傳遞的呢?讓我們一起來探索即時通訊系統(IM)的原理。
IM 系統架構的原理
當你在群聊“相親相愛一家人”中,發送了一條“我找到女朋友了,今天帶回家吃飯”,你自然是希望全家人都收到你的喜訊,為你女朋友的到來分頭準備。那么正常的流程應該是這樣:遍歷群成員、查詢每個成員的在線狀態、如果小伙伴們在線則實時進行推送,如果小伙伴們不在線則暫存至離線庫待上線后主動拉取。
這種模式就是傳統的 IM 架構,由于發送成功的消息不會落入離線庫,因此聊天記錄多端漫游無法實現。如果在線用戶推送發生異常,會導致個別人員丟失關鍵發言,錯失重要信息。為了保證消息存儲的可靠性,我們對 IM 系統架構進行了優化,不管成員是否在線都要先把消息和發送對象存儲起來,再進行推送。流程變成:遍歷群成員、為群聊的每一個人對應的消息隊列都存一份消息、查詢每個成員的在線狀態、對在線成員進行推送。這就是所謂的寫擴散模型。
這里顯然還存在一個問題,我們向每個小伙伴的消息隊列中都存儲了相同的“我找到女朋友了,今天帶回家吃飯”消息,對磁盤和帶寬造成了很大的浪費,這是寫擴散的最大弊端。所以我們繼續優化,群消息實體存儲一份,用戶只存消息ID索引。流程優化為:遍歷群聊的成員、先存一份消息實體、群聊所有人都存一份 ID引用、查詢每個成員的在線狀態、對在線成員進行推送。這就是所謂的讀擴散模型。
簡單總結下:
1.讀擴散:讀取操作很重,寫入操作很輕,資源消耗相對小一些。
2.寫擴散:讀取操作很輕,寫入操作很重,資源消耗相對大一些。
IM 系統架構優化實踐
接下來,讓我們使用 GaussDB(forRedis)來實現一個簡單的 IM 應用。
使用 GaussDB(forRedis)的 List 類型實現一個消息隊列,防止發送端瞬時高流量會壓爆消息處理模塊;
收到消息后,先生成一個全局唯一 ID 標識該信息,將消息 ID 和消息內容存入 String 類型的消息存儲庫中,如果消息字段復雜也可以考慮使用 Hash 類型;
對于消息中可索引的信息,將消息的索引信息存入 Zset 類型的消息索引庫中,這樣無論是接收者還是發送者,都可以按照一定規則對歷史消息進行檢索;
通過查詢 Set 類型的消息關系群組庫,查詢該信息的接收者集合,這個集合可以根據一定的規則動態增刪;
將消息 ID 推入 Stream 類型的消息同步庫,每個 Stream 對象對應一個接收者,接收者可以通過 XRANG 命令獲取一個范圍內的未讀信息 ID;
最后,接收者再通過這組 ID,從消息存儲庫中讀取消息原始內容,即完成了一次消息傳遞。
WhyGaussDB(forRedis)?
IM 系統有哪些痛點?高斯 Redis 如何解決這些痛點?
開源 Redsi 數據庫可靠性差,甚至丟數據,會直接導致 IM 系統癱瘓。
GaussDB(forRedis)對數據進行分片,在故障場景下可以自動進行接管,最多可以滿足 N-1 個計算節點故障;存儲層使用華為自研的企業級存儲池 DFVPool,基于分布式、強一致、高性能的先進架構,實現 3AZ6 副本存儲,保證了在任何時間點的數據強一致,故障情況下數據不丟失。
大流量、高并發場景如何支持連接管理,按業務況分散壓力?
GaussDB(forRedis)可以滿足 IM 系統對可用性的要求,客戶端程序通過 ELB 接入 GaussDB(forRedis)實例,可實現自動負載均衡。
突發的高流量、大量的歷史消息數據如何處理?
GaussDB(forRedis)采用先進的存算分離架構,在 IM 系統持續運營的過程中,如果出現突發流量,可以迅速對計算層資源進行秒級擴縮容,快速扛住流量尖峰;歷史消息持續增長時,也可以單獨對存儲層資源大小進行秒級動態調整,最高可擴容至 PB 級。
GaussDB(forRedis)廣泛適用于社交媒體、游戲、電商、推薦系統等領域,在海量并發場景具備極強的高可用能力。如果你需要一款穩定可靠的高性能企業級 KV 數據庫,不妨試試 GaussDB(forRedis)。
審核編輯黃宇
-
通訊系統
+關注
關注
0文章
70瀏覽量
12205 -
華為云
+關注
關注
3文章
2445瀏覽量
17410
發布評論請先 登錄
相關推薦
評論