IM全稱是『Instant Messaging』,中文名是即時通信。在這個高度信息化的移動互聯網時代,生活中IM類產品已經成爲必備品,比較有名的如釘釘、微信、QQ等以IM爲核心功能的產品。固然目前微信已經成長爲一個生態型產品,但其核心功能仍是IM。還有一些非以IM系統爲核心的應用,最典型的如一些在線遊戲、社交應用,IM也是其重要的功能模塊。能夠說,IM系統已是任何一個帶有社交屬性的應用須要具有的基礎功能,網絡上對於這類系統的設計與實現的討論也愈來愈多。後端
IM系統在互聯網初期即存在,其基礎技術架構在這十幾年的發展中更新迭代屢次,從早期的CS、P2P架構,到如今後臺已經演變爲一個複雜的分佈式系統,涉及移動端、網絡通訊、協議、安全、存儲和搜索等技術的方方面面。IM系統中最核心的部分是消息系統,消息系統中最核心的功能是消息的同步、存儲和檢索:緩存
本篇文章內容主要涉及IM系統中的消息系統架構,會介紹一種基於阿里雲表格存儲Tablestore的Timeline模型構建的消息系統。基於Tablestore Timeline構建的現代消息系統,可以同時支持消息系統的衆多高級特性,包括『多端同步』、『消息漫遊』和『在線檢索』。在性能和規模上,可以作到全量消息雲端存儲和索引,百萬TPS寫入以及毫秒級延遲的消息同步和檢索能力。安全
以後咱們會繼續發表兩篇文章,來更詳細介紹Tablestore Timeline模型概念及使用:服務器
傳統架構下,消息是先同步後存儲。對於在線的用戶,消息會直接實時同步到在線的接收方,消息同步成功後,並不會在服務端持久化。而對於離線的用戶或者消息沒法實時同步成功時,消息會持久化到離線庫,當接收方從新鏈接後,會從離線庫拉取全部未讀消息。當離線庫中的消息成功同步到接收方後,消息會從離線庫中刪除。傳統的消息系統,服務端的主要工做是維護髮送方和接收方的鏈接狀態,並提供在線消息同步和離線消息緩存的能力,保證消息必定可以從發送方傳遞到接收方。服務端不會對消息進行持久化,因此也沒法支持消息漫遊。消息的持久化存儲及索引一樣只能在接收端本地實現,數據可靠性極低。微信
現代架構下,消息是先存儲後同步。先存儲後同步的好處是,若是接收方確認接收到了消息,那這條消息必定是已經在雲端保存了。而且消息會有兩個庫來保存,一個是消息存儲庫,用於全量保存全部會話的消息,主要用於支持消息漫遊。另外一個是消息同步庫,主要用於接收方的多端同步。消息從發送方發出後,通過服務端轉發,服務端會先將消息保存到消息存儲庫,後保存到消息同步庫。完成消息的持久化保存後,對於在線的接收方,會直接選擇在線推送。但在線推送並非一個必須路徑,只是一個更優的消息傳遞路徑。對於在線推送失敗或者離線的接收方,會有另一個統一的消息同步方式。接收方會主動的向服務端拉取全部未同步消息,但接收方什麼時候來同步以及會在哪些端來同步消息對服務端來講是未知的,因此要求服務端必須保存全部須要同步到接收方的消息,這是消息同步庫的主要做用。對於新的同步設備,會有消息漫遊的需求,這是消息存儲庫的主要做用,在消息存儲庫中,能夠拉取任意會話的全量歷史消息。消息檢索的實現依賴於對消息存儲庫內消息的索引,一般是一個近實時(NRT,near real time)的索引構建過程,這個索引一樣是在線的。網絡
以上就是傳統架構和現代架構的一個簡單的對比,現代架構上整個消息的同步、存儲和索引流程,並無變複雜太多。現代架構的實現本質上是把傳統架構內本地存儲和索引都搬到雲上,最大挑戰是須要集中管理全量消息的存儲和索引,帶來的好處是能實現多端同步、消息漫遊以及在線檢索。能夠看到現代架構中最核心的就是兩個消息庫『消息同步庫』和『消息存儲庫』,以及對『消息存儲庫』的『消息索引』的實現,接下來咱們逐步拆解這幾個核心的設計和實現。數據結構
在深刻講解消息系統的設計和實現以前,須要對消息系統內的幾個基本概念和基礎模型有一個理解。網上分析的不少的不一樣類型的消息系統實現,實現差別上主要在消息同步和存儲的方案上,在消息的數據模型上其實有很大的共性。圍繞數據同步模型的討論主要在『讀擴散』、『寫擴散』和『混合模式』這三種方案,目前尚未更多的選擇。而對於數據模型的抽象,尚未一個標準的定義。架構
本章節會介紹下表格存儲Tablestore提出的Timeline模型,這是一個對消息系統內消息模型的一個抽象,能簡化和更好的讓開發者理解消息系統內的消息同步和存儲模型,基於此模型咱們會再深刻探討消息的同步和存儲的選擇和實現。異步
Timeline是一個對消息抽象的邏輯模型,該模型會幫助咱們簡化對消息同步和存儲模型的理解,而消息同步庫和存儲庫的設計和實現也是圍繞Timeline的特性和需求來展開。分佈式
如圖是Timeline模型的一個抽象表述,Timeline能夠簡單理解爲是一個消息隊列,但這個消息隊列有以下特性:
消息同步能夠基於Timeline很簡單的實現,圖中的例子中,消息發送方是A,消息接收方是B,同時B存在多個接收端,分別是B一、B2和B3。A向B發送消息,消息須要同步到B的多個端,待同步的消息經過一個Timeline來進行交換。A向B發送的全部消息,都會保存在這個Timeline中,B的每一個接收端都是獨立的從這個Timeline中拉取消息。每一個接收端同步完畢後,都會在本地記錄下最新同步到的消息的SequenceId,即最新的一個位點,做爲下次消息同步的起始位點。服務端不會保存各個端的同步狀態,各個端都可以在任意時間從任意點開始拉取消息。
消息存儲也是基於Timeline實現,和消息同步惟一的區別是,消息存儲要求服務端可以對Timeline內的全部數據進行持久化,而且消息採用會話順序來保存,須要自定義順序ID。
消息檢索基於Timeline提供的消息索引來實現,能支持比較靈活的多字段索引,根據業務的不一樣可有自由度較高的定製。
如圖是基於Timeline的消息存儲模型,消息存儲要求每一個會話都對應一個獨立的Timeline。如圖例子所示,A與B/C/D/E/F均發生了會話,每一個會話對應一個獨立的Timeline,每一個Timeline內存有這個會話中的全部消息,消息根據會話順序排序,服務端會對每一個Timeline進行持久化存儲,也就擁有了消息漫遊的能力。
消息同步模型會比消息存儲模型稍複雜一些,消息的同步通常有讀擴散(也叫拉模式)和寫擴散(也叫推模式)兩種不一樣的方式,分別對應不一樣的Timeline物理模型。
如圖是讀擴散和寫擴散兩種不一樣同步模式下對應的不一樣的Timeline模型,按圖中的示例,A做爲消息接收者,其與B/C/D/E/F發生了會話,每一個會話中的新的消息都須要同步到A的某個端,看下讀擴散和寫擴散兩種模式下消息如何作同步。
針對IM這種應用場景,消息系統一般會選擇寫擴散這種消息同步模式。IM場景下,一條消息只會產生一次,可是會被讀取屢次,是典型的讀多寫少的場景,消息的讀寫比例大概是10:1。若使用讀擴散同步模式,整個系統的讀寫比例會被放大到100:1。一個優化的好的系統,必須從設計上去平衡這種讀寫壓力,避免讀或寫任意一維觸碰到天花板。因此IM系統這類場景下,一般會應用寫擴散這種同步模式,來平衡讀和寫,將100:1的讀寫比例平衡到30:30。固然寫擴散這種同步模式,還須要處理一些極端場景,例如萬人大羣。針對這種極端寫擴散的場景,會退化到使用讀擴散。一個簡單的IM系統,一般會在產品層面限制這種大羣的存在,而對於一個高級的IM系統,會採用讀寫擴散混合的同步模式,來知足這類產品的需求。採用混合模式,會根據數據的不一樣類型和不一樣的讀寫負載,來決定用寫擴散仍是讀擴散。
如圖是一個典型的消息系統架構,架構中包含幾個重要組件:
對於在線的設備,能夠由消息服務器主動推送至在線設備端。對於離線設備,登陸後會主動向服務端同步消息。每一個設備會在本地保留有最新一條消息的順序ID,向服務端同步該順序ID後的全部消息。
本篇文章主要介紹了現代IM系統中消息系統所須要具有的能力,對比了傳統架構和現代架構。爲方便接下來的深刻探討,介紹了表格存儲Tablestore推出的Timeline模型,以及在IM系統中消息存儲和消息同步模型的基本概念和策略,最後介紹了一個典型的架構設計。
本文爲雲棲社區原創內容,未經容許不得轉載。