倪超 著
適讀人群 :大型網(wǎng)站和分布式系統(tǒng)的開(kāi)發(fā)人員,對(duì)分布式一致性和ZooKeeper感興趣的IT從業(yè)人員。
國(guó)內(nèi)罕見(jiàn)系統(tǒng)講解ZooKeeper這一應(yīng)用廣泛、成熟的分布式協(xié)調(diào)框架之技術(shù)書。
原理深入,闡述清晰,覆蓋ACID、CAP、BASE,二階段/三階段提交,Paxos、ZAB協(xié)議等熱門話題。
徹底剖析分布式一致性問(wèn)題,并給出相應(yīng)系統(tǒng)思路,以及完整解決方案及實(shí)戰(zhàn)參考。
無(wú)論開(kāi)發(fā)人員,還是運(yùn)維人士,都可通過(guò)書中ZooKeeper使用方法、內(nèi)部實(shí)現(xiàn)及運(yùn)維技巧來(lái)全面提升。
《Paxos到Zookeeper 分布式一致性原理與實(shí)踐》從分布式一致性的理論出發(fā),向讀者簡(jiǎn)要介紹幾種典型的分布式一致性協(xié)議,以及解決分布式一致性問(wèn)題的思路,其中重點(diǎn)講解了Paxos和ZAB協(xié)議。同時(shí),本書深入介紹了分布式一致性問(wèn)題的工業(yè)解決方案——ZooKeeper,并著重向讀者展示這一分布式協(xié)調(diào)框架的使用方法、內(nèi)部實(shí)現(xiàn)及運(yùn)維技巧,旨在幫助讀者全面了解ZooKeeper,并更好地使用和運(yùn)維ZooKeeper。全書共8章,分為五部分:前一部分(第1章)主要介紹了計(jì)算機(jī)系統(tǒng)從集中式向分布式系統(tǒng)演變過(guò)程中面臨的挑戰(zhàn),并簡(jiǎn)要介紹了ACID、CAP和BASE等經(jīng)典分布式理論;第二部分(第2~4章)介紹了2PC、3PC和Paxos三種分布式一致性協(xié)議,并著重講解了ZooKeeper中使用的一致性協(xié)議——ZAB協(xié)議;第三部分(第5~6章)介紹了ZooKeeper的使用方法,包括客戶端API的使用以及對(duì)ZooKeeper服務(wù)的部署與運(yùn)行,并結(jié)合真實(shí)的分布式應(yīng)用場(chǎng)景,總結(jié)了ZooKeeper使用實(shí)踐;第四部分(第7章)對(duì)ZooKeeper的架構(gòu)設(shè)計(jì)和實(shí)現(xiàn)原理進(jìn)行了深入分析,包含系統(tǒng)模型、Leader選舉、客戶端與服務(wù)端的工作原理、請(qǐng)求處理,以及服務(wù)器角色的工作流程和數(shù)據(jù)存儲(chǔ)等;第五部分(第8章)介紹了ZooKeeper的運(yùn)維實(shí)踐,包括配置詳解和監(jiān)控管理等,重點(diǎn)講解了如何構(gòu)建一個(gè)高可用的ZooKeeper服務(wù)。
倪超,阿里巴巴集團(tuán)高級(jí)研發(fā)工程師,國(guó)家認(rèn)證系統(tǒng)分析師,畢業(yè)于杭州電子科技大學(xué)計(jì)算機(jī)系。2010年加入阿里巴巴中間件團(tuán)隊(duì)擔(dān)任研發(fā)實(shí)習(xí)崗位,一直從事ZooKeeper的開(kāi)發(fā)與運(yùn)維工作,從中學(xué)習(xí)與總結(jié)了不少分布式一致性相關(guān)的理論與實(shí)踐經(jīng)驗(yàn),尤其對(duì)ZooKeeper及其相關(guān)技術(shù)有非常深入的研究。目前在中間件團(tuán)隊(duì)專家組任職產(chǎn)品經(jīng)理,負(fù)責(zé)分布式產(chǎn)品的產(chǎn)品化和云計(jì)算化改造工作。
★感謝軟件開(kāi)源和知識(shí)開(kāi)源,新浪愛(ài)彩利用各開(kāi)源軟件和算法,構(gòu)建了核心交易系統(tǒng)和分布式中間件系統(tǒng):利用ZooKeeper 構(gòu)建了分布式 ID 生成器、分布式單例控制器、Dubbo RPC 框架,以及基于 Hadoop/JStorm/Spark 體系的業(yè)務(wù)系統(tǒng),等等。ZooKeeper 的穩(wěn)定性和對(duì)一致性的保證一直為業(yè)界所稱道,在大量的分布式系統(tǒng)和開(kāi)源組件中得到應(yīng)用。本書是作者在長(zhǎng)期使用 ZooKeeper 后深入研究其算法原理和源代碼的總結(jié),將對(duì)讀者在分布式一致性的理論學(xué)習(xí)與實(shí)踐上有啟發(fā)意義。
——新浪愛(ài)彩首席架構(gòu)師 周鋒
★分布式一致性是中國(guó)銀聯(lián)風(fēng)控系統(tǒng)架構(gòu)與設(shè)計(jì)的重要目標(biāo),新一代的銀聯(lián)反洗錢交易實(shí)時(shí)分析系統(tǒng)采用 Storm 進(jìn)行大數(shù)據(jù)的實(shí)時(shí)計(jì)算,ZooKeeper 作為 Storm 的重要組成部分,為數(shù)據(jù)一致性提供了關(guān)鍵保障。本書深入淺出地描述了分布式一致性這一問(wèn)題的由來(lái),并對(duì) ZooKeeper 在 Storm、Hadoop 和 HBase 等大型分布式系統(tǒng)中的應(yīng)用場(chǎng)景進(jìn)行了詳盡介紹,針對(duì) ZooKeeper在分布式系統(tǒng)中的業(yè)務(wù)實(shí)踐與運(yùn)維保障提供了重要參考。
——中國(guó)銀聯(lián)反洗錢系統(tǒng)核心負(fù)責(zé)人 羅科勤
★分布式地理信息系統(tǒng)的研發(fā)挑戰(zhàn)主要在于它的地理信息共享和分布式協(xié)調(diào)操作,ZooKeeper 作為一個(gè)針對(duì)大型分布式系統(tǒng)的高可靠協(xié)調(diào)系統(tǒng),提供的功能包括:配置維護(hù)、名字服務(wù)、分布式同步和組服務(wù)等,正好能夠解決地信系統(tǒng)中的諸多分布式一致性問(wèn)題。該書兼顧分布式一致性的理論和實(shí)踐,并重點(diǎn)講解了 ZooKeeper,適合不同層次的讀者閱讀。
——浙江省測(cè)繪局地信系統(tǒng)設(shè)計(jì)師 王浩烽
★騰訊在 2010 年啟動(dòng)建設(shè)開(kāi)放云平臺(tái)時(shí),面臨著海量第三方虛擬機(jī)之間訪問(wèn)限制規(guī)則以及內(nèi)網(wǎng)透明負(fù)載均衡配置的管理等問(wèn)題。引入 ZooKeeper 之后,一直穩(wěn)定運(yùn)行至今,利用其發(fā)布訂閱特性很好地保證了規(guī)則數(shù)據(jù)和配置信息的一致性,確保了服務(wù)的可用性。本書從分布式一致性理論出發(fā),再以ZooKeeper 系統(tǒng)為例詳盡地介紹了這個(gè)開(kāi)源系統(tǒng)的架構(gòu)與實(shí)現(xiàn),并結(jié)合實(shí)際的應(yīng)用場(chǎng)景和運(yùn)維經(jīng)驗(yàn)為在實(shí)戰(zhàn)中面臨分布式問(wèn)題的讀者提供了重要參考。
——騰訊企業(yè)級(jí)產(chǎn)品中心架構(gòu)師 陳盛龍
★一致性是計(jì)算機(jī)學(xué)科中“硬”和重要的問(wèn)題之一,可見(jiàn)寫這樣一個(gè)主題挑戰(zhàn)之大。阿里巴巴業(yè)務(wù)龐大,倪超之前維護(hù)的為整個(gè)集團(tuán)提供一致性方案的 ZooKeeper 集群,場(chǎng)景之復(fù)雜、規(guī)模之大在國(guó)內(nèi)甚至世界上都可能是罕見(jiàn)的。本人由于工作需要對(duì) Paxos 和 ZooKeeper 進(jìn)行了粗淺的學(xué)習(xí),所以有機(jī)會(huì)和倪超有過(guò)這方面的交流,樂(lè)自不言,獲益彼多。本書兼顧理論與實(shí)踐,希望讓讀者讀完之后有所提升:使用上知其所以然,架構(gòu)上能選擇出合適又低成本的方案。
——阿里巴巴 Dubbo 框架、PaaS 平臺(tái)資深架構(gòu)師 & 核心開(kāi)發(fā) 李鼎
★在我的工作經(jīng)歷中,有多次與分布式系統(tǒng)的配置管理中心打過(guò)交道,比如之前在老東家阿里巴巴負(fù)責(zé) HSF 服務(wù)框架,以及最近在陌陌負(fù)責(zé)的 MOA 服務(wù)框架的工作。基于簡(jiǎn)單可用的原則,這些場(chǎng)景都沒(méi)有選擇使用 ZooKeeper,而是自己實(shí)現(xiàn)了配置管理系統(tǒng)。但最近在參與分布式緩存服務(wù)建設(shè)的過(guò)程中,我們發(fā)現(xiàn)已經(jīng)無(wú)法再繞開(kāi)分布式協(xié)調(diào)問(wèn)題,這時(shí),ZooKeeper作為行業(yè)的成熟實(shí)踐就成了我們的優(yōu)選。這本書的作者倪超是我在阿里的同事,一直從事著與 ZooKeeper 相關(guān)的工作 在這個(gè)領(lǐng)域積累了豐富的經(jīng)驗(yàn)。本書從理論、設(shè)計(jì)實(shí)現(xiàn)和應(yīng)用場(chǎng)景等多個(gè)方面對(duì) ZooKeeper 進(jìn)行了深入介紹,非常值得一讀。
——陌陌基礎(chǔ)平臺(tái)部主管 宓學(xué)強(qiáng)
★搜狐從 2009 年微博時(shí)代初期就利用 ZooKeeper 的發(fā)布與訂閱模型實(shí)現(xiàn)了對(duì) CDN URL 和一些基本管理配置的動(dòng)態(tài)加載。至今 ZooKeeper 已經(jīng)被運(yùn)用在了搜狐各大業(yè)務(wù)線上,完成了許多分布式高可用服務(wù)的構(gòu)建,范圍涉及分布式緩存、服務(wù)化框架和前端業(yè)務(wù)系統(tǒng)等等,幫助團(tuán)隊(duì)解決了分布式方面的主要技術(shù)障礙,大大提高了業(yè)務(wù)穩(wěn)定性和運(yùn)維效率。本書全面詳盡地介紹了分布式環(huán)境中各個(gè)典型場(chǎng)景下的 ZooKeeper 應(yīng)用實(shí)例,為讀者構(gòu)建自己的分布式高可用服務(wù)提供了參考。
——搜狐移動(dòng)事業(yè)部高級(jí)運(yùn)維主管 劉鵬
第1章 分布式架構(gòu)
1.1 從集中式到分布式
1.1.1 集中式的特點(diǎn)
1.1.2 分布式的特點(diǎn)
1.1.3 分布式環(huán)境的各種問(wèn)題
1.2 從ACID到CAP/BASE
1.2.1 ACID
1.2.2 分布式事務(wù)
1.2.3 CAP和BASE理論
小結(jié)
第2章 一致性協(xié)議
2.1 2PC與3PC
2.1.1 2PC
2.1.2 3PC
2.2 Paxos算法
2.2.1 追本溯源
2.2.2 Paxos理論的誕生
2.2.3 Paxos算法詳解
小結(jié)
第3章 Paxos的工程實(shí)踐
3.1 Chubby
3.1.1 概述
3.1.2 應(yīng)用場(chǎng)景
3.1.3 設(shè)計(jì)目標(biāo)
3.1.4 Chubby技術(shù)架構(gòu)
3.1.5 Paxos協(xié)議實(shí)現(xiàn)
3.2 Hypertable
3.2.1 概述
3.2.2 算法實(shí)現(xiàn)
小結(jié)
第4章 ZooKeeper與Paxos
4.1 初識(shí)ZooKeeper
4.1.1 ZooKeeper介紹
4.1.2 ZooKeeper從何而來(lái)
4.1.3 ZooKeeper的基本概念
4.1.4 為什么選擇ZooKeeper
4.2 ZooKeeper的ZAB協(xié)議
4.2.1 ZAB協(xié)議
4.2.2 協(xié)議介紹
4.2.3 深入ZAB協(xié)議
4.2.4 ZAB與Paxos算法的聯(lián)系與區(qū)別
小結(jié)
第5章 使用ZooKeeper
5.1 部署與運(yùn)行
5.1.1 系統(tǒng)環(huán)境
5.1.2 集群與單機(jī)
5.1.3 運(yùn)行服務(wù)
5.2 客戶端腳本
5.2.1 創(chuàng)建
5.2.2 讀取
5.2.3 更新
5.2.4 刪除
5.3 Java客戶端API使用
5.3.1 創(chuàng)建會(huì)話
5.3.2 創(chuàng)建節(jié)點(diǎn)
5.3.3 刪除節(jié)點(diǎn)
5.3.4 讀取數(shù)據(jù)
5.3.5 更新數(shù)據(jù)
5.3.6 檢測(cè)節(jié)點(diǎn)是否存在
5.3.7 權(quán)限控制
5.4 開(kāi)源客戶端
5.4.1 ZkClient
5.4.2 Curator
小結(jié)
第6章 ZooKeeper的典型應(yīng)用場(chǎng)景
6.1 典型應(yīng)用場(chǎng)景及實(shí)現(xiàn)注
6.1.1 數(shù)據(jù)發(fā)布/訂閱
6.1.2 負(fù)載均衡
6.1.3 命名服務(wù)
6.1.4 分布式協(xié)調(diào)/通知
6.1.5 集群管理
6.1.6 Master選舉
6.1.7 分布式鎖
6.1.8 分布式隊(duì)列
小結(jié)
6.2 ZooKeeper在大型分布式系統(tǒng)中的應(yīng)用
6.2.1 Hadoop
6.2.2 HBase
6.2.3 Kafka
6.3 ZooKeeper在阿里巴巴的實(shí)踐與應(yīng)用
6.3.1 案例一 消息中間件:Metamorphosis
6.3.2 案例二 RPC服務(wù)框架:Dubbo
6.3.3 案例三 基于MySQL Binlog的增量訂閱和消費(fèi)組件:Canal
6.3.4 案例四 分布式數(shù)據(jù)庫(kù)同步系統(tǒng):Otter
6.3.5 案例五 輕量級(jí)分布式通用搜索平臺(tái):終搜
6.3.6 案例六 實(shí)時(shí)計(jì)算引擎:JStorm
小結(jié)
第7章 ZooKeeper技術(shù)內(nèi)幕
7.1 系統(tǒng)模型
7.1.1 數(shù)據(jù)模型
7.1.2 節(jié)點(diǎn)特性
7.1.3 版本――保證分布式數(shù)據(jù)原子性操作
7.1.4 Watcher――數(shù)據(jù)變更的通知
7.1.5 ACL――保障數(shù)據(jù)的安全
7.2 序列化與協(xié)議
7.2.1 Jute介紹
7.2.2 使用Jute進(jìn)行序列化
7.2.3 深入Jute
7.2.4 通信協(xié)議
7.3 客戶端
7.3.1 一次會(huì)話的創(chuàng)建過(guò)程
7.3.2 服務(wù)器地址列表
7.3.3 ClientCnxn:網(wǎng)絡(luò)I/O
7.4 會(huì)話
7.4.1 會(huì)話狀態(tài)
7.4.2 會(huì)話創(chuàng)建
7.4.3 會(huì)話管理
7.4.4 會(huì)話清理
7.4.5 重連
7.5 服務(wù)器啟動(dòng)
7.5.1 單機(jī)版服務(wù)器啟動(dòng)
7.5.2 集群版服務(wù)器啟動(dòng)
7.6 Leader選舉
7.6.1 Leader選舉概述
7.6.2 Leader選舉的算法分析
7.6.3 Leader選舉的實(shí)現(xiàn)細(xì)節(jié)
7.7 各服務(wù)器角色介紹
7.7.1 Leader
7.7.2 Follower
7.7.3 Observer
7.7.4 集群間消息通信
7.8 請(qǐng)求處理
7.8.1 會(huì)話創(chuàng)建請(qǐng)求
7.8.2 SetData請(qǐng)求
7.8.3 事務(wù)請(qǐng)求轉(zhuǎn)發(fā)
7.8.4 GetData請(qǐng)求
7.9 數(shù)據(jù)與存儲(chǔ)
7.9.1 內(nèi)存數(shù)據(jù)
7.9.2 事務(wù)日志
7.9.3 snapshot――數(shù)據(jù)快照
7.9.4 初始化
7.9.5 數(shù)據(jù)同步
小結(jié)
第8章 ZooKeeper運(yùn)維
8.1 配置詳解
8.1.1 基本配置
8.1.2 高級(jí)配置
8.2 四字命令
8.3 JMX
8.3.1 開(kāi)啟遠(yuǎn)程JMX
8.3.2 通過(guò)JConsole連接ZooKeeper
8.4 監(jiān)控
8.4.1 實(shí)時(shí)監(jiān)控
8.4.2 數(shù)據(jù)統(tǒng)計(jì)
8.5 構(gòu)建一個(gè)高可用的集群
8.5.1 集群組成
8.5.2 容災(zāi)
8.5.3 擴(kuò)容與縮容
8.6 日常運(yùn)維
8.6.1 數(shù)據(jù)與日志管理
8.6.2 Too many connections
8.6.3 磁盤管理
小結(jié)
附錄A Windows平臺(tái)上部署ZooKeeper
附錄B 從源代碼開(kāi)始構(gòu)建
附錄C 各發(fā)行版本重大更新記錄
附錄D ZooKeeper源代碼閱讀指引
第1章
分布式架構(gòu)
隨著計(jì)算機(jī)系統(tǒng)規(guī)模變得越來(lái)越大,將所有的業(yè)務(wù)單元集中部署在一個(gè)或若干個(gè)大型機(jī)上的體系結(jié)構(gòu),已經(jīng)越來(lái)越不能滿足當(dāng)今計(jì)算機(jī)系統(tǒng),尤其是大型互聯(lián)網(wǎng)系統(tǒng)的快速發(fā)展,各種靈活多變的系統(tǒng)架構(gòu)模型層出不窮。同時(shí),隨著微型計(jì)算機(jī)的出現(xiàn),越來(lái)越多廉價(jià)的PC機(jī)成為了各大企業(yè)IT架構(gòu)的首選,分布式的處理方式越來(lái)越受到業(yè)界的青睞——計(jì)算機(jī)系統(tǒng)正在經(jīng)歷一場(chǎng)前所未有的從集中式向分布式架構(gòu)的變革。
1.1 從集中式到分布式
自20世紀(jì)60年代大型主機(jī)被發(fā)明出來(lái)以后,憑借其超強(qiáng)的計(jì)算和I/O處理能力以及在穩(wěn)定性和安全性方面的卓越表現(xiàn),在很長(zhǎng)一段時(shí)間內(nèi),大型主機(jī)引領(lǐng)了計(jì)算機(jī)行業(yè)以及商業(yè)計(jì)算領(lǐng)域的發(fā)展。在大型主機(jī)的研發(fā)上最知名的當(dāng)屬IBM,其主導(dǎo)研發(fā)的革命性產(chǎn)品System/360系列大型主機(jī),是計(jì)算機(jī)發(fā)展史上的一個(gè)里程碑,與波音707和福特T型車齊名,被譽(yù)為20世紀(jì)最重要的三大商業(yè)成就,并一度成為了大型主機(jī)的代名詞。從那時(shí)起,IT界進(jìn)入了大型主機(jī)時(shí)代。
伴隨著大型主機(jī)時(shí)代的到來(lái),集中式的計(jì)算機(jī)系統(tǒng)架構(gòu)也成為了主流。在那個(gè)時(shí)候,由于大型主機(jī)卓越的性能和良好的穩(wěn)定性,其在單機(jī)處理能力方面的優(yōu)勢(shì)非常明顯,使得IT系統(tǒng)快速進(jìn)入了集中式處理階段,其對(duì)應(yīng)的計(jì)算機(jī)系統(tǒng)稱為集中式系統(tǒng)。但從20世紀(jì)80年代以來(lái),計(jì)算機(jī)系統(tǒng)向網(wǎng)絡(luò)化和微型化的發(fā)展日趨明顯,傳統(tǒng)的集中式處理模式越來(lái)越不能適應(yīng)人們的需求。
首先,大型主機(jī)的人才培養(yǎng)成本非常之高。通常一臺(tái)大型主機(jī)匯集了大量精密的計(jì)算機(jī)組件,操作非常復(fù)雜,這對(duì)一個(gè)運(yùn)維人員掌握其技術(shù)細(xì)節(jié)提出了非常高的要求。
其次,大型主機(jī)也是非常昂貴的。通常一臺(tái)配置較好的IBM大型主機(jī),其售價(jià)可能在上百萬(wàn)美元甚至更高,因此也只有像政府、金融和電信等企業(yè)才有能力采購(gòu)大型主機(jī)。
另外,集中式系統(tǒng)具有明顯的單點(diǎn)問(wèn)題。大型主機(jī)雖然在性能和穩(wěn)定性方面表現(xiàn)卓越,但這并不代表其永遠(yuǎn)不會(huì)出現(xiàn)故障。一旦一臺(tái)大型主機(jī)出現(xiàn)了故障,那么整個(gè)系統(tǒng)將處于不可用狀態(tài),其后果相當(dāng)嚴(yán)重。最后,隨著業(yè)務(wù)的不斷發(fā)展,用戶訪問(wèn)量迅速提高,計(jì)算機(jī)系統(tǒng)的規(guī)模也在不斷擴(kuò)大,在單一大型主機(jī)上進(jìn)行系統(tǒng)的擴(kuò)容往往比較困難。
而另一方面,隨著PC機(jī)性能的不斷提升和網(wǎng)絡(luò)技術(shù)的快速普及,大型主機(jī)的市場(chǎng)份額變得越來(lái)越小,很多企業(yè)開(kāi)始放棄原來(lái)的大型主機(jī),而改用小型機(jī)和普通PC服務(wù)器來(lái)搭建分布式的計(jì)算機(jī)系統(tǒng)。
其中最為典型的就是阿里巴巴集團(tuán)的“去IOE”運(yùn)動(dòng)。從2008年開(kāi)始,阿里巴巴的各項(xiàng)業(yè)務(wù)都進(jìn)入了井噴式的發(fā)展階段,這對(duì)于后臺(tái)IT系統(tǒng)的計(jì)算與存儲(chǔ)能力提出了非常高的要求,一味地針對(duì)小型機(jī)和高端存儲(chǔ)進(jìn)行不斷擴(kuò)容,無(wú)疑會(huì)產(chǎn)生巨大的成本。同時(shí),集中式的系統(tǒng)架構(gòu)體系也存在諸多單點(diǎn)問(wèn)題,完全無(wú)法滿足互聯(lián)網(wǎng)應(yīng)用爆炸式的發(fā)展需求。因此,為了解決業(yè)務(wù)快速發(fā)展給IT系統(tǒng)帶來(lái)的巨大挑戰(zhàn),從2009年開(kāi)始,阿里集團(tuán)啟動(dòng)了“去IOE”計(jì)劃,其電商系統(tǒng)開(kāi)始正式邁入分布式系統(tǒng)時(shí)代。
1.1.1 集中式的特點(diǎn)
所謂的集中式系統(tǒng)就是指由一臺(tái)或多臺(tái)主計(jì)算機(jī)組成中心節(jié)點(diǎn),數(shù)據(jù)集中存儲(chǔ)于這個(gè)中心節(jié)點(diǎn)中,并且整個(gè)系統(tǒng)的所有業(yè)務(wù)單元都集中部署在這個(gè)中心節(jié)點(diǎn)上,系統(tǒng)的所有功能均由其集中處理。也就是說(shuō),在集中式系統(tǒng)中,每個(gè)終端或客戶端機(jī)器僅僅負(fù)責(zé)數(shù)據(jù)的錄入和輸出,而數(shù)據(jù)的存儲(chǔ)與控制處理完全交由主機(jī)來(lái)完成。
集中式系統(tǒng)最大的特點(diǎn)就是部署結(jié)構(gòu)簡(jiǎn)單。由于集中式系統(tǒng)往往基于底層性能卓越的大型主機(jī),因此無(wú)須考慮如何對(duì)服務(wù)進(jìn)行多個(gè)節(jié)點(diǎn)的部署,也就不用考慮多個(gè)節(jié)點(diǎn)之間的分布式協(xié)作問(wèn)題。
1.1.2 分布式的特點(diǎn)
在《分布式系統(tǒng)概念與設(shè)計(jì)》注 一書中,對(duì)分布式系統(tǒng)做了如下定義:
分布式系統(tǒng)是一個(gè)硬件或軟件組件分布在不同的網(wǎng)絡(luò)計(jì)算機(jī)上,彼此之間僅僅通過(guò)消息傳遞進(jìn)行通信和協(xié)調(diào)的系統(tǒng)。
上面這個(gè)簡(jiǎn)單的定義涵蓋了幾乎所有有效地部署了網(wǎng)絡(luò)化計(jì)算機(jī)的系統(tǒng)。嚴(yán)格地講,同一個(gè)分布式系統(tǒng)中的計(jì)算機(jī)在空間部署上是可以隨意分布的,這些計(jì)算機(jī)可能被放在不同的機(jī)柜上,也可能在不同的機(jī)房中,甚至分布在不同的城市。無(wú)論如何,一個(gè)標(biāo)準(zhǔn)的分布式系統(tǒng)在沒(méi)有任何特定業(yè)務(wù)邏輯約束的情況下,都會(huì)有如下幾個(gè)特征。
分布性
分布式系統(tǒng)中的多臺(tái)計(jì)算機(jī)都會(huì)在空間上隨意分布,同時(shí),機(jī)器的分布情況也會(huì)隨時(shí)變動(dòng)。
對(duì)等性
分布式系統(tǒng)中的計(jì)算機(jī)沒(méi)有主/從之分,既沒(méi)有控制整個(gè)系統(tǒng)的主機(jī),也沒(méi)有被控制的從機(jī),組成分布式系統(tǒng)的所有計(jì)算機(jī)節(jié)點(diǎn)都是對(duì)等的。副本(Replica)是分布式系統(tǒng)最常見(jiàn)的概念之一,指的是分布式系統(tǒng)對(duì)數(shù)據(jù)和服務(wù)提供的一種冗余方式。在常見(jiàn)的分布式系統(tǒng)中,為了對(duì)外提供高可用的服務(wù),我們往往會(huì)對(duì)數(shù)據(jù)和服務(wù)進(jìn)行副本處理。數(shù)據(jù)副本是指在不同的節(jié)點(diǎn)上持久化同一份數(shù)據(jù),當(dāng)某一個(gè)節(jié)點(diǎn)上存儲(chǔ)的數(shù)據(jù)丟失時(shí),可以從副本上讀取到該數(shù)據(jù),這是解決分布式系統(tǒng)數(shù)據(jù)丟失問(wèn)題最為有效的手段。另一類副本是服務(wù)副本,指多個(gè)節(jié)點(diǎn)提供同樣的服務(wù),每個(gè)節(jié)點(diǎn)都有能力接收來(lái)自外部的請(qǐng)求并進(jìn)行相應(yīng)的處理。
并發(fā)性
在“問(wèn)題的提出”部分,我們已經(jīng)提到過(guò)與“更新的并發(fā)性”相關(guān)的內(nèi)容。在一個(gè)計(jì)算機(jī)網(wǎng)絡(luò)中,程序運(yùn)行過(guò)程中的并發(fā)性操作是非常常見(jiàn)的行為,例如同一個(gè)分布式系統(tǒng)中的多個(gè)節(jié)點(diǎn),可能會(huì)并發(fā)地操作一些共享的資源,諸如數(shù)據(jù)庫(kù)或分布式存儲(chǔ)等,如何準(zhǔn)確并高效地協(xié)調(diào)分布式并發(fā)操作也成為了分布式系統(tǒng)架構(gòu)與設(shè)計(jì)中最大的挑戰(zhàn)之一?! ∪狈θ謺r(shí)鐘 在上面的講解中,我們已經(jīng)了解到,一個(gè)典型的分布式系統(tǒng)是由一系列在空間上隨意分布的多個(gè)進(jìn)程組成的,具有明顯的分布性,這些進(jìn)程之間通過(guò)交換消息來(lái)進(jìn)行相互通信。因此,在分布式系統(tǒng)中,很難定義兩個(gè)事件究竟誰(shuí)先誰(shuí)后,原因就是因?yàn)榉植际较到y(tǒng)缺乏一個(gè)全局的時(shí)鐘序列控制。關(guān)于分布式系統(tǒng)的時(shí)鐘和事件順序,在Leslie Lamport注 的經(jīng)典論文Time, Clocks, and the Ordering of Events in a Distributed System注 中已經(jīng)做了非常深刻的講解。
故障總是會(huì)發(fā)生
組成分布式系統(tǒng)的所有計(jì)算機(jī),都有可能發(fā)生任何形式的故障。一個(gè)被大量工程實(shí)踐所檢驗(yàn)過(guò)的黃金定理是:任何在設(shè)計(jì)階段考慮到的異常情況,一定會(huì)在系統(tǒng)實(shí)際運(yùn)行中發(fā)生,并且,在系統(tǒng)實(shí)際運(yùn)行過(guò)程中還會(huì)遇到很多在設(shè)計(jì)時(shí)未能考慮到的異常故障。所以,除非需求指標(biāo)允許,在系統(tǒng)設(shè)計(jì)時(shí)不能放過(guò)任何異常情況。
1.1.3 分布式環(huán)境的各種問(wèn)題
分布式系統(tǒng)體系結(jié)構(gòu)從其出現(xiàn)之初就伴隨著諸多的難題和挑戰(zhàn),本節(jié)將向讀者簡(jiǎn)要的介紹分布式環(huán)境中一些典型的問(wèn)題。
通信異常
從集中式向分布式演變的過(guò)程中,必然引入了網(wǎng)絡(luò)因素,而由于網(wǎng)絡(luò)本身的不可靠性,因此也引入了額外的問(wèn)題。分布式系統(tǒng)需要在各個(gè)節(jié)點(diǎn)之間進(jìn)行網(wǎng)絡(luò)通信,因此每次網(wǎng)絡(luò)通信都會(huì)伴隨著網(wǎng)絡(luò)不可用的風(fēng)險(xiǎn),網(wǎng)絡(luò)光纖、路由器或是DNS等硬件設(shè)備或是系統(tǒng)不可用都會(huì)導(dǎo)致最終分布式系統(tǒng)無(wú)法順利完成一次網(wǎng)絡(luò)通信。另外,即使分布式系統(tǒng)各節(jié)點(diǎn)之間的網(wǎng)絡(luò)通信能夠正常進(jìn)行,其延時(shí)也會(huì)遠(yuǎn)大于單機(jī)操作。通常我們認(rèn)為在現(xiàn)代計(jì)算機(jī)體系結(jié)構(gòu)中,單機(jī)內(nèi)存訪問(wèn)的延時(shí)在納秒數(shù)量級(jí)(通常是10ns左右),而正常的一次網(wǎng)絡(luò)通信的延遲在0.1~1ms左右(相當(dāng)于內(nèi)存訪問(wèn)延時(shí)的105~106倍),如此巨大的延時(shí)差別,也會(huì)影響消息的收發(fā)的過(guò)程,因此消息丟失和消息延遲變得非常普遍?! 【W(wǎng)絡(luò)分區(qū) 當(dāng)網(wǎng)絡(luò)由于發(fā)生異常情況,導(dǎo)致分布式系統(tǒng)中部分節(jié)點(diǎn)之間的網(wǎng)絡(luò)延時(shí)不斷增大,最終導(dǎo)致組成分布式系統(tǒng)的所有節(jié)點(diǎn)中,只有部分節(jié)點(diǎn)之間能夠進(jìn)行正常通信,而另一些節(jié)點(diǎn)則不能——我們將這個(gè)現(xiàn)象稱為網(wǎng)絡(luò)分區(qū),就是俗稱的“腦裂”。當(dāng)網(wǎng)絡(luò)分區(qū)出現(xiàn)時(shí),分布式系統(tǒng)會(huì)出現(xiàn)局部小集群,在極端情況下,這些局部小集群會(huì)獨(dú)立完成原本需要整個(gè)分布式系統(tǒng)才能完成的功能,包括對(duì)數(shù)據(jù)的事務(wù)處理,這就對(duì)分布式一致性提出了非常大的挑戰(zhàn)。
三態(tài)
從上面的介紹中,我們已經(jīng)了解到了在分布式環(huán)境下,網(wǎng)絡(luò)可能會(huì)出現(xiàn)各式各樣的問(wèn)題,因此分布式系統(tǒng)的每一次請(qǐng)求與響應(yīng),存在特有的“三態(tài)”概念,即成功、失敗與超時(shí)。在傳統(tǒng)的單機(jī)系統(tǒng)中,應(yīng)用程序在調(diào)用一個(gè)函數(shù)之后,能夠得到一個(gè)非常明確的響應(yīng):成功或失敗。而在分布式系統(tǒng)中,由于網(wǎng)絡(luò)是不可靠的,雖然在絕大部分情況下,網(wǎng)絡(luò)通信也能夠接收到成功或失敗的響應(yīng),但是當(dāng)網(wǎng)絡(luò)出現(xiàn)異常的情況下,就可能會(huì)出現(xiàn)超時(shí)現(xiàn)象,通常有以下兩種情況: 由于網(wǎng)絡(luò)原因,該請(qǐng)求(消息)并沒(méi)有被成功地發(fā)送到接收方,而是在發(fā)送過(guò)程就發(fā)生了消息丟失現(xiàn)象。
該請(qǐng)求(消息)成功的被接收方接收后,并進(jìn)行了處理,但是在將響應(yīng)反饋給發(fā)送方的過(guò)程中,發(fā)生了消息丟失現(xiàn)象。 當(dāng)出現(xiàn)這樣的超時(shí)現(xiàn)象時(shí),網(wǎng)絡(luò)通信的發(fā)起方是無(wú)法確定當(dāng)前請(qǐng)求是否被成功處理的。
節(jié)點(diǎn)故障
節(jié)點(diǎn)故障則是分布式環(huán)境下另一個(gè)比較常見(jiàn)的問(wèn)題,指的是組成分布式系統(tǒng)的服務(wù)器節(jié)點(diǎn)出現(xiàn)的宕機(jī)或“僵死”現(xiàn)象。通常根據(jù)經(jīng)驗(yàn)來(lái)說(shuō),每個(gè)節(jié)點(diǎn)都有可能會(huì)出現(xiàn)故障,并且每天都在發(fā)生。
1.2 從ACID到CAP/BASE
在上文中,我們講解了集中式系統(tǒng)和分布式系統(tǒng)各自的特點(diǎn),同時(shí)也看到了在從集中式系統(tǒng)架構(gòu)向分布式系統(tǒng)架構(gòu)變遷的過(guò)程中會(huì)碰到的一系列問(wèn)題。接下來(lái),我們?cè)僦攸c(diǎn)看看在分布式系統(tǒng)事務(wù)處理與數(shù)據(jù)一致性上遇到的種種挑戰(zhàn)。
1.2.1 ACID
事務(wù)(Transaction)是由一系列對(duì)系統(tǒng)中數(shù)據(jù)進(jìn)行訪問(wèn)與更新的操作所組成的一個(gè)程序執(zhí)行邏輯單元(Unit),狹義上的事務(wù)特指數(shù)據(jù)庫(kù)事務(wù)。一方面,當(dāng)多個(gè)應(yīng)用程序并發(fā)訪問(wèn)數(shù)據(jù)庫(kù)時(shí),事務(wù)可以在這些應(yīng)用程序之間提供一個(gè)隔離方法,以防止彼此的操作互相干擾。另一方面,事務(wù)為數(shù)據(jù)庫(kù)操作序列提供了一個(gè)從失敗中恢復(fù)到正常狀態(tài)的方法,同時(shí)提供了數(shù)據(jù)庫(kù)即使在異常狀態(tài)下仍能保持?jǐn)?shù)據(jù)一致性的方法。
事務(wù)具有四個(gè)特征,分別是原子性(Atomicity)、一致性(Consistency)、隔離性(Isolation)和持久性(Durability),簡(jiǎn)稱為事務(wù)的ACID特性?! ≡有浴 ∈聞?wù)的原子性是指事務(wù)必須是一個(gè)原子的操作序列單元。事務(wù)中包含的各項(xiàng)操作在一次執(zhí)行過(guò)程中,只允許出現(xiàn)以下兩種狀態(tài)之一。
全部成功執(zhí)行。
全部不執(zhí)行。
任何一項(xiàng)操作失敗都將導(dǎo)致整個(gè)事務(wù)失敗,同時(shí)其他已經(jīng)被執(zhí)行的操作都將被撤銷并回滾,只有所有的操作全部成功,整個(gè)事務(wù)才算是成功完成。
一致性
事務(wù)的一致性是指事務(wù)的執(zhí)行不能破壞數(shù)據(jù)庫(kù)數(shù)據(jù)的完整性和一致性,一個(gè)事務(wù)在執(zhí)行之前和執(zhí)行之后,數(shù)據(jù)庫(kù)都必須處于一致性狀態(tài)。也就是說(shuō),事務(wù)執(zhí)行的結(jié)果必須是使數(shù)據(jù)庫(kù)從一個(gè)一致性狀態(tài)轉(zhuǎn)變到另一個(gè)一致性狀態(tài),因此當(dāng)數(shù)據(jù)庫(kù)只包含成功事務(wù)提交的結(jié)果時(shí),就能說(shuō)數(shù)據(jù)庫(kù)處于一致性狀態(tài)。而如果數(shù)據(jù)庫(kù)系統(tǒng)在運(yùn)行過(guò)程中發(fā)生故障,有些事務(wù)尚未完成就被迫中斷,這些未完成的事務(wù)對(duì)數(shù)據(jù)庫(kù)所做的修改有一部分已寫入物理數(shù)據(jù)庫(kù),這時(shí)數(shù)據(jù)庫(kù)就處于一種不正確的狀態(tài),或者說(shuō)是不一致的狀態(tài)。
隔離性
事務(wù)的隔離性是指在并發(fā)環(huán)境中,并發(fā)的事務(wù)是相互隔離的,一個(gè)事務(wù)的執(zhí)行不能被其他事務(wù)干擾。也就是說(shuō),不同的事務(wù)并發(fā)操縱相同的數(shù)據(jù)時(shí),每個(gè)事務(wù)都有各自完整的數(shù)據(jù)空間,即一個(gè)事務(wù)內(nèi)部的操作及使用的數(shù)據(jù)對(duì)其他并發(fā)事務(wù)是隔離的,并發(fā)執(zhí)行的各個(gè)事務(wù)之間不能互相干擾。
在標(biāo)準(zhǔn)SQL規(guī)范中,定義了4個(gè)事務(wù)隔離級(jí)別,不同的隔離級(jí)別對(duì)事務(wù)的處理不同,如未授權(quán)讀取、授權(quán)讀取、可重復(fù)讀取和串行化注 。
未授權(quán)讀取
未授權(quán)讀取也被稱為讀未提交(Read Uncommitted),該隔離級(jí)別允許臟讀取,其隔離級(jí)別最低。換句話說(shuō),如果一個(gè)事務(wù)正在處理某一數(shù)據(jù),并對(duì)其進(jìn)行了更新,但同時(shí)尚未完成事務(wù),因此還沒(méi)有進(jìn)行事務(wù)提交;而與此同時(shí),允許另一個(gè)事務(wù)也能夠訪問(wèn)該數(shù)據(jù)。舉個(gè)例子來(lái)說(shuō),事務(wù)A和事務(wù)B同時(shí)進(jìn)行,事務(wù)A在整個(gè)執(zhí)行階段,會(huì)將某數(shù)據(jù)項(xiàng)的值從1開(kāi)始,做一系列加法操作(比如說(shuō)加1操作)直到變成10之后進(jìn)行事務(wù)提交,此時(shí),事務(wù)B能夠看到這個(gè)數(shù)據(jù)項(xiàng)在事務(wù)A操作過(guò)程中的所有中間值(如1變成2、2變成3等),而對(duì)這一系列的中間值的讀取就是未授權(quán)讀取。
授權(quán)讀取
授權(quán)讀取也被稱為讀已提交(Read Committed),它和未授權(quán)讀取非常相近,唯一的區(qū)別就是授權(quán)讀取只允許獲取已經(jīng)被提交的數(shù)據(jù)。同樣以上面的例子來(lái)說(shuō),事務(wù)A和事務(wù)B同時(shí)進(jìn)行,事務(wù)A進(jìn)行與上述同樣的操作,此時(shí),事務(wù)B無(wú)法看到這個(gè)數(shù)據(jù)項(xiàng)在事務(wù)A操作過(guò)程中的所有中間值,只能看到最終的10。另外,如果說(shuō)有一個(gè)事務(wù)C,和事務(wù)A進(jìn)行非常類似的操作,只是事務(wù)C是將數(shù)據(jù)項(xiàng)從10加到20,此時(shí)事務(wù)B也同樣可以讀取到20,即授權(quán)讀取允許不可重復(fù)讀取。
可重復(fù)讀取
可重復(fù)讀?。≧epeatable Read),簡(jiǎn)單地說(shuō),就是保證在事務(wù)處理過(guò)程中,多次讀取同一個(gè)數(shù)據(jù)時(shí),其值都和事務(wù)開(kāi)始時(shí)刻是一致的。因此該事務(wù)級(jí)別禁止了不可重復(fù)讀取和臟讀取,但是有可能出現(xiàn)幻影數(shù)據(jù)。所謂幻影數(shù)據(jù),就是指同樣的事務(wù)操作,在前后兩個(gè)時(shí)間段內(nèi)執(zhí)行對(duì)同一個(gè)數(shù)據(jù)項(xiàng)的讀取,可能出現(xiàn)不一致的結(jié)果。在上面的例子,可重復(fù)讀取隔離級(jí)別能夠保證事務(wù)B在第一次事務(wù)操作過(guò)程中,始終對(duì)數(shù)據(jù)項(xiàng)讀取到1,但是在下一次事務(wù)操作中,即使事務(wù)B(注意,事務(wù)名字雖然相同,但是指的是另一次事務(wù)操作)采用同樣的查詢方式,就可能會(huì)讀取到10或20。
串行化
串行化(Serializable)是最嚴(yán)格的事務(wù)隔離級(jí)別。它要求所有事務(wù)都被串行執(zhí)行,即事務(wù)只能一個(gè)接一個(gè)地進(jìn)行處理,不能并發(fā)執(zhí)行。
圖1-1展示了不同隔離級(jí)別下事務(wù)訪問(wèn)數(shù)據(jù)的差異。
圖1-1.4種隔離級(jí)別示意圖
以上4個(gè)隔離級(jí)別的隔離性依次增強(qiáng),分別解決不同的問(wèn)題,表1-1對(duì)這4個(gè)隔離級(jí)別進(jìn)行了一個(gè)簡(jiǎn)單的對(duì)比。
表1-1.隔離級(jí)別對(duì)比 隔離級(jí)別 臟讀 可重復(fù)讀 幻讀 未授權(quán)讀取 存在 不可以 存在
授權(quán)讀取 不存在 不可以 存在
可重復(fù)讀取 不存在 可以 存在
串行化 不存在 可以 不存在
事務(wù)隔離級(jí)別越高,就越能保證數(shù)據(jù)的完整性和一致性,但同時(shí)對(duì)并發(fā)性能的影響也越大。通常,對(duì)于絕大多數(shù)的應(yīng)用程序來(lái)說(shuō),可以優(yōu)先考慮將數(shù)據(jù)庫(kù)系統(tǒng)的隔離級(jí)別設(shè)置為授權(quán)讀取,這能夠在避免臟讀取的同時(shí)保證較好的并發(fā)性能。盡管這種事務(wù)隔離級(jí)別會(huì)導(dǎo)致不可重復(fù)讀、虛讀和第二類丟失更新等并發(fā)問(wèn)題,但較為科學(xué)的做法是在可能出現(xiàn)這類問(wèn)題的個(gè)別場(chǎng)合中,由應(yīng)用程序主動(dòng)采用悲觀鎖或樂(lè)觀鎖來(lái)進(jìn)行事務(wù)控制。
持久性
事務(wù)的持久性也被稱為永久性,是指一個(gè)事務(wù)一旦提交,它對(duì)數(shù)據(jù)庫(kù)中對(duì)應(yīng)數(shù)據(jù)的狀態(tài)變更就應(yīng)該是永久性的。換句話說(shuō),一旦某個(gè)事務(wù)成功結(jié)束,那么它對(duì)數(shù)據(jù)庫(kù)所做的更新就必須被永久保存下來(lái)——即使發(fā)生系統(tǒng)崩潰或機(jī)器宕機(jī)等故障,只要數(shù)據(jù)庫(kù)能夠重新啟動(dòng),那么一定能夠?qū)⑵浠謴?fù)到事務(wù)成功結(jié)束時(shí)的狀態(tài)。
1.2.2 分布式事務(wù)
隨著分布式計(jì)算的發(fā)展,事務(wù)在分布式計(jì)算領(lǐng)域中也得到了廣泛的應(yīng)用。在單機(jī)數(shù)據(jù)庫(kù)中,我們很容易能夠?qū)崿F(xiàn)一套滿足ACID特性的事務(wù)處理系統(tǒng),但在分布式數(shù)據(jù)庫(kù)中,數(shù)據(jù)分散在各臺(tái)不同的機(jī)器上,如何對(duì)這些數(shù)據(jù)進(jìn)行分布式的事務(wù)處理具有非常大的挑戰(zhàn)。在1.1.3節(jié)中,我們已經(jīng)講解了分布式環(huán)境中會(huì)碰到的種種問(wèn)題,其中就包括機(jī)器宕機(jī)和各種網(wǎng)絡(luò)異常等。盡管存在這種種分布式問(wèn)題,但是在分布式計(jì)算領(lǐng)域,為了保證分布式應(yīng)用程序的可靠性,分布式事務(wù)是無(wú)法回避的。
分布式事務(wù)是指事務(wù)的參與者、支持事務(wù)的服務(wù)器、資源服務(wù)器以及事務(wù)管理器分別位于分布式系統(tǒng)的不同節(jié)點(diǎn)之上。通常一個(gè)分布式事務(wù)中會(huì)涉及對(duì)多個(gè)數(shù)據(jù)源或業(yè)務(wù)系統(tǒng)的操作。
我們可以設(shè)想一個(gè)最典型的分布式事務(wù)場(chǎng)景:一個(gè)跨銀行的轉(zhuǎn)賬操作涉及調(diào)用兩個(gè)異地的銀行服務(wù),其中一個(gè)是本地銀行提供的取款服務(wù),另一個(gè)則是目標(biāo)銀行提供的存款服務(wù),這兩個(gè)服務(wù)本身是無(wú)狀態(tài)并且是互相獨(dú)立的,共同構(gòu)成了一個(gè)完整的分布式事務(wù)。如果從本地銀行取款成功,但是因?yàn)槟撤N原因存款服務(wù)失敗了,那么就必須回滾到取款前的狀態(tài),否則用戶可能會(huì)發(fā)現(xiàn)自己的錢不翼而飛了。
從上面這個(gè)例子中,我們可以看到,一個(gè)分布式事務(wù)可以看作是由多個(gè)分布式的操作序列組成的,例如上面例子中的取款服務(wù)和存款服務(wù),通??梢园堰@一系列分布式的操作序列稱為子事務(wù)。因此,分布式事務(wù)也可以被定義為一種嵌套型的事務(wù),同時(shí)也就具有了ACID事務(wù)特性。但由于在分布式事務(wù)中,各個(gè)子事務(wù)的執(zhí)行是分布式的,因此要實(shí)現(xiàn)一種能夠保證ACID特性的分布式事務(wù)處理系統(tǒng)就顯得格外復(fù)雜。
1.2.3 CAP和BASE理論
對(duì)于本地事務(wù)處理或者是集中式的事務(wù)處理系統(tǒng),很顯然我們可以采用已經(jīng)被實(shí)踐證明很成熟的ACID模型來(lái)保證數(shù)據(jù)的嚴(yán)格一致性。而在1.2.2節(jié)中,我們也已經(jīng)看到,隨著分布式事務(wù)的出現(xiàn),傳統(tǒng)的單機(jī)事務(wù)模型已經(jīng)無(wú)法勝任。尤其是對(duì)于一個(gè)高訪問(wèn)量、高并發(fā)的互聯(lián)網(wǎng)分布式系統(tǒng)來(lái)說(shuō),如果我們期望實(shí)現(xiàn)一套嚴(yán)格滿足ACID特性的分布式事務(wù),很可能出現(xiàn)的情況就是在系統(tǒng)的可用性和嚴(yán)格一致性之間出現(xiàn)沖突——因?yàn)楫?dāng)我們要求分布式系統(tǒng)具有嚴(yán)格一致性時(shí),很可能就需要犧牲掉系統(tǒng)的可用性。但毋庸置疑的一點(diǎn)是,可用性又是一個(gè)所有消費(fèi)者不允許我們討價(jià)還價(jià)的系統(tǒng)屬性,比如說(shuō)像淘寶網(wǎng)這樣的在線購(gòu)物網(wǎng)站,就要求它能夠7?24小時(shí)不間斷地對(duì)外提供服務(wù),而對(duì)于一致性,則更加是所有消費(fèi)者對(duì)于一個(gè)軟件系統(tǒng)的剛需。因此,在可用性和一致性之間永遠(yuǎn)無(wú)法存在一個(gè)兩全其美的方案,于是如何構(gòu)建一個(gè)兼顧可用性和一致性的分布式系統(tǒng)成為了無(wú)數(shù)工程師探討的難題,出現(xiàn)了諸如CAP和BASE這樣的分布式系統(tǒng)經(jīng)典理論。
CAP定理
2000年7月,來(lái)自加州大學(xué)伯克利分校的Eric Brewer教授注 在ACM PODC(Principles of Distributed Computing)會(huì)議上,首次提出了著名的CAP猜想注 。2年后,來(lái)自麻省理工學(xué)院的Seth Gilbert和Nancy Lynch從理論上證明了Brewer教授CAP猜想的可行性注 ,從此,CAP理論正式在學(xué)術(shù)上成為了分布式計(jì)算領(lǐng)域的公認(rèn)定理,并深深地影響了分布式計(jì)算的發(fā)展。
CAP理論告訴我們,一個(gè)分布式系統(tǒng)不可能同時(shí)滿足一致性(C:Consistency)、可用性(A:Availability)和分區(qū)容錯(cuò)性(P:Partition tolerance)這三個(gè)基本需求,最多只能同時(shí)滿足其中的兩項(xiàng)。
一致性 在分布式環(huán)境中,一致性是指數(shù)據(jù)在多個(gè)副本之間是否能夠保持一致的特性。在一致性的需求下,當(dāng)一個(gè)系統(tǒng)在數(shù)據(jù)一致的狀態(tài)下執(zhí)行更新操作后,應(yīng)該保證系統(tǒng)的數(shù)據(jù)仍然處于一致的狀態(tài)。
對(duì)于一個(gè)將數(shù)據(jù)副本分布在不同分布式節(jié)點(diǎn)上的系統(tǒng)來(lái)說(shuō),如果對(duì)第一個(gè)節(jié)點(diǎn)的數(shù)據(jù)進(jìn)行了更新操作并且更新成功后,卻沒(méi)有使得第二個(gè)節(jié)點(diǎn)上的數(shù)據(jù)得到相應(yīng)的更新,于是在對(duì)第二個(gè)節(jié)點(diǎn)的數(shù)據(jù)進(jìn)行讀取操作時(shí),獲取的依然是老數(shù)據(jù)(或稱為臟數(shù)據(jù)),這就是典型的分布式數(shù)據(jù)不一致情況。在分布式系統(tǒng)中,如果能夠做到針對(duì)一個(gè)數(shù)據(jù)項(xiàng)的更新操作執(zhí)行成功后,所有的用戶都可以讀取到其最新的值,那么這樣的系統(tǒng)就被認(rèn)為具有強(qiáng)一致性(或嚴(yán)格的一致性)。
可用性
可用性是指系統(tǒng)提供的服務(wù)必須一直處于可用的狀態(tài),對(duì)于用戶的每一個(gè)操作請(qǐng)求總是能夠在有限的時(shí)間內(nèi)返回結(jié)果。這里我們重點(diǎn)看下“有限的時(shí)間內(nèi)”和“返回結(jié)果”。
“有限的時(shí)間內(nèi)”是指,對(duì)于用戶的一個(gè)操作請(qǐng)求,系統(tǒng)必須能夠在指定的時(shí)間(即響應(yīng)時(shí)間)內(nèi)返回對(duì)應(yīng)的處理結(jié)果,如果超過(guò)了這個(gè)時(shí)間范圍,那么系統(tǒng)就被認(rèn)為是不可用的。另外,“有限的時(shí)間內(nèi)”是一個(gè)在系統(tǒng)設(shè)計(jì)之初就設(shè)定好的系統(tǒng)運(yùn)行指標(biāo),通常不同的系統(tǒng)之間會(huì)有很大的不同。比如說(shuō),對(duì)于一個(gè)在線搜索引擎來(lái)說(shuō),通常在0.5秒內(nèi)需要給出用戶搜索關(guān)鍵詞對(duì)應(yīng)的檢索結(jié)果。以Google為例,搜索“分布式”這一關(guān)鍵詞,Google能夠在0.3秒左右的時(shí)間,返回大約上千萬(wàn)條檢索結(jié)果。而對(duì)于一個(gè)面向HIVE的海量數(shù)據(jù)查詢平臺(tái)來(lái)說(shuō),正常的一次數(shù)據(jù)檢索時(shí)間可能在20秒到30秒之間,而如果是一個(gè)時(shí)間跨度較大的數(shù)據(jù)內(nèi)容查詢,“有限的時(shí)間”有時(shí)候甚至?xí)L(zhǎng)達(dá)幾分鐘。
從上面的例子中,我們可以看出,用戶對(duì)于一個(gè)系統(tǒng)的請(qǐng)求響應(yīng)時(shí)間的期望值不盡相同。但是,無(wú)論系統(tǒng)之間的差異有多大,唯一相同的一點(diǎn)就是對(duì)于用戶請(qǐng)求,系統(tǒng)必須存在一個(gè)合理的響應(yīng)時(shí)間,否則用戶便會(huì)對(duì)系統(tǒng)感到失望。
“返回結(jié)果”是可用性的另一個(gè)非常重要的指標(biāo),它要求系統(tǒng)在完成對(duì)用戶請(qǐng)求的處理后,返回一個(gè)正常的響應(yīng)結(jié)果。正常的響應(yīng)結(jié)果通常能夠明確地反映出對(duì)請(qǐng)求的處理結(jié)果,即成功或失敗,而不是一個(gè)讓用戶感到困惑的返回結(jié)果。
讓我們?cè)賮?lái)看看上面提到的在線搜索引擎的例子,如果用戶輸入指定的搜索關(guān)鍵詞后,返回的結(jié)果是一個(gè)系統(tǒng)錯(cuò)誤,通常類似于“OutOfMemoryError”或“System Has Crashed”等提示語(yǔ),那么我們認(rèn)為此時(shí)系統(tǒng)是不可用的。
分區(qū)容錯(cuò)性
分區(qū)容錯(cuò)性約束了一個(gè)分布式系統(tǒng)需要具有如下特性:分布式系統(tǒng)在遇到任何網(wǎng)絡(luò)分區(qū)故障的時(shí)候,仍然需要能夠保證對(duì)外提供滿足一致性和可用性的服務(wù),除非是整個(gè)網(wǎng)絡(luò)環(huán)境都發(fā)生了故障。
網(wǎng)絡(luò)分區(qū)是指在分布式系統(tǒng)中,不同的節(jié)點(diǎn)分布在不同的子網(wǎng)絡(luò)(機(jī)房或異地網(wǎng)絡(luò)等)中,由于一些特殊的原因?qū)е逻@些子網(wǎng)絡(luò)之間出現(xiàn)網(wǎng)絡(luò)不連通的狀況,但各個(gè)子網(wǎng)絡(luò)的內(nèi)部網(wǎng)絡(luò)是正常的,從而導(dǎo)致整個(gè)系統(tǒng)的網(wǎng)絡(luò)環(huán)境被切分成了若干個(gè)孤立的區(qū)域。需要注意的是,組成一個(gè)分布式系統(tǒng)的每個(gè)節(jié)點(diǎn)的加入與退出都可以看作是一個(gè)特殊的網(wǎng)絡(luò)分區(qū)。
以上就是對(duì)CAP定理中一致性、可用性和分區(qū)容錯(cuò)性的講解,通常使用圖1-2所示的示意圖來(lái)表示CAP定理。
既然在上文中我們提到,一個(gè)分布式系統(tǒng)無(wú)法同時(shí)滿足上述三個(gè)需求,而只能滿足其中的兩項(xiàng),因此在進(jìn)行對(duì)CAP定理的應(yīng)用時(shí),我們就需要拋棄其中的一項(xiàng),表1-2所示是拋棄CAP定理中任意一項(xiàng)特性的場(chǎng)景說(shuō)明。
圖1-2.CAP定理示意圖
表1-2.CAP定理應(yīng)用
放棄CAP定理 說(shuō)明
放棄P 如果希望能夠避免系統(tǒng)出現(xiàn)分區(qū)容錯(cuò)性問(wèn)題,一種較為簡(jiǎn)單的做法是將所有的數(shù)據(jù)(或者僅僅是那些與事務(wù)相關(guān)的數(shù)據(jù))都放在一個(gè)分布式節(jié)點(diǎn)上。這樣的做法雖然無(wú)法100%地保證系統(tǒng)不會(huì)出錯(cuò),但至少不會(huì)碰到由于網(wǎng)絡(luò)分區(qū)帶來(lái)的負(fù)面影響。但同時(shí)需要注意的是,放棄P的同時(shí)也就意味著放棄了系統(tǒng)的可擴(kuò)展性
放棄A 相對(duì)于放棄“分區(qū)容錯(cuò)性”來(lái)說(shuō),放棄可用性則正好相反,其做法是一旦系統(tǒng)遇到網(wǎng)絡(luò)分區(qū)或其他故障時(shí),那么受到影響的服務(wù)需要等待一定的時(shí)間,因此在等待期間系統(tǒng)無(wú)法對(duì)外提供正常的服務(wù),即不可用
放棄C 這里所說(shuō)的放棄一致性,并不是完全不需要數(shù)據(jù)一致性,如果真是這樣的話,那么系統(tǒng)的數(shù)據(jù)都是沒(méi)有意義的,整個(gè)系統(tǒng)也是沒(méi)有價(jià)值的。
事實(shí)上,放棄一致性指的是放棄數(shù)據(jù)的強(qiáng)一致性,而保留數(shù)據(jù)的最終一致性。這樣的系統(tǒng)無(wú)法保證數(shù)據(jù)保持實(shí)時(shí)的一致性,但是能夠承諾的是,數(shù)據(jù)最終會(huì)達(dá)到一個(gè)一致的狀態(tài)。這就引入了一個(gè)時(shí)間窗口的概念,具體多久能夠達(dá)到數(shù)據(jù)一致取決于系統(tǒng)的設(shè)計(jì),主要包括數(shù)據(jù)副本在不同節(jié)點(diǎn)之間的復(fù)制時(shí)間長(zhǎng)短
從CAP定理中我們可以看出,一個(gè)分布式系統(tǒng)不可能同時(shí)滿足一致性、可用性和分區(qū)容錯(cuò)性這三個(gè)需求。另一方面,需要明確的一點(diǎn)是,對(duì)于一個(gè)分布式系統(tǒng)而言,分區(qū)容錯(cuò)性可以說(shuō)是一個(gè)最基本的要求。為什么這樣說(shuō),其實(shí)很簡(jiǎn)單,因?yàn)榧热皇且粋€(gè)分布式系統(tǒng),那么分布式系統(tǒng)中的組件必然需要被部署到不同的節(jié)點(diǎn),否則也就無(wú)所謂分布式系統(tǒng)了,因此必然出現(xiàn)子網(wǎng)絡(luò)。而對(duì)于分布式系統(tǒng)而言,網(wǎng)絡(luò)問(wèn)題又是一個(gè)必定會(huì)出現(xiàn)的異常情況,因此分區(qū)容錯(cuò)性也就成為了一個(gè)分布式系統(tǒng)必然需要面對(duì)和解決的問(wèn)題。因此系統(tǒng)架構(gòu)設(shè)計(jì)師往往需要把精力花在如何根據(jù)業(yè)務(wù)特點(diǎn)在C(一致性)和A(可用性)之間尋求平衡。
BASE理論
BASE是Basically Available(基本可用)、Soft state(軟狀態(tài))和Eventually consistent(最終一致性)三個(gè)短語(yǔ)的簡(jiǎn)寫,是由來(lái)自eBay的架構(gòu)師Dan Pritchett在其文章BASE: An Acid Alternative注 中第一次明確提出的。BASE是對(duì)CAP中一致性和可用性權(quán)衡的結(jié)果,其來(lái)源于對(duì)大規(guī)模互聯(lián)網(wǎng)系統(tǒng)分布式實(shí)踐的總結(jié),是基于CAP定理逐步演化而來(lái)的,其核心思想是即使無(wú)法做到強(qiáng)一致性(Strong consistency),但每個(gè)應(yīng)用都可以根據(jù)自身的業(yè)務(wù)特點(diǎn),采用適當(dāng)?shù)姆绞絹?lái)使系統(tǒng)達(dá)到最終一致性(Eventual consistency)。接下來(lái)我們著重對(duì)BASE中的三要素進(jìn)行詳細(xì)講解。
基本可用
基本可用是指分布式系統(tǒng)在出現(xiàn)不可預(yù)知故障的時(shí)候,允許損失部分可用性——但請(qǐng)注意,這絕不等價(jià)于系統(tǒng)不可用。以下兩個(gè)就是“基本可用”的典型例子。
響應(yīng)時(shí)間上的損失:正常情況下,一個(gè)在線搜索引擎需要在0.5秒之內(nèi)返回給用戶相應(yīng)的查詢結(jié)果,但由于出現(xiàn)故障(比如系統(tǒng)部分機(jī)房發(fā)生斷電或斷網(wǎng)故障),查詢結(jié)果的響應(yīng)時(shí)間增加到了1~2秒。
功能上的損失:正常情況下,在一個(gè)電子商務(wù)網(wǎng)站上進(jìn)行購(gòu)物,消費(fèi)者幾乎能夠順利地完成每一筆訂單,但是在一些節(jié)日大促購(gòu)物高峰的時(shí)候,由于消費(fèi)者的購(gòu)物行為激增,為了保護(hù)購(gòu)物系統(tǒng)的穩(wěn)定性,部分消費(fèi)者可能會(huì)被引導(dǎo)到一個(gè)降級(jí)頁(yè)面。
弱狀態(tài)
弱狀態(tài)也稱為軟狀態(tài),和硬狀態(tài)相對(duì),是指允許系統(tǒng)中的數(shù)據(jù)存在中間狀態(tài),并認(rèn)為該中間狀態(tài)的存在不會(huì)影響系統(tǒng)的整體可用性,即允許系統(tǒng)在不同節(jié)點(diǎn)的數(shù)據(jù)副本之間進(jìn)行數(shù)據(jù)同步的過(guò)程存在延時(shí)。
最終一致性
最終一致性強(qiáng)調(diào)的是系統(tǒng)中所有的數(shù)據(jù)副本,在經(jīng)過(guò)一段時(shí)間的同步后,最終能夠達(dá)到一個(gè)一致的狀態(tài)。因此,最終一致性的本質(zhì)是需要系統(tǒng)保證最終數(shù)據(jù)能夠達(dá)到一致,而不需要實(shí)時(shí)保證系統(tǒng)數(shù)據(jù)的強(qiáng)一致性。
亞馬遜首席技術(shù)官Werner Vogels在于2008年發(fā)表的一篇經(jīng)典文章Eventually Consistent-
Revisited中,對(duì)最終一致性進(jìn)行了非常詳細(xì)的介紹。他認(rèn)為最終一致性是一種特殊的弱一致性:系統(tǒng)能夠保證在沒(méi)有其他新的更新操作的情況下,數(shù)據(jù)最終一定能夠達(dá)到一致的狀態(tài),因此所有客戶端對(duì)系統(tǒng)的數(shù)據(jù)訪問(wèn)都能夠獲取到最新的值。同時(shí),在沒(méi)有發(fā)生故障的前提下,數(shù)據(jù)達(dá)到一致?tīng)顟B(tài)的時(shí)間延遲,取決于網(wǎng)絡(luò)延遲、系統(tǒng)負(fù)載和數(shù)據(jù)復(fù)制方案設(shè)計(jì)等因素。
在實(shí)際工程實(shí)踐中,最終一致性存在以下五類主要變種。
因果一致性(Causal consistency)
因果一致性是指,如果進(jìn)程A在更新完某個(gè)數(shù)據(jù)項(xiàng)后通知了進(jìn)程B,那么進(jìn)程B之后對(duì)該數(shù)據(jù)項(xiàng)的訪問(wèn)都應(yīng)該能夠獲取到進(jìn)程A更新后的最新值,并且如果進(jìn)程B要對(duì)該數(shù)據(jù)項(xiàng)進(jìn)行更新操作的話,務(wù)必基于進(jìn)程A更新后的最新值,即不能發(fā)生丟失更新情況。與此同時(shí),與進(jìn)程A無(wú)因果關(guān)系的進(jìn)程C的數(shù)據(jù)訪問(wèn)則沒(méi)有這樣的限制。
讀己之所寫(Read your writes)
讀己之所寫是指,進(jìn)程A更新一個(gè)數(shù)據(jù)項(xiàng)之后,它自己總是能夠訪問(wèn)到更新過(guò)的最新值,而不會(huì)看到舊值。也就是說(shuō),對(duì)于單個(gè)數(shù)據(jù)獲取者來(lái)說(shuō),其讀取到的數(shù)據(jù),一定不會(huì)比自己上次寫入的值舊。因此,讀己之所寫也可以看作是一種特殊的因果一致性?! ?huì)話一致性(Session consistency)
會(huì)話一致性將對(duì)系統(tǒng)數(shù)據(jù)的訪問(wèn)過(guò)程框定在了一個(gè)會(huì)話當(dāng)中:系統(tǒng)能保證在同一個(gè)有效的會(huì)話中實(shí)現(xiàn)“讀己之所寫”的一致性,也就是說(shuō),執(zhí)行更能操作之后,客戶端能夠在同一個(gè)會(huì)話中始終讀取到該數(shù)據(jù)項(xiàng)的最新值。
單調(diào)讀一致性(Monotonic read consistency)
單調(diào)讀一致性是指如果一個(gè)進(jìn)程從系統(tǒng)中讀取出一個(gè)數(shù)據(jù)項(xiàng)的某個(gè)值后,那么系統(tǒng)對(duì)于該進(jìn)程后續(xù)的任何數(shù)據(jù)訪問(wèn)都不應(yīng)該返回更舊的值。
單調(diào)寫一致性(Monotonic write consistency)
單調(diào)寫一致性是指,一個(gè)系統(tǒng)需要能夠保證來(lái)自同一個(gè)進(jìn)程的寫操作被順序地執(zhí)行。
以上就是最終一致性的五類常見(jiàn)的變種,在實(shí)際系統(tǒng)實(shí)踐中,可以將其中的若干個(gè)變種互相結(jié)合起來(lái),以構(gòu)建一個(gè)具有最終一致性特性的分布式系統(tǒng)。事實(shí)上,最終一致性并不是只有那些大型分布式系統(tǒng)才涉及的特性,許多現(xiàn)代的關(guān)系型數(shù)據(jù)庫(kù)都采用了最終一致性模型。在現(xiàn)代關(guān)系型數(shù)據(jù)庫(kù)中,大多都會(huì)采用同步和異步方式來(lái)實(shí)現(xiàn)主備數(shù)據(jù)復(fù)制技術(shù)。在同步方式中,數(shù)據(jù)的復(fù)制過(guò)程通常是更新事務(wù)的一部分,因此在事務(wù)完成后,主備數(shù)據(jù)庫(kù)的數(shù)據(jù)就會(huì)達(dá)到一致。而在異步方式中,備庫(kù)的更新往往會(huì)存在延時(shí),這取決于事務(wù)日志在主備數(shù)據(jù)庫(kù)之間傳輸?shù)臅r(shí)間長(zhǎng)短,如果傳輸時(shí)間過(guò)長(zhǎng)或者甚至在日志傳輸過(guò)程中出現(xiàn)異常導(dǎo)致無(wú)法及時(shí)將事務(wù)應(yīng)用到備庫(kù)上,那么很顯然,從備庫(kù)中讀取的數(shù)據(jù)將是舊的,因此就出現(xiàn)了數(shù)據(jù)不一致的情況。當(dāng)然,無(wú)論是采用多次重試還是人為數(shù)據(jù)訂正,關(guān)系型數(shù)據(jù)庫(kù)還是能夠保證最終數(shù)據(jù)達(dá)到一致——這就是系統(tǒng)提供最終一致性保證的經(jīng)典案例。
總的來(lái)說(shuō),BASE理論面向的是大型高可用可擴(kuò)展的分布式系統(tǒng),和傳統(tǒng)事務(wù)的ACID特性是相反的,它完全不同于ACID的強(qiáng)一致性模型,而是提出通過(guò)犧牲強(qiáng)一致性來(lái)獲得可用性,并允許數(shù)據(jù)在一段時(shí)間內(nèi)是不一致的,但最終達(dá)到一致?tīng)顟B(tài)。但同時(shí),在實(shí)際的分布式場(chǎng)景中,不同業(yè)務(wù)單元和組件對(duì)數(shù)據(jù)一致性的要求是不同的,因此在具體的分布式系統(tǒng)架構(gòu)設(shè)計(jì)過(guò)程中,ACID特性與BASE理論往往又會(huì)結(jié)合在一起使用。
小結(jié)
計(jì)算機(jī)系統(tǒng)從集中式向分布式的變革伴隨著包括分布式網(wǎng)絡(luò)、分布式事務(wù)和分布式數(shù)據(jù)一致性等在內(nèi)的一系列問(wèn)題與挑戰(zhàn),同時(shí)也催生了一大批諸如ACID、CAP和BASE等經(jīng)典理論的快速發(fā)展。
本章由計(jì)算機(jī)系統(tǒng)從集中式向分布式發(fā)展的過(guò)程展開(kāi),圍繞在分布式架構(gòu)發(fā)展過(guò)程中碰到的一系列問(wèn)題,結(jié)合ACID、CAP和BASE等分布式事務(wù)與一致性方面的經(jīng)典理論,向讀者介紹了分布式架構(gòu)。
……
問(wèn)題的提出
在計(jì)算機(jī)科學(xué)領(lǐng)域,分布式一致性問(wèn)題是一個(gè)相當(dāng)重要,且被廣泛探索與論證的問(wèn)題,通常存在于諸如分布式文件系統(tǒng)、緩存系統(tǒng)和數(shù)據(jù)庫(kù)等大型分布式存儲(chǔ)系統(tǒng)中。
什么是分布式一致性?分布式一致性分為哪些類型?分布式系統(tǒng)達(dá)到一致性后將會(huì)是一個(gè)什么樣的狀態(tài)?如果失去了一致性約束,分布式系統(tǒng)是否還可以依賴?如果一味地追求一致性,對(duì)系統(tǒng)的整體架構(gòu)和性能又有多大影響?這一系列的問(wèn)題,似乎都沒(méi)有一個(gè)嚴(yán)格意義上準(zhǔn)確的定義和答案。
終端用戶
IT技術(shù)的發(fā)展,讓我們受益無(wú)窮,從日常生活的超市收銀,到高端精細(xì)的火箭發(fā)射,現(xiàn)代社會(huì)中幾乎所有行業(yè),都離不開(kāi)計(jì)算機(jī)技術(shù)的支持。
盡管計(jì)算機(jī)工程師們創(chuàng)造出了很多高科技的計(jì)算機(jī)產(chǎn)品來(lái)解決我們?nèi)粘E龅降膯?wèn)題,但用戶只會(huì)傾向于選擇一些易用、好用的產(chǎn)品,那些難以使用的計(jì)算機(jī)產(chǎn)品最終都會(huì)被淘汰——這種易用性,其實(shí)就是用戶體驗(yàn)的一部分。
計(jì)算機(jī)產(chǎn)品的用戶體驗(yàn),可以分為便捷性、安全性和穩(wěn)定性等方面。在本書中,我們主要討論的是用戶在使用計(jì)算機(jī)產(chǎn)品過(guò)程中遇到的那些和一致性有關(guān)的問(wèn)題。在此之前,我們首先來(lái)看一下計(jì)算機(jī)產(chǎn)品的終端用戶是誰(shuí),他們的需求又是什么。
火車站售票
假如說(shuō)我們的終端用戶是一位經(jīng)常做火車的旅行家,通常他是去車站的售票處購(gòu)買車票,然后拿著車票去檢票口,再坐上火車,開(kāi)始一段美好的旅行——一切似乎都是那么和諧。想象一下,如果他選擇的目的地是杭州,而某一趟開(kāi)往杭州的火車只剩下最后一張車票了,可能在同一時(shí)刻,不同售票窗口的另一位乘客也購(gòu)買了同一張車票。假如說(shuō)售票系統(tǒng)沒(méi)有進(jìn)行一致性保障,兩人都購(gòu)票成功了。而在檢票口檢票的時(shí)候,其中一位乘客會(huì)被告知他的車票無(wú)效——當(dāng)然,現(xiàn)代的中國(guó)鐵路售票系統(tǒng)已經(jīng)很少出現(xiàn)這樣的問(wèn)題了,但在這個(gè)例子中,我們可以看出,終端用戶對(duì)于我們的系統(tǒng)的需求非常簡(jiǎn)單:
“請(qǐng)售票給我,如果沒(méi)有余票了,請(qǐng)?jiān)谑燮钡臅r(shí)候就告訴我票是無(wú)效票的?!?/p>
這就對(duì)購(gòu)票系統(tǒng)提出了嚴(yán)格的一致性要求——系統(tǒng)的數(shù)據(jù)(在本例中指的就是那趟開(kāi)往杭州的火車的余票數(shù)),無(wú)論在哪個(gè)售票窗口,每時(shí)每刻都必須是準(zhǔn)確無(wú)誤的!
銀行轉(zhuǎn)賬
假如說(shuō)我們的終端用戶是一名剛畢業(yè)的大學(xué)生,通常在拿到第一個(gè)月工資之后,都會(huì)選擇向家里匯款。當(dāng)他來(lái)到銀行柜臺(tái),完成轉(zhuǎn)賬操作后,銀行的柜臺(tái)服務(wù)員會(huì)友善地提醒他:“您的轉(zhuǎn)賬將在N個(gè)工作日后到賬!”此時(shí)這名畢業(yè)生有一些沮喪,會(huì)對(duì)那名柜臺(tái)服務(wù)員叮囑:“好吧,多久沒(méi)關(guān)系,錢不要少就行了!”——這也成為了幾乎所有的用戶對(duì)于現(xiàn)代銀行系統(tǒng)最基本的需求。
網(wǎng)上購(gòu)物
假如說(shuō)我們的終端用戶是一名網(wǎng)上購(gòu)物狂,當(dāng)他看到一件庫(kù)存量為5的心儀商品,會(huì)迅速地確認(rèn)購(gòu)買,寫下收貨地址,然后下單——然而,在下單的那個(gè)瞬間,系統(tǒng)可能會(huì)告知該用戶:“庫(kù)存量不足!”此時(shí),絕大部分的消費(fèi)者往往都會(huì)抱怨自己動(dòng)作太慢,使得心愛(ài)的商品被其他人搶走了!
但其實(shí)有過(guò)網(wǎng)購(gòu)系統(tǒng)開(kāi)發(fā)經(jīng)驗(yàn)的工程師一定明白,在商品詳情頁(yè)面上顯示的那個(gè)庫(kù)存量,通常不是該商品的真實(shí)庫(kù)存量,只有在真正下單購(gòu)買的時(shí)候,系統(tǒng)才會(huì)檢查該商品的真實(shí)庫(kù)存量。但是,誰(shuí)在意呢?
在上面三個(gè)例子中,相信讀者一定已經(jīng)看出來(lái)了,我們的終端用戶在使用不同的計(jì)算機(jī)產(chǎn)品時(shí)對(duì)于數(shù)據(jù)一致性的需求是不一樣的:
有些系統(tǒng),既要快速地響應(yīng)用戶,同時(shí)還要保證系統(tǒng)的數(shù)據(jù)對(duì)于任意客戶端都是真實(shí)可靠的,就像火車站的售票系統(tǒng)。
還有些系統(tǒng),需要為用戶保證絕對(duì)可靠的數(shù)據(jù)安全,雖然在數(shù)據(jù)一致性上存在延時(shí),但最終務(wù)必保證嚴(yán)格的一致,就像銀行的轉(zhuǎn)賬系統(tǒng)。
另外的一些系統(tǒng),雖然向用戶展示了一些可以說(shuō)是“錯(cuò)誤”的數(shù)據(jù),但是在整個(gè)系統(tǒng)使用過(guò)程中,一定會(huì)在某一個(gè)流程上對(duì)系統(tǒng)數(shù)據(jù)進(jìn)行準(zhǔn)確無(wú)誤的檢查,從而避免用戶發(fā)生不必要的損失,就像網(wǎng)購(gòu)系統(tǒng)。
更新的并發(fā)性
在計(jì)算機(jī)發(fā)展的早期階段,受到底層硬件技術(shù)的制約,同時(shí)也是由于人們對(duì)于計(jì)算機(jī)系統(tǒng)的實(shí)際使用需求比較簡(jiǎn)單,因此很多上層的應(yīng)用程序架構(gòu)都是單線程模型的。以C語(yǔ)言為例,其誕生于上世紀(jì)70年代,當(dāng)時(shí)幾乎所有使用C語(yǔ)言開(kāi)發(fā)的應(yīng)用程序都是單線程的。從現(xiàn)在來(lái)看,單線程應(yīng)用程序雖然在運(yùn)行效率上無(wú)法和后來(lái)的多線程應(yīng)用程序相比,但是在編程模型上相對(duì)簡(jiǎn)單,因此能夠避免多線程程序中出現(xiàn)的不少并發(fā)問(wèn)題。
隨著計(jì)算機(jī)底層硬件技術(shù)和現(xiàn)代操作系統(tǒng)的不斷發(fā)展,多線程技術(shù)開(kāi)始被越來(lái)越多地引入到計(jì)算機(jī)編程模型之中,并對(duì)現(xiàn)代計(jì)算機(jī)應(yīng)用程序的整體架構(gòu)起到了至關(guān)重要的作用。
多線程的引入,為應(yīng)用程序帶來(lái)性能上的卓越提升,同時(shí)也帶來(lái)了一個(gè)最大的副作用,那就是并發(fā)。《深入理解計(jì)算機(jī)系統(tǒng)》一書對(duì)并發(fā)進(jìn)行了如下定義:如果邏輯控制流在時(shí)間上重疊,那么它們就是并發(fā)的。這里提到的邏輯控制流,通俗地講,就是一次程序操作,比如讀取或更新內(nèi)存中變量的值。
在本書后面的討論中,我們提到的“并發(fā)”都特指更新操作的并發(fā),即有多個(gè)線程同時(shí)更新內(nèi)存中變量的值——我們將這一現(xiàn)象稱為更新的并發(fā)性。
分布式一致性問(wèn)題
在分布式系統(tǒng)中另一個(gè)需要解決的重要問(wèn)題就是數(shù)據(jù)的復(fù)制。在我們?nèi)粘5拈_(kāi)發(fā)經(jīng)驗(yàn)中,相信很多開(kāi)發(fā)人員都碰到過(guò)這樣的問(wèn)題:假設(shè)客戶端C1將系統(tǒng)中的一個(gè)值K由V1更新為V2,但客戶端C2無(wú)法立即讀取到K的最新值,需要在一段時(shí)間之后才能讀取到。讀者可能也已經(jīng)猜到了,上面這個(gè)例子就是常見(jiàn)的數(shù)據(jù)庫(kù)之間復(fù)制的延時(shí)問(wèn)題。
分布式系統(tǒng)對(duì)于數(shù)據(jù)的復(fù)制需求一般都來(lái)自于以下兩個(gè)原因。
為了增加系統(tǒng)的可用性,以防止單點(diǎn)故障引起的系統(tǒng)不可用。
提高系統(tǒng)的整體性能,通過(guò)負(fù)載均衡技術(shù),能夠讓分布在不同地方的數(shù)據(jù)副本都能夠?yàn)橛脩籼峁┓?wù)。
數(shù)據(jù)復(fù)制在可用性和性能方面給分布式系統(tǒng)帶來(lái)的巨大好處是不言而喻的,然而數(shù)據(jù)復(fù)制所帶來(lái)的一致性挑戰(zhàn),也是每一個(gè)系統(tǒng)研發(fā)人員不得不面對(duì)的。
所謂的分布式一致性問(wèn)題,是指在分布式環(huán)境中引入數(shù)據(jù)復(fù)制機(jī)制后,不同數(shù)據(jù)節(jié)點(diǎn)間可能出現(xiàn)的,并無(wú)法依靠計(jì)算機(jī)應(yīng)用程序自身解決的數(shù)據(jù)不一致情況。簡(jiǎn)單地講,數(shù)據(jù)一致性就是指在對(duì)一個(gè)副本數(shù)據(jù)進(jìn)行更新的同時(shí),必須確保也能夠更新其他的副本,否則不同副本之間的數(shù)據(jù)將不再一致。
那怎么來(lái)解決這個(gè)問(wèn)題呢?順著上面提到的復(fù)制延時(shí)問(wèn)題,很快就有人想到了一種解決辦法,那就是:
“既然是由于延時(shí)引起的問(wèn)題,那我可以將寫入的動(dòng)作阻塞,直到數(shù)據(jù)復(fù)制完成后,才完成寫入動(dòng)作?!?/p>
沒(méi)錯(cuò),這似乎能解決問(wèn)題,而且有一些系統(tǒng)的架構(gòu)也確實(shí)直接使用了這個(gè)思路。但這個(gè)思路在解決一致性問(wèn)題的同時(shí),又帶來(lái)了新的問(wèn)題:寫入的性能。如果你的應(yīng)用場(chǎng)景有非常多的寫請(qǐng)求,那么使用這個(gè)思路之后,后續(xù)的寫請(qǐng)求都將會(huì)阻塞在前一個(gè)請(qǐng)求的寫操作上,導(dǎo)致系統(tǒng)整理性能急劇下降。
總的來(lái)講,我們無(wú)法找到一種能夠滿足分布式系統(tǒng)所有系統(tǒng)屬性的分布式一致性解決方案。因此,如何既保證數(shù)據(jù)的一致性,同時(shí)又不影響系統(tǒng)運(yùn)行的性能,是每一個(gè)分布式系統(tǒng)都需要重點(diǎn)考慮和權(quán)衡的。于是,一致性級(jí)別由此誕生。
強(qiáng)一致性
這種一致性級(jí)別是最符合用戶直覺(jué)的,它要求系統(tǒng)寫入什么,讀出來(lái)的也會(huì)是什么,用戶體驗(yàn)好,但實(shí)現(xiàn)起來(lái)往往對(duì)系統(tǒng)的性能影響比較大。
弱一致性
這種一致性級(jí)別約束了系統(tǒng)在寫入成功后,不承諾立即可以讀到寫入的值,也不具體承諾多久之后數(shù)據(jù)能夠達(dá)到一致,但會(huì)盡可能地保證到某個(gè)時(shí)間級(jí)別(比如秒級(jí)別)后,數(shù)據(jù)能夠達(dá)到一致?tīng)顟B(tài)。弱一致性還可以再進(jìn)行細(xì)分:
會(huì)話一致性:該一致性級(jí)別只保證對(duì)于寫入的值,在同一個(gè)客戶端會(huì)話中可以讀到一致的值,但其他的會(huì)話不能保證。
用戶一致性:該一致性級(jí)別只保證對(duì)于寫入的值,在同一個(gè)用戶中可以讀到一致的值,但其他用戶不能保證。
最終一致性
最終一致性是弱一致性的一個(gè)特例,系統(tǒng)會(huì)保證在一定時(shí)間內(nèi),能夠達(dá)到一個(gè)數(shù)據(jù)一致的狀態(tài)。這里之所以將最終一致性單獨(dú)提出來(lái),是因?yàn)樗侨跻恢滦灾蟹浅V匾囊环N一致性模型,也是業(yè)界在大型分布式系統(tǒng)的數(shù)據(jù)一致性上比較推崇的模型。
本書將會(huì)從分布式一致性的理論出發(fā),向讀者講解幾種典型的分布式一致性協(xié)議是如何解決分布式一致性問(wèn)題的。之后,本書則會(huì)深入介紹分布式一致性問(wèn)題的工業(yè)解決方案——ZooKeeper,并著重向讀者展示這一分布式協(xié)調(diào)框架的使用方法、內(nèi)部實(shí)現(xiàn)以及運(yùn)維技巧。
致謝
首先要感謝現(xiàn)在的部門老大蔣江偉先生。第一次接觸蔣江偉是在2011年,當(dāng)時(shí)參加了他的一個(gè)講座“淘寶前臺(tái)系統(tǒng)優(yōu)化實(shí)踐——吞吐量?jī)?yōu)化”,對(duì)其中關(guān)于“編寫GC友好代碼”的內(nèi)容有不解之處,于是私下請(qǐng)教。他耐心的講解令我至今記憶猶新。兩年前,他全面負(fù)責(zé)中間件團(tuán)隊(duì)之后,給予了我更大的幫助和鼓勵(lì),使我得到了極大的進(jìn)步,真的非常感謝。本書的問(wèn)世,離不開(kāi)他的推薦。也正是這一份寫作的責(zé)任感,讓我有決心和毅力來(lái)對(duì)整個(gè)ZooKeeper內(nèi)容進(jìn)行了一次全面的整理。在這里,衷心祝福蔣江偉先生帶領(lǐng)中間件團(tuán)隊(duì)走向新的高度。
其次,本書的寫作,離不開(kāi)各位小伙伴們的支持和幫助,他們是各領(lǐng)域的資深專家,我向他們征集了很多有營(yíng)養(yǎng)的內(nèi)容。在這里,按照章節(jié)順序,依次表示感謝:許澤彬參與了“問(wèn)題提出”的寫作;侯前明對(duì)Paxos算法的前世今生進(jìn)行的整理;段培樂(lè)對(duì)晦澀的Paxos協(xié)議進(jìn)行了細(xì)致的講解;姜宇向我提供了他對(duì)于分布式事務(wù)的見(jiàn)解;徐偉辰參與了分布式鎖服務(wù)Chubby相關(guān)的寫作;葉成旭提供了他在上家公司時(shí)對(duì)Hypertable的學(xué)習(xí)和研究成果;高偉細(xì)致地向我展示了Curator這一ZooKeeper客戶端的使用;陳杰提供了他在“自動(dòng)化的DNS服務(wù)”場(chǎng)景中的經(jīng)驗(yàn)總結(jié);曹龍參與了Hadoop相關(guān)內(nèi)容的寫作;鄧明鑒則貢獻(xiàn)了他對(duì)HBase的深刻見(jiàn)解;作為產(chǎn)品的開(kāi)源負(fù)責(zé)人,莊曉丹和王強(qiáng)提供了對(duì)消息中間件Metamorphosis技術(shù)架構(gòu)的講解;李鼎則向我全面展示了RPC服務(wù)框架Dubbo的技術(shù)細(xì)節(jié);樓江航向我提供了Canal和Otter這兩個(gè)分布式產(chǎn)品中的ZooKeeper應(yīng)用場(chǎng)景;李雨前、柳明和溫朝凱則一起寫了終搜在產(chǎn)品演進(jìn)過(guò)程中對(duì)ZooKeeper的使用和改進(jìn);封仲淹參與了對(duì)其自主產(chǎn)品JStorm的技術(shù)剖析……是你們一遍又一遍地對(duì)內(nèi)容進(jìn)行修改,才使得本書內(nèi)容更為豐滿。
另外,也要感謝溫文鎏、王林、許澤彬、高偉和段培樂(lè)等人對(duì)全書的審閱,正是你們提出的寶貴建議,對(duì)完善本書提供了非常大的幫助。
感謝現(xiàn)在的同事陸學(xué)慧先生,從2013年下半年開(kāi)始,他全面接手對(duì)ZooKeeper的開(kāi)發(fā)和運(yùn)維,在他身上感受到的專業(yè)和創(chuàng)新精神讓我備受鼓舞。
另外,感謝我的第一個(gè)主管馬震先生,是他的幫助為我指引了方向,讓我有機(jī)會(huì)進(jìn)入ZooKeeper的世界,并負(fù)責(zé)這個(gè)產(chǎn)品在公司的發(fā)展。盡管由于業(yè)務(wù)調(diào)整,馬震先生已經(jīng)轉(zhuǎn)崗到其他部門,但依然由衷祝福他工作順利。
還要感謝我的同事,阿里巴巴店鋪平臺(tái)的侯前明先生。本來(lái)該書作者應(yīng)該是我們兩個(gè)人,但是由于期間他的家庭又增加了一個(gè)小生命,導(dǎo)致其不得不中途退出。從本書的選題到寫作大綱的制定,他都傾注了不少心血,相信如果有他一起創(chuàng)作,本書內(nèi)容會(huì)更加豐滿、深刻。這里表達(dá)遺憾的同時(shí),也向這位兩個(gè)孩子的父親送去祝福,祝愿他生活美滿。
感謝本書的責(zé)任編輯劉蕓女士,是她反復(fù)審稿和編排,才能讓本書的內(nèi)容趨于完美。
感謝本書的封面設(shè)計(jì)吳海燕女士,她的努力已經(jīng)無(wú)需言表,在技術(shù)書上的這一前衛(wèi)、極富視覺(jué)沖擊力的封面設(shè)計(jì),深深震撼到了我,也希望讀者朋友們能夠喜歡。
尤其感謝本書的策劃編輯張春雨先生。作為一個(gè)南方人,我很少有機(jī)會(huì)和那些有著一口北方腔的朋友交談,第一次接到張春雨先生電話的時(shí)候,我才真正領(lǐng)略了北京腔,也正是他的邀請(qǐng),才能讓我有機(jī)會(huì)進(jìn)行本書的撰寫,同時(shí)在前后將近1年半的漫長(zhǎng)寫作過(guò)程中,也是他的幫助和鼓勵(lì),才讓我堅(jiān)持完成并不斷完善本書的內(nèi)容。在這里,也衷心祝愿張春雨先生事業(yè)更上一層樓。
最后,還有我的父母,在過(guò)去的1年時(shí)間里,多次放假?zèng)]有回家,盡管父母一直鼓勵(lì)我專注工作,專注于自己的事業(yè),但我深知他們內(nèi)心對(duì)兒子的牽掛,在這里也深深地向他們道一聲:“謝謝”,也謹(jǐn)以此書獻(xiàn)給我最親愛(ài)的爸爸媽媽。
倪超
2014年12月于杭州淘寶城
更多建議: