基本需求
-
可擴展
Memcached和DB可以動態添加,不需要修改程序和重啓任何服務
-
可監控
系統可以監控集羣中某個節點是否異常,資源佔用情況,緩存命中率如何,系統當前壓力,且當壓力到達一個閥值時提供異常報警機制,有詳細的錯誤日誌,便於排查問題
-
可維護
維護人員可以對系統進行修改,測試,部署
-
可定製
集羣系統可以根據應用需求定製分佈式策略
-
高可用(高可讀,高可寫)
集羣系統中單個節點出故障,不影響整個系統的使用
-
容錯
系統出現錯誤,系統可以自動恢復
在Dynamo系統中通過三個參數(N,R,W)來實現可用性和容錯性的平衡。對於數據存儲系統來說,Dynamo的節點採用冗餘存儲是保證容錯性的必要手段,N就代表一份數據將會在系統多少個節點存儲。R表示在讀取某一存儲的數據時,最少參與節點數,也就是最少需要有多少個節點返回存儲的信息纔算是成功讀取了該數據內容。W表示在存儲某一個數據時,最少參與節點數,也就是最少要有多少個節點表示存儲成功纔算是成功存儲了該數據
對於讀操作十分密集寫相對來說較少的情況來說,配置R=1,W=N,則可以實現高讀引擎,系統只要還有一個節點可以讀取數據就可以讀到數據
對於寫比較頻繁的情況來說,那麼可以配置R=N,W=1實現高寫引擎,系統只要還有一個節點可以寫入,就可以保證業務寫入的正常,不過讀取數據進行衝突解決會比較複雜一些
-
容災
當出現災難時,可由異地系統迅速接替本地系統而保證業務的連續性
應用需求
分佈式數據庫
問題
1. 數據存儲的能否平均每臺機器上?
>> 渠道號是手動干預的,數據存儲的分配是不均的
>> 按hash值分配是系統控制的,數據存儲分配是比較平均的
2. 數據訪問控制能否平均到各個負載的機器上?
>> 通過權值來控制,每個機器上都有一個權重,權重大的訪問數量大,權重低的訪問數量小
3. 渠道號01,用戶管理的用戶量達到某個級別時能否再擴展?
>> 可以再擴展,按照HiPi號自動生成的區段來分
4. Consistent Hashing算法的優缺點?
>> 環狀結構。虛擬節點來替換實體節點被分配到環狀某一位置上(根據處理能力不同可以將一個實體節點映射到多個虛擬節點上)。主鍵爲key的節點position = hash(key),在環上按照順時針查找value大於position的第一個虛擬節點,由它對應的實體節點處理
5. 餘數計算分散的優缺點
>> 餘數計算的方法簡單,數據的分散性也相當優秀,但也有其缺點。那就是當添加或移除服務器時,
>> 緩存重組的代價相當巨大。添加服務器後,餘數就會產生鉅變,這樣就無法獲取與保存時相同的服務器,
>> 從而影響緩存的命中率。
6. 動態添加機器時是否可以重啓服務?
>> 不可以
7. 節點離開系統的時候
>> 比如宕機,這個節點上存儲的信息需要繼續備份到其它節點上,雖然節點離開了系統,但是因爲備份的存在,我們通過其他節點可以恢復出本節點的所有信息,備份節點上的信息(離開的節點的信息)也要備份
8. 節點加入系統
>> 從其他節點恢復數據後,其他節點也需要相應減少備份數而一個節點如果只是暫時性的不可達,也就是一個很短的時間內失效(這種情況是最常發生的),那麼需要其他節點暫時接管這個節點的工作,在其可用的時候,把數據增量傳送回該節點
問題 | 技術 | 優點 |
---|---|---|
分佈 | Consistent Hashing | 節點可擴展 |
高可寫性 | 版本鎖 | 與更新率解耦 |
臨時錯誤處理 | 延遲處理和hinted handoff | 提供了高可用和某些負載節點不可用時可持續性提高服務 |
永久性數據錯誤的恢復 | Merkle tree(Hash tree) | 後臺同步不同的備份,比rsync高效 |
節點和故障檢測 | Gossip-based協議(p2p) | 避免了由中心節點提供服務 |
垂直劃分
應用名 | 渠道號 | 數據庫id |
---|---|---|
用戶管理 | 01 | DB1(3),DB4(2) |
權限管理 | 01 | DB2 |
支付管理 | 01 | DB3 |
DB1(3):DB1 - 數據庫1 , (3)- 權重
DB1和DB4要做同步操作 - rsync
延時問題 同步的延時問題,例如:用戶向DB1寫入數據,rsync會向DB4同步數據,在沒有同步完成時DB1與DB2數據不一致性 |
寫問題
用戶1在DB1修改某條數據,這時用戶2在DB4也在修改同一條數據,這時rsync就會覆蓋用戶2修改的數據 |
放棄rsync,使用開源解決方案:
1. Mysql-Proxy - 穩定
2. Amoeba - 中文文檔豐富
Amoeba是一個類似MySQL Proxy 的分佈式數據庫中間代理層軟件,是由陳思儒開發的一個開源的java項目。其主要功能包括讀寫分離,垂直分庫,水平分庫等.
兩者同樣都有Master的單點問題
能否修改Amoeba代碼,實現Master宕機後,隨機選出一個Slave當作Master,或所有的Slave選舉出一個Master。
另外,Mysql 5.1以上支持分區功能,可以解決水平分庫問題。
水平劃分
第一種按渠道號劃分
應用名 | 渠道號 | 數據庫id |
---|---|---|
用戶管理 | 01 | DB1 |
用戶管理 | 02 | DB2 |
用戶管理 | 03 | DB3 |
按渠道劃分問題
假設我的數據是自然數(1-20),資源現在是三臺主機(A,B,C), |
第二種按Hash值來劃分(Hash的第一個字母)
數據庫id | 範圍 |
---|---|
DB1 | 0-9 |
DB2 | a-j |
DB3 | k-t |
DB4 | n-z |
資源名 | URL | Hash值 | 數據庫id |
---|---|---|---|
城市風雲兒1 _09 | ebook.hipidata.cn/story/csfy/1_09.jpg | edsfdflaodfdldfdsf | DB2 |
城市風雲兒1 _07 | ebook.hipidata.cn/story/csfy/1_07.jpg | odsfdflaodfdlskfds | DB3 |
城市風雲兒1 _08 | ebook.hipidata.cn/story/csfy/1_08.jpg | ytrodrlaodfdlsdfsf | DB4 |
Hash算法的比較 |
垂直,水平混合劃分
應用名 | 渠道號 | 數據庫id |
---|---|---|
用戶管理 | 01 | DB1(3),DB6(4) |
權限管理 | 01 | DB2 |
用戶管理 | 02 | DB3 |
權限管理 | 02 | DB4 |
支付管理 | 01,02 | DB5 |
DB1和DB6要做同步操作
分佈式緩存
緩存策略
渠道號 | 緩存id |
---|---|
01 | M1(3),M2(2) |
02 | M4(4),M3(1) |
M1(3):M1 - 緩存機器1 (3)- 權重
Xmemcached client可以設置權重
但是 M1,M2之間的數據同步還不知道怎麼處理的?
>> M1 down -> M2 up(M2爲熱備)
這種雙寫方案,會有成本問題?需要2陪的內存,更多的CPU
方案有:
重新計算Key的分佈->節點故障問題會引起部分用戶數據丟失(有的數據可能沒有關係,但是像用戶登陸的session)
建議方案:
登陸的session及重要數據採用:一致性哈希+雙寫方案 -> 內存是不安全的,如果兩臺機器都掛了(以google的1000臺每天有一臺掛的概率算)那麼每天同時掛的概率是10萬分之一,但是如果發生將是嚴重事件所有用戶都不能使用服務。
>>兩臺機器都寫成功算成功
其他非影響用戶使用的數據採用:一致性哈希(consistent hashing)
用戶登陸的session值如果大小爲1k,那麼1g的內存大概可以放10萬用戶的數據,一臺普通的臺式機4g的內存大概可以放30萬用戶左右,如果我們採用一致性哈希+雙寫方案,只要有四臺機器就可以在Consistent hashing上產生兩個節點,故障率可以降低到100萬分之一,用戶數可以容60萬到70萬的人數同時在線。
4臺普通臺式機的總價也就在1w-1.5w之間(以每臺2k-3k算)
備份方式
客戶端集羣配置lazy複製的方式 |
操作流程
動作 | 步驟 |
---|---|
取數據 | 先取緩存,再取數據庫,最後存緩存 |
更新數據 | a.緩存有數據 - 更新緩存,返回,更新數據庫(異步) b. 緩存沒數據 - 從數據庫取數據,更新數據並放入緩存,更新數據庫(異步) |
插入數據 | 插入緩存,返回,插入數據庫(異步) |
刪除數據 | a.緩存有數據 - 刪除緩存數據,返回,刪除數據庫(異步) |
內存不足時,髒數據問題
異步更新數據庫引擎(第二階段實現)
序號 | case | 操作 |
---|---|---|
1 | 同一條數據,有兩次或多次update | 合併所有更新操作爲一條再更新數據庫 |
2 | 同一條數據,一次update一次delete | 數據庫操作爲delete操作 |
3 | 同一條數據,一次create一次delete | 不操作數據庫 |
4 | 同一條數據,一次create一次update | 合併執行create操作 |
5 | 同一條數據,一次create一次delete一次create | 執行後一次create操作 |
6 | 同一條數據,一次delete一次create | 不操作數據庫 |
7 | 同一條數據,一次delete一次create一次delete | 執行delete |