IM 去中心化概念模型與架構設計

来源:http://www.cnblogs.com/mindwind/archive/2016/08/01/5727036.html
-Advertisement-
Play Games

今天打算寫寫關於 IM 去中心化涉及的架構模型變化和設計思路,去中心化的概念就是說用戶的訪問不是集中在一個數據中心,這裡的去中心是針對數據中心而言的。 站在這個角度而言,實際上並非所有的業務都能做去中心化設計,對於一致性要求越高的業務去中心化越難做。比如電商領域的庫存就是一個對一致性要求很高的業務, ...


今天打算寫寫關於 IM 去中心化涉及的架構模型變化和設計思路,去中心化的概念就是說用戶的訪問不是集中在一個數據中心,這裡的去中心是針對數據中心而言的。

站在這個角度而言,實際上並非所有的業務都能做去中心化設計,對於一致性要求越高的業務去中心化越難做。比如電商領域的庫存就是一個對一致性要求很高的業務,不能超賣也不能少賣,這在單中心容易實現,但多中心純從技術層面感覺無解,可能需要從業務和技術層面一起去做個折衷。

反過來看 IM 的業務場景是非常適合做去中心化設計的,因為其業務場景都是弱一致性需求。打開你的微信或 QQ 仔細觀察下,對大部分人來說與你聯繫最頻繁的實際多是在地域上離你最近的人,人與人之間的心理距離和物理距離會隨著時間漸趨保持一致。所以根據這個特點,按地域來分佈數據中心和聚合人群是比較合適的。

在進入去中心化 IM 架構模型之前,我們先看看中心化架構是怎樣的,分析其關鍵設計再來看如果要去中心化需要做哪些變化?

中心化

IM 的中心化架構並不意味著只有一個數據中心,它也可以是多數據中心的,如下圖。

之所以說它是中心化架構,關鍵特征是其存在共用的數據存儲。部署在兩個數據中心的應用需要共用訪問統一的數據存儲,而這種共用訪問實際是依賴數據中心之間的專線連通,這樣的架構也限制了能選取的數據中心地理位置的距離。而實現去中心架構的關鍵點就在於規避跨數據中心的共用存儲訪問,使得應用在其自身數據中心實現訪問閉環。

我們這裡只分析下實現 IM 消息互通這個最重要場景下共用數據存儲里需要存些什麼數據呢?一個是用戶上線後的「座標」,主要指用戶本次線上接入了哪台機器的哪根連接,這個「座標」用於線上消息投遞。而另一方面若用戶離線時,別人給它發消息,這些消息也需要存儲下來,一般稱為用戶的「離線消息」,下次用戶上線就可以自動收取自己的離線消息。

中心化架構實際能做到的極致就是把讀實現自有數據中心閉環,而寫依然需要向主數據中心所在的存儲寫入。而 IM 的寫入場景還不算是一個低頻操作,那麼要實現去中心化架構關鍵點就在如何解決寫的問題上。

去中心化

在設計 IM 的去中心化架構之前,希望去實現這個架構並編寫代碼時,不需要去考慮最終部署到底是去中心的還是中心的。編碼時就像開發中心化架構一樣去實現場景的功能,而去中心化的能力做為純基礎的技術能力,通過附加的方式來獲得,先看看架構圖的變化,如下。

這裡的變化是為「座標」增加一個「數據中心」緯度,當按通用的方式去本地存儲定位用戶時,發現一個非本地的座標時消息該怎麼投遞?這裡可以在每個本地數據中心額外添加一個消息網關程式,註冊到本地存儲中,並負責接收所有非本地座標的消息,這有點像路由網路中的邊界網關。

消息網關統一接收應當發往其他數據中心的消息,以實現跨數據中心的消息流轉。這裡有個疑問是其他數據中心的「座標」是怎麼跑到本地來的?離線消息的場景又該如何處理呢?關於這兩個問題,就涉及到我們解決跨數據中心同步數據的關鍵技術了。

關鍵技術

結合 IM 的業務場景,實際它對同步的延時具有一定的容忍度。所以我覺得基於 Gossip 協議的小道消息傳播特性就能很好的滿足這個同步場景。

關於 Gossip 我是在新近的 NoSQL 資料庫 Cassandra 上聽說的,後來 Redis Cluster 也利用了該協議來實現無中心化集群架構。但 Gossip 協議可不是什麼新東西,實際關於它的誕生可以追溯到好幾十年前的施樂研究中心,就是為瞭解決資料庫同步問題被我們的前前前輩想出來的。

這個協議的靈感來自於辦公室小道消息的傳播路徑,當一個人知道了一條小道消息,他碰到一個朋友並隨口告訴了他,朋友又告訴了朋友的朋友,沒多久整個辦公室都知道了,也就完成了信息的同步。借用這個模型,實際上我們需要同步的信息就是用戶的線上「座標」和「離線消息」。

因為 Gossip 自好幾十年前已經有很多論文證明並公開發表,而且近年也有 Cassandra 和 Redis 的成功工程實踐,所以我就先不用去懷疑其可行性,而是直接利用其結論了。根據其特性,分析 IM 的去中心場景在引入 Gossip 後有些什麼可供觀察的變化和值得註意的方面。

在一個稍具規模的 IM 場景下,用戶總是在上上下下,消息也在不停的在「線上」和「離線」之間變化,所以需要通過 Gossip 同步的信息是時時存在的。所以假設我們在某個時刻去拍一個快照(實際做不到),得到的結果是多個數據中心的數據肯定是不一致的,幾乎不存在所謂的全局最終一致性的某一時刻。在這樣的客觀環境下,對 IM 的業務場景有多大影響?

當用戶A在 IDC#1 線上,用戶B 在 IDC#2 剛上線,這裡存在一個同步時差,那麼此時用戶A給用戶B發消息,在本地沒有用戶B的座標,所以進入離線消息池。用戶B此時不能立刻收到用戶A的消息,但離線消息池會在隨後通過 Gossip 協議同步到用戶B所在的 IDC#2,用戶B此時就可以通過離線消息收取用戶A的消息。

上面描述了一種臨界場景,在這種臨界場景下,用戶收消息存在延時。而這種臨界場景實際上並不是常態,而且 IM 用戶實際對這種剛上線的消息延時存在很高的容忍度。這一點我想大家用 QQ 可能體會過,有時一上線都一分鐘了,還會收到之前的離線消息,我不知道這是有意的延時還是真有這麼長的系統延時。

那麼使用 Gossip 協議從理論上來估算下會產生多久的延時?假設我們在全國東西南北中各部署一個數據中心,一共五個。五個數據中心之間無專線,走公網互通,網路延時最大 200 ms。使用 Gossip 完成在五個數據中心的最終一致性同步最大需要多長時間?這裡我直接引用 Gossip 論文結論:

Cycles = log(N) + ln(N) + O(1)

當 N=5 時,完成全部同步,需要節點間私下傳播的次數,套用公式得到 3.3 次,取整得 4 次。按最大網路延時 200 ms,每次 Gossip 交換信息間隔 100 ms,那麼協議本身固有延時大約 4x200 + 4x100 = 1.2s,而再算上程式開銷,這個延時很可能在數秒內波動,這個量級的延時對於少數的臨界場景是完全可以接受的。

總結

本文的標題是概念模型,但它不像另外一篇《RPC 的概念模型與實現解析》跟了實現解析,說明這隻是一個理論推導。因為裡面最關鍵的是如何配合 Gossip 的共用存儲似乎沒有找到特別適合的產品,要是自己做一個呢就會產生一種今天只想出去兜兜風,卻要先自己動手造輛車的感覺。

參考

[1]. Wikipedia. Gossip protocol. 2016.03.29
[2]. ALVARO VIDELA. GOSSIP PROTOCOLS, WHERE TO START. 2015.12.02
[3]. Anne-Marie et al. Gossiping in Distributed Systems. 2007
[4]. Márk Jelasity. Gossip Protocols
[5]. Alberto Montresor. Gossip protocols for large-scale distributed systems. 2010


寫點程式世間的文字,畫點生活瞬間的畫兒。
微信公眾號「瞬息之間」,遇見了不妨就關註看看。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 一、prototype和__proto__的概念 prototype是函數的一個屬性(每個函數都有一個prototype屬性),這個屬性是一個指針,指向一個對象。它是顯示修改對象的原型的屬性。 __proto__是一個對象擁有的內置屬性(請註意:prototype是函數的內置屬性,__proto__ ...
  • 常常會在程式中遇到多個子類有共同的方法已經相似的調用過程。這個時候我們就可以使用模板模式來解決這些重覆性的工作,例如我們買東西的時候一般都是挑選商品、付款這樣的步驟,區別僅僅是挑選的商品品種不一樣而已,這個時候我們就可以使用模板模式。那麼模板模式需要怎麼來實現呢,如下圖 代碼如下: public c ...
  • 本文為作者原創,如需轉載請註明出處。 1. 實現的功能 一主多備,自動選主 啟動記錄可查詢 一主多備,自動選主 啟動記錄可查詢 2. 前置需求 一臺資料庫用以記錄,如 MySQL、Redis、MongoDB 等。關鍵是設計中的思想,用啥資料庫都行。 3. 設計實現 在資料庫中,存一張表,結構如下: ...
  • 橋接模式的定義: 將抽象化(Abstraction)與實現化(Implementation)脫耦,使得二者可以獨立地變化。 橋接模式結構圖: 橋接模式中得角色: 抽象化(Abstraction)角色:抽象化給出的定義,並保存一個對實現化對象的引用。 修正抽象化(Refined Abstraction ...
  • 1. 理解MVC MVC是一種經典的設計模式,全名為Model-View-Controller,即模型-視圖-控制器。 其中,模型是用於封裝數據的載體,例如,在Java中一般通過一個簡單的POJO(Plain Ordinary Java Object)來表示,其本質是一個普通的Java Bean,包 ...
  • 1.用法示例1 String str = QString("%1 %2 %3 %4 %5 %6 %7 %8 %9 %10 %11").arg("1","2","3","4","5","6","7","8","9"); qDebug() << str << endl; 輸出 "1 2 3 4 5 6 ...
  • 分散式事務與本地事務一樣,包含原子性(Atomicity)、一致性(Consistency)、隔離性(Isolation)和持久性(Durability)。兩階段提交是保證分散式事務中原子性的重要方法。本文重點介紹了兩階段提交的原理,PostgreSQL中兩階段提交介面,以及Java中兩階段提交介面... ...
  • 一、概述 單例模式確保一個類只有一個實例,並提供一個安全的訪問點。 二、解決問題 從概述中我們知道,單例模式就是保證系統的一個類只有一個實例。它的作用就是控制受限資源的訪問,確保任何時刻都只有一個線程在訪問一個受保護的資源。或者確保行為和狀態的一致性,避免異常行為。在java web的程式中可能用到 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...