MySpace DataRelay 分布式數據緩存源碼分析[轉]


MySpace作為.NET架構在互聯網平台最為成功的案例之一,其中非常重要的系統datarelay分布式數據緩存也開源了,DataRelay提供了高性能的緩存系統和消息處理機制,並支持自定義計算Component組件,支持Cluster,有完整的Replication和負載均衡機制,組件都是以windows服務的形式,可以非常靈活的進行部署,客戶端與服務端使用Socket進行通信通訊,另外還可以很方便的擴展各種自定義組件,譬如緩存部分可以使用Memcached,還有最近比較流行Redis。

MySpace雖然開源出來datarelay,但是沒有很好的文檔幫助大家學習,下面將對整套代碼分析,讓大家從全局認識DataRelay這套在.net平台上少有的精品。

CodePlex代碼下載地址:http://datarelay.codeplex.com

MIX 10上的演講:Robots at MySpace: Massive Scaling a .NET Website with the Microsoft Robotic Studio http://ecn.channel9.msdn.com/o9/mix/10/pptx/EX04.pptx

DataRelay架構分析

主要分析DataRelay的架構,分別從DataRelay的特點,系統的物理部署架構,以及系統的內部結構和基於組件規范接口分析,詳細地介紹了DataRelay系統的構架思想以及實現方案。

1.DataRelay的基本特點

DataRelay在參考各種數據緩存功能和設計理念基礎上,在.NET平台體系下設計並實現的一套分布式緩存體系,具有以下特點:

<!--[if !supportLists]-->1) <!--[endif]-->利用現有的Cache解決方案來完成本地Cache功能。現有的Berkeley DB、Memcached、 本地Cache模塊都可以作為插件,接入該系統中,作為本地Cache機制。

<!--[if !supportLists]-->2) <!--[endif]-->自定義序列化和反序列接口,減少存儲空間,提供網絡傳輸效率。

<!--[if !supportLists]-->3) <!--[endif]-->服務部署簡單,對服務節點支持熱插拔。

<!--[if !supportLists]-->4) <!--[endif]-->對符合DataRelay組件接口定義的模塊,通過統一的組件接口管理模塊,對服務端組件支持動態更新。

<!--[if !supportLists]-->5) <!--[endif]-->規范的組件開發接口,大大簡化了組件開發,提高擴展性。

<!--[if !supportLists]-->6) <!--[endif]-->網絡消息分發與同步結合了Replicated Cache和Distributed Cache模式,保證了系統的可靠行。

<!--[if !supportLists]-->7) <!--[endif]-->利用微軟CCR組件(並發與協調運行時(Concurrency and Coordination Runtime))很好的管理消息的異步、並發、協調和失敗處理,保證了系統的高效,穩定。

2 DataRelay的物理架構

DataRelay的物理架構圖如圖1所示,標明了DataRelay在整個網站系統中所處的地位。DataRelay處於整個網站體系中的中間層,不同於一般中間層設計,Web服務器即連接數據庫服務器,也同時連接中間層,這樣設計可以防止單點,如果Web服務器只連接中間層,一旦中間層服務器盪機,整個網站將不能工作,而采用圖中設計方案,一旦中間層服務器當機,Web服務器同樣可以直接訪問數據庫服務器,不至於不工作。當Web服務器請求被Cache的業務對象時,首先請求DataRelay系統,如果該數據在DataRelay系統中存在,將直接返回給Web服務器,當不存在DataRelay系統中,系統將請求轉向數據庫請求,請求到數據首先將數據保存到DataRelay系統中,過后返回給Web服務器。

 datarelay01
<!--[endif]-->

圖1 網站物理架構圖

整個DataRelay集群部署如圖2所示,對於DataRelay的服務器的組織結構,主要有以下三點定義:

<!--[if !supportLists]-->1) <!--[endif]-->Groups

<!--[if !supportLists]-->l <!--[endif]-->不同的組存儲不同的數據,在DataRelay系統中,可以定義多個組,可以針對組進行訪問模式設置。

<!--[if !supportLists]-->2) <!--[endif]-->Clusters

<!--[if !supportLists]-->l <!--[endif]-->多個集群存在一個組中,緩存業務的數據對象根據Distributed Cache模式分配選擇需要保存的集群地址。

<!--[if !supportLists]-->3) <!--[endif]-->Servers

<!--[if !supportLists]-->l <!--[endif]-->DataRelay集群中的服務器,每個集群中服務器之間采用Replicated Cache模式同步保存數據。

datarelay02

圖2 DataRelay集群部署圖

在此結構中,每一組Cluster中的服務器之間會同步數據,保存同樣的數據備份,當Web服務器請求數據,獲取數據服務器節點的算法:

Cluster Index = ObjectID %(# Cluster)

Server Node = Random (Cluster Index)

注:ObjectID 表示存儲數據的類型ID,# Cluster 表示一個Group中有多少個Cluster

當確定了Cluster Index過后,就隨機從該Cluster中取出一台可用的節點服務器處理數據請求。

3 DataRelay內部模塊組成

DataRelay各個模塊之間協調工作,保障了系統的正常運行,各個模塊的設計有各自的責任,DataRelay的內部模塊組成如圖3所示,主要職責如下:

<!--[if !supportLists]-->1) <!--[endif]-->DataRelay.Client:是整個體系提供給客戶端使用的接口,客戶端通過該接口完成數據操作。

<!--[if !supportLists]-->2) <!--[endif]-->DataRelay.Server:服務端的管理組件,控制服務的生命周期,以及擴展組件的熱插拔。

datarelay09

圖3 DataRelay的內部模塊結構圖

<!--[if !supportLists]-->3) <!--[endif]-->DataRelay.Transports.Socket:管理客戶端和服務端的TCP連接池管理。

<!--[if !supportLists]-->4) <!--[endif]-->DataRelay.Common:主要封裝了DataRelay體系中通用操作以及接口定義,主要包括:

<!--[if !supportLists]-->a) <!--[endif]-->RelayComponent.Interface 定義DataRelay的組件接口規范,擴展組件必須實現該接口。

<!--[if !supportLists]-->b) <!--[endif]-->RelayMessage 定義了服務端和客戶端交互的消息類型,是整個體系通信的基礎。

<!--[if !supportLists]-->c) <!--[endif]-->RelayConfiguration Schemas 對體系中的配置文件進行格式驗證,保證配置的准確性。

<!--[if !supportLists]-->5) <!--[endif]-->DataRelay.Components:組件模塊,包含了基本模塊,以及擴展模塊

<!--[if !supportLists]-->a) <!--[endif]-->Storage是真正存放Cache的地方,對於存放的介質有多種,采用Berkeley DB用來持久化存儲數據,也可以為了高性能,采用內存保存Cache。這部分采用DataRelay組件設計規范,可以根據緩存的數據類型以及數據操作方式,擴展合適的存儲組件模塊。

<!--[if !supportLists]-->b) <!--[endif]-->Forwarding :網絡消息分發組件,該組件模塊是整個DataRelay的核心組件,它負責RelayMessage的傳遞,以及消息的處理,它的組成包含以下幾個核心模塊:

<!--[if !supportLists]-->l <!--[endif]-->CCR 是微軟提供的異步編程組件,在Forwarding中它負責管理消息的異步、並發、協調和失敗處理。

<!--[if !supportLists]-->l <!--[endif]-->NodeManager 對DataRelay服務器節點的管理,Forwarding通過它很好的對節點進行分配以及調用,完成網絡消息的分發與同步。

<!--[if !supportLists]-->l <!--[endif]-->PerfCounter 性能計數器[10]主要職責是監控服務器各個節點的服務狀態。

<!--[if !supportLists]-->6) <!--[endif]-->DataRelay.Logging:負責記錄DataRelay的日志。

4序列化和反序列化

DataRelay為了提升序列化效率,對業務緩存對象進行了自定義序列化和反序列化的實現,自定義的序列化數據結構非常緊湊,如圖4自定義序列化數據結構圖所示,32位整型(int32)只占用4個字節,布爾型(bool)占用1個字節,一個長度為2的16位的整型數組(int16[2])占用總共8個字節,數組長度占4個字節,每位16位數占用2個字節。可以看出,DataRelay自行編碼的序列化數據結構相當的緊湊。

datarelay04

圖4 自定義序列化數據結構

通過對序列化和反序列化的實現,做了對比測試,在包含一系列System.Int32類型的數據對象中,使用.NET序列化體系,做序列化生成的字節流是190 KB,如果使用自定義序列化實現,將生成僅僅14 KB,字節流減少超過85%,並且序列化的時間減少14.4s,減少了字節流就減少了網絡的傳輸量以及序列化時間縮短,網絡傳輸性能顯著提高。

5 DataRelay消息(RelayMessage)

RelayMessage是DataRelay框架的通信數據基礎,它負責承載需要緩存的數據在服務端和客戶端之間交互。RelayMessage設計具有以下特點:

<!--[if !supportLists]-->1) <!--[endif]-->規范消息的類型定義,包括get,update,save,delete 等等,隨着框架的擴展,添加擴展的類型。

<!--[if !supportLists]-->2) <!--[endif]-->為了提供傳輸性能,減少網絡傳輸量,消息被序列化成Byte數組存放到服務端,客戶端獲取到數據過后需要反序列。

<!--[if !supportLists]-->3) <!--[endif]-->每個消息具有唯一的ID,如果ID不能確定唯一性,還有ExtendedID 組合使用。

<!--[if !supportLists]-->4) <!--[endif]-->消息TypeID, 針對每種類型的消息都將分配一個TypeID,用來定位緩存的數據位置。

6 DataRelay組件

DataRelay是一套基於組件的體系架構,網絡消息分發是個組件,持久化存儲是個組件,內存存儲是個組件,在DataRelay中任何功能的開發都是一個組件,這樣能很好的提供了系統的擴展性。

當然對與設計組件本身,還具有很強的自主性,每個組件可以定義自己的配置文件,在配置文件中通過反射生成處理自身配置信息的實例,如DataRelay設計的Berkeley DB存儲組件,由於Berkeley DB本身配置就相當復雜,所以DataRelay在設計該組件時,單獨對Berkeley DB配置進行管理,

在DataRelay組件接口定義中,主要是定義了組件要處理消息的接口以及組件自身運行時的信息。特點如下:

<!--[if !supportLists]-->1) <!--[endif]-->服務框架依賴組件的接口操作RelayMessage。

<!--[if !supportLists]-->2) <!--[endif]-->組件可以自定義的配置文件,服務框架通過反射,獲取組件配置信息。

<!--[if !supportLists]-->3) <!--[endif]-->當組件配置文件變動,服務框架會自動讀取重新讀取配置信息。

7 DataRelay 組件容器

DataRelay體系是基於組件模塊的,對於組件的運行需要一個環境,DataRelay提供組件容器,組件容器的主要職責就是維護組件的生命周期,以及調度消息在組件中傳輸。該類實現兩個接口,分別是IRelayNode和IDataHandler。

<!--[if !supportLists]-->1) <!--[endif]-->IRelayNode:該接口定義容器中組件節點的生命周期,以及配置信息,通過該接口,我們可以獲取到容器中各個組件當前的運行狀況,以及相關配置信息。

<!--[if !supportLists]-->2) <!--[endif]-->IDataHandler:該接口是傳輸消息的接口定義,同樣在組件接口定義中也需要集成該接口,該接口定義在整個體系中消息的傳輸。

服務端消息將接收到消息全部傳輸到組件容器中,有組件容器進行消息分發,所以在RelayNode類的設計上,對大量高並發的消息,也采用CCR組件管理。

8 DataRelay 網絡消息分發機制

網絡消息分發在DataRelay中是由Forwarding組件模塊完成的,Forwarding是DataRelay的一個核心模塊,在服務端和客戶端都要使用。它完成DataRelay分布式緩存系統的網絡消息分發與同步。它對消息分發與同步機制分成兩種方式,一種是要實時操作消息,一種是異步操作消息。對於獲取Cache數據,需要實時操作,對於更新、保存、刪除Cache數據可以根據業務場景選擇異步操作。

DataRelay在系統中實現的分布式Cache是Replicated Cache和Distributed Cache相結合的做法:

<!--[if !supportLists]-->1) <!--[endif]-->在對於同一個組下緩存對象的選擇放在某個集群中存儲是采用Distributed Cache方式,根據Mod運算定位存放的集群位置。

<!--[if !supportLists]-->2) <!--[endif]-->對於在同一個組下同一個集群中節點機器上的Cache數據分布采用的是Replicated Cache,即是指在同一個組中的同一個集群下的每個節點所包含的Cache數據是一致的。

Forwarding組件模塊處理Cache數據主要分為2個方面,一方面是獲取數據,另一個方面是更新數據。如圖10示意了在保存和獲取的邏輯過程。假設當前DataRelay系統4台服務器節點,分成2個集群,在同一App組中,需要處理的緩存業務對象數據有2個,2個數據對象的ID分別是120和121。下面分別說明數據在獲取和保存的邏輯過程。

<!--[if !supportLists]-->1) <!--[endif]-->獲取對象Id為121的緩存數據:

<!--[if !supportLists]-->a) <!--[endif]-->獲取對象Id為121配置描述中設置的組名稱:App。

<!--[if !supportLists]-->b) <!--[endif]-->選擇Cluster Index:首先根據Cluster Index 算法,計算得出 Cluster Index = 1 ( 121 % 2 = 1 ) mod ( 業務對象ID,集群數量 )

<!--[if !supportLists]-->c) <!--[endif]-->從該Cluster中隨機選擇一台服務節點,獲取數據。

<!--[if !supportLists]-->2) <!--[endif]-->保存對象Id為120的緩存數據:

<!--[if !supportLists]-->a) <!--[endif]-->獲取對象Id為120配置描述中設置的組名稱:App。

<!--[if !supportLists]-->b) <!--[endif]-->選擇Cluster Index: 首先根據Cluster Index算法,計算得出 Cluster Index = 0 ( 120 % 2 )。

<!--[if !supportLists]-->c) <!--[endif]-->從該Cluster中隨機選擇一台服務器節點,保存數據

<!--[if !supportLists]-->d) <!--[endif]-->該服務器節點會異步發送網絡消息,同步該緩存數據到該Cluster的其他節點中。

datarelay05

圖10 網絡消息分發模型

DataRelay在Forwarding的設計上具有以下幾個特點:

<!--[if !supportLists]-->1) <!--[endif]-->結合了Replicated Cache 和Distributed Cache各自特點,很好的處理了Cache數據在集群上的數據分布與同步。

<!--[if !supportLists]-->2) <!--[endif]-->CCR組件模塊的集成,使得網絡消息處理具有高效行,可靠性。

<!--[if !supportLists]-->3) <!--[endif]-->通過配置可以對消息批量打包,一次性提交,減少網絡通信。

9 DataRelay 服務部署

在服務部署這塊,datarelay也有獨特之處,利用了.net appdomain這個特性,做到可熱插拔,在設計這部分功能時,采用DataRelay系統框架和組件模塊使用不同的AppDomain來加載,將在一個獨立的 AppDomain將所有組件模塊程序集加載到組件容器中,這樣當添加或者更新組件dll和配置文件時,DataRelay將可以動態卸載 AppDomain,過后在從新創建新的 AppDomain,然后將當前組件加載到其中。

這樣就可以不用從新啟動DataRelay服務管理組件更新,在線上運維還是非常方便的,設想一下如果有幾十台Relay服務器需要更新組件,這樣部署很便利很高效。

《程序員2012.11期》 作者:張慶化

原文:http://www.tita.com/blog/tech/myspace-datarelay-分布式數據緩存源碼分析


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM