存儲系統(tǒng)講解——分布式存儲系統(tǒng)問題考慮
分布式系統(tǒng)主要分成存儲模型和計算模型兩類。本文主要描述的是存儲模型的介紹。其中計算模型的分布式系統(tǒng)原理跟存儲模型類似,只是會根據(jù)自身計算特點加一些特殊調(diào)度邏輯進去。
任何一個分布式系統(tǒng)都需要考慮如下5個問題:
1.數(shù)據(jù)如何分布
就像把雞蛋放進籃子里面。一般來說籃子大小是一樣的,當然也有的系統(tǒng)支持不一樣大小的籃子。雞蛋大小也不一樣,有很多系統(tǒng)就把雞蛋給"切割"成一樣大小然后再放。并且有的雞蛋表示對籃子有要求,比如對機房/機架位的要求。
衡量一個數(shù)據(jù)分布算法好不好就看他是否分得足夠均勻,使得所有機器的負載方差足夠小。
2.如何容災
分布式系統(tǒng)一個很重要的定位就是要讓程序自動來管機器,盡量減少人工參與,否則一個分布式系統(tǒng)的運維成本將不可接受。
容災問題非常復雜,有很多很成熟的系統(tǒng)也不敢保證自己做得特別好,那么來看看一個典型的系統(tǒng)都有可能出哪些問題吧:
(1)機器宕機
這是最常見的故障了。系統(tǒng)中最容易出問題的硬盤的年故障率可能能達到10%。這樣算下來,一個有1000臺機器的集群,每一個星期就會有2臺機器宕機。所以在機器數(shù)量大了之后,這是一個很正常的事情。
一般一臺機器出故障之后修復周期是24小時,這個過程是人工接入換設備或者重啟機器。在機器恢復之后內(nèi)存信息完全丟失,硬盤信息可能可以保存。
一個分布式系統(tǒng)必須保證一臺機器的宕機對服務不受影響,并且在修復好了之后再重新放到集群當中之后也能正常工作。
(2)網(wǎng)絡故障
這是最常見且要命的故障。就是該問題會大大增加分布式系統(tǒng)設計的難度。故障一般發(fā)生在網(wǎng)絡擁塞,路由變動,設備異常等情況。出現(xiàn)的問題可能是丟包,可能是延時,也可能是完全失去連接。
有鑒于此,我們一般在設計分布式系統(tǒng)的時候,四層協(xié)議都采用TCP,很少采用UDP/UDT協(xié)議。而且由于TCP協(xié)議并不能完全保證數(shù)據(jù)傳輸?shù)綄γ?,比如我們再發(fā)送數(shù)據(jù),只要數(shù)據(jù)寫入本地緩沖區(qū),操作系統(tǒng)就會返回應用層說發(fā)送成功,但是有可能根本沒送到對面。所以我們一般還需要加上應用層的ACK,來保證網(wǎng)絡層的行為是可預期的。
但是,即使加上應用層的ACK,當發(fā)送請求之后遲遲沒收到ACK。這個時候作為發(fā)送方也并不知道到底對方是直接掛了沒收到請求,還是收到請求之后才掛的。這個尤其是對于一些控制命令請求的發(fā)送尤為致命。
一般系統(tǒng)有兩種方案:
- 發(fā)送查詢命令來判斷到底是哪種情況
- 將協(xié)議設計成"冪等性"(即可重復發(fā)送數(shù)據(jù)并不影響最終數(shù)據(jù)), 然后不停重試
(3)其他異常
比如磁盤壞塊,但是機器并沒有宕機;機器還活著,就是各種操作特別慢;由于網(wǎng)絡擁塞導致一會網(wǎng)絡斷掉,不發(fā)送數(shù)據(jù)之后又好了,一旦探活之后重新使用又掛了等惡心的情況;
這些異常都需要根據(jù)實際情況來分析,在長期工程實踐中去調(diào)整解決。
并且令人非常沮喪的事實是:你在設計階段考慮的異常一定會在實際運行情況中遇到,你沒考慮到的異常也會在實際運行中遇到。所以分布式系統(tǒng)設計的一個原則是:不放過任何一個你看得到的異常。
3.讀寫過程一致性如何保證
一致性的概率很簡單,就是我更新/刪除請求返回之后,別人是否能讀到我新寫的這個值。對于單機系統(tǒng),這個一致性要達到很簡單,大不了是損失一點寫的效率。但是對于分布式系統(tǒng),這個就復雜了。為了容災,一份數(shù)據(jù)肯定有多個副本,那么如何更新這多個副本以及控制讀寫協(xié)議就成了一個大問題。
而且有的寫操作可能會跨越多個分片,這就更復雜了。再加上剛才提到的網(wǎng)絡故障,可能在同步數(shù)據(jù)的時候還會出現(xiàn)各種網(wǎng)絡故障,想想就頭疼。
而且即使達到了一致性,有可能讀寫性能也會受到很大損失。我們設計系統(tǒng)的時候就像一個滑動條,左邊是一致性,右邊是性能,兩者無法同時滿足(CAP原理)。一般的系統(tǒng)會取折衷,設計得比較好的系統(tǒng)能夠讓用戶通過配置來控制這個滑動條的位置,滿足不同類型的需求。
一致性一般怎么折衷呢?我們來看看如下幾種一致性的定義。注意除了強一致性以外,其他幾種一致性并不沖突,一個系統(tǒng)可以同時滿足一種或者幾種一致性特點。
強一致性
不用多說,就是最嚴格的一致性要求。任何時候任何用戶只要寫了,寫請求返回的一霎那,所有其他用戶都能讀到新的值了。
最終一致性
這個也是提得很多的一個概念,很多系統(tǒng)默認提供這種方式的一致性。即最終系統(tǒng)將將達到"強一致性"的狀態(tài),但在之前會有一段不確定的時間,系統(tǒng)處于不一致的狀態(tài)。
會話一致性
這個也很容易理解,能滿足很多場景下的需求。在同一個會話當中,用戶感受到的是"強一致性"的服務。
單調(diào)一致性
這個比會話一致性還要弱一點。他之保證一個用戶在讀到某個數(shù)據(jù)之后,絕對不會讀到比上一次讀到的值更老的數(shù)據(jù)。
4.如何提高性能
分布式系統(tǒng)設計之初就是為了通過堆積機器來增加系統(tǒng)整體性能,所以系統(tǒng)性能也非常重要。性能部分一般會受一致性/容災等設計的影響,會有一定的折衷。
衡量一個分布式系統(tǒng)的性能指標往往有:
- ***容量
- 讀qps
- 寫qps
5.如何保證橫向擴展
橫向擴展是指一個集群的服務能力是否可以通過加機器做到線性擴展。