前言
已經讀完本書的第二部分了,發現第一篇讀書筆記中的第5章應該放到這一篇來的,算了,有空改一下
目前讀到這兒的最大感受是,共鳴非常多,就是平時有很多耳熟而不一定能詳的名詞術語,在本書中都有多次提及並進行了詳細的討論(例如:數據分區,事務,ACID,分佈式系統,CAP理論, 兩階段提交, ZooKeeper等)
如果還在猶豫要不要讀這本書,希望看了這篇筆記後下定決心吧,啃它!
書中每部分的小結值得反覆閱讀~
一、數據分區
- 面對一些海量數據或非常高的查詢壓力,複製技術還不夠,我們還需要將數據拆分成爲分區,也稱爲分片 P189
- 分區的定義:每一條數據只屬於某個特定分區,每個分區都可以視爲一個完整的小型數據庫,雖然數據庫可能存在一些跨分區的成分 P189
- 採用數據分區的主要目的是提高可擴展性,不同的分區可以放在一個無共享集羣的不同節點上 P189
- 分區與複製通常結合使用 P190
- 分區的主要目的是將數據和查詢負載均勻分佈在所有節點上
- 分區不均勻會導致“傾斜” P191
- 基於關鍵字的分區 P191
- 基於關鍵字哈希值分區 P193
- 一致性哈希
- 二級索引技術是Solr和Elasticsearch等全文索引服務器存在之根本 P195
- 基於文檔分區的二級索引
- 基於詞條的二級索引分區
- 分區在平衡 P198
- 隨着時間的推移,分區數據總會出現一些變化,這些變化要求數據和請求可以從一個節點轉移到另一個節點
- 這樣一個遷移負載的過程稱爲再平衡(or 動態平衡)
- 無論哪種分區方案,分區再平衡通常至少滿足
- 平衡之後,負載、數據存儲、讀寫請求等應該再集羣範圍更均勻的分佈
- 在平衡執行過程中,數據庫應該可以繼續正常提供讀寫服務
- 避免不必要的負載遷移,以加快動態平衡,並減少網絡和磁盤I/O影響
- 動態再平衡策略 P198
- 取模的缺點
- 使用固定數據量的分區 p199
- 動態分區
- 當分區的數據增長超過一個可配的參數閾值(HBase上默認是10GB),他就拆分爲兩個分區,每個承擔一半的數據量,相反,如果有大量的數據被刪除,並且分區縮小到某個閾值以下,則將其與相鄰分區進行合併。該過程類似於B樹的分裂操作
- 預分裂
- 按節點比例分區
- 請求路由
- 現在已經將數據集分佈到多個節點上,但是仍有一個懸而未決的問題,當客戶端需要發送請求時,如何知道應該連接哪個節點?如果發生了分區再平衡,分區與節點的對應關係隨之還會變化。
- 幾種不同的路由處理策略 P202
- 允許客戶端鏈接任意的節點,如果恰好擁有所請求的分區,則直接處理該請求,否則,將請求轉發到下一個合適的節點
- 將所有請求發送到一個路由層,由其進行轉發
- 客戶端感知分區和節點的關係。此時,客戶端可以直接連接到目標節點,而不需要任何中介。
- 小結 P205
二、 事務
- 事務將應用程序的多個讀、寫操作捆綁在一起成爲一個邏輯操作單元。即事務中的所有讀寫是一個執行的整體,整個事務要麼成功(提交)、要麼失敗(終止或回滾)。如果失敗,應用程序可以安全的重試
- ACID的含義 P213
- 原子性(Atomicity)、一致性(Consistency)、隔離性(Isolation)與持久性(Durability)
- 不符合ACID標準的系統被冠以BASE,即基本可用性(Basically Available)、軟狀態(soft state)和最終一致性(Eventual consistency),但這基本沒有什麼實際作用
- 原子性定義的特徵是:再出錯時終止事務,並將部分完成的寫入全部丟棄。
- 一致性 P214
- 一致性非常重要,但它在不同場合有着不同的具體含義,例如:
- 討論副本一致性以及異步複製模型時,引出了最終一致性問題(參閱第五章複製滯後問題)
- 一致性哈希則是某些系統用於動態分區再平衡的方法(參見第6章一致性哈希)
- CAP理論中,一致性一次用來表示線性化(參見第9章“可線性化”)
- 而在ACID中,一致性主要指數據庫處於應用程序所期待的“預期狀態”
- ACID中的一致性主要是指對數據有特定的預期狀態,任何數據更改必須滿足這些狀態約束(或者恆等條件)
- 一致性非常重要,但它在不同場合有着不同的具體含義,例如:
- 原子性,隔離性和持久性是數據庫自身的屬性,而ACID中的一致性更多的是應用層的屬性
- 隔離性 P215
- 併發執行的多個事務相互隔離,他們不能互相交叉
- 持久性 P215
- 持久性保證一旦事務提交成功,及時存在硬件故障或數據庫崩潰,事務所寫入的任何數據也不會消失
- 對於某個特定鏈接,SQL語句BEGIN TRANSACTION和COMMIT之間的所有操作和屬於同一個事務
- 單對象寫入 P219
- 通常意義上的事務針對的是多個對象,將多個操作聚合爲一個邏輯執行單元 P219
- 弱隔離級別 P221
- 讀提交是最基本的事務隔離級別,它只提供以下兩個保證
- 讀數據庫時,只能看到已成功提交的數據(防止髒讀)
- 寫數據庫時,只會赴會已經成功提交的數據(防止髒寫)
- 數據庫通常採用行級鎖來防止髒寫 p224
- 當事務想修改某個對象(例如行或文檔)時,它必須首先獲得該對象的鎖;然後一直持有鎖直到事務提交(或終止)後,才能獲得鎖並繼續 P224
- 防止髒寫(採用讀鎖並不可行,運行較長時間的寫事務會導致許多隻讀的事務等待太長時間)
- 對於每個待更新的對象,數據庫都會維護其舊值和當前持鎖事務將要設置的新值兩個版本。在事務提交之前,所有其他讀都讀取舊值;僅當寫事務提交之後,纔會切換到讀取新值
- 讀提交是最基本的事務隔離級別,它只提供以下兩個保證
- 快照級別隔離與可重複讀 P225
- 如果查詢的是數據庫在某時刻點所凍結的一致性快照,則查詢結果的含義非常明確
- 多版本併發控制(MVCC) P227
- 考慮到多個正在進行的事務可能會在不同的時間點查看數據庫狀態,所以數據庫保留了對象多個不同的提交版本,這種技術因此也被稱爲多版本併發控制
- 典型的做法是,在讀-提交級別下,對每一個不同的查詢單獨創建快照;而快照級別隔離則是使用一個快照來運行整個事務。
- 一致快照的可見性原則 P228
- 處理兩個寫事務併發的解決方案 P230
- 原子寫操作,如果原子操作可行,那麼它就是推薦的最佳方式
- 顯式加鎖
- 自動檢測更新丟失 P232
- 原子比較和設置
- 衝突解決與複製
- 寫傾斜與幻讀 P233
- 寫傾斜與幻讀 P233
- 可以講寫傾斜視爲一種更爲廣義的更新丟失問題。即如果兩個事務讀取相同的一組對象,然後更新其中一部分。
- 不同事務可能更新不同的對象,則可能發生寫傾斜;
- 而不同的事務如果更新的是同一個對象,則可能發生髒寫或更新丟失。
- 解決方案
- 串行化隔離級別
- 對事務依賴的行進行顯式的加鎖 P235
- 更多寫傾斜的例子(會議室預定系統,多人遊戲,聲明一個用戶名,防止雙重開支) P236
- 產生寫傾斜的原因 P236
- 幻讀 P237
- 在一個事務中的寫入改變了另一個事務查詢結果的現象,稱爲幻讀
- 實體化衝突解決幻讀(書中不建議這麼做)
- 串行化 P237
- 解決併發的方式是避免併發
- 串行執行小結,當滿足以下約束條件時,串行執行事務可以實現串行化隔離
- 事務必須剪短而高效,否則一個緩慢的事務會影響到所有其他事務的執行性能;
- 僅限於活動數據集完全可以加載到內存的場景。有些很少訪問的數據可能會被移到磁盤,但萬一單線程事務需要訪問它,就會嚴重拖累性能
- 寫入吞吐量必須足夠低,才能在單個CPU核上處理;否則就需要採用分區,最好沒有跨分區事務
- 跨分區事務雖然也可以支持,但是佔比必須很小
- 兩階段加鎖 P242
- 快照級別隔離的口號“讀寫互不干擾” P243
- 謂詞鎖 P244
- 作用類似於之前描述的共享/獨佔鎖,而區別在於,他並不屬於某個特定的對象,而是作用與滿足某些搜索條件的所有查詢對象。
- 索引區間鎖 P245
- 可串行化快照隔離 P246
- 小結 P250
三、分佈式系統的挑戰
- 在分佈式系統中,可能會出現系統的一部分工作正常,但其他某些部分出現難以預測的故障,稱之爲“部分失效”
- 無共享並不是構建集羣系統的唯一方式,但它卻是構建互聯網服務的主流方式 P263
- 不可靠的網絡 P262
- 檢測故障 p265
- 許多系統都需要自動檢測節點失效這樣的功能,例如:
- 負載均衡器要避免向已失效的節點繼續分發請求(即將其做下線處理)
- 對於主從複製的分佈式數據庫,如果主節點失敗,需要將某個從節點提升爲主節點。不過,由於網絡的不確定性很難準確判斷節點是否確實失效。
- …還有4點,直接看書吧:)
- 許多系統都需要自動檢測節點失效這樣的功能,例如:
- 超時是故障檢測的有效辦法,但不幸的是,超時的時常沒有標準可言 P266
- 網絡擁塞與排隊
- 駕車時往往由於交通堵塞,導致行車時間變化很大,同樣,計算機網絡上數據包延時的變化根源往往在於排隊 P267
- 爲什麼數據中心網絡和互聯網採用分組交換而不是電路交換網絡呢?答案是,他們針對突發流量進行了很多優化 P270
- 總之,當前廣泛部署的技術無法爲我們提供延遲或可靠性方面的硬件級保證,我們必須假設會出現網絡擁塞,排隊,和無上限的延遲。基於此,超時設置並不存在絕對正確的值,而是需要通過實驗的方式來確定。 P270
- 延遲與資源利用率 P271
- 如果資源總是靜態分配(例如,專用硬件和預留帶寬分配),則某些環境下可以保證延遲的確定性。但是,這是以降低資源使用率爲代價的,換句話說,其成本過於昂貴,而多租戶、動態資源分配方式則可以提供更高的資源使用率,因而成本更低,當然也引入了可變延遲的缺點
- 網絡中的可變延遲並不是一種自然規律,只是成本與收益互相博弈的結果
- 分佈式系統多節點間複製數據時,可能由於時鐘的時間差導致數據庫寫入丟失 P276
- 快照隔離,廣泛用於小數據量,快速讀寫的事務以及大數據量,長時間運行的只讀事務(例如設備分析),可以在數據庫的某個一致狀態上不需加鎖、不違背讀寫隔離性的前提下高效支持只讀事務。 P 278
- 開發實時系統代價昂貴的原因 P282
- 知識,真相與謊言 P282
- 如果節點存在“撒謊”的情況(即故意發送錯誤的活破壞性的響應),那麼分佈式系統處理的難度就上了一個臺階。例如,節點明明沒有收到某條消息,但卻對外聲稱收到了。這種行爲稱爲拜占庭故障,在這樣不信任的環境中需要達成共識的問題也被稱爲拜占庭將軍問題 P286
- 在絕大多數服務器端數據系統中,部署拜占庭容錯解決方案基本不太可行。
- 系統協議異常複雜
- 依賴於硬件層面的支持
- 對於真實系統的建模,最普遍的組合是崩潰-恢復模型結合部分同步模型。 P290
- 小結 P292
四、一致性與共識
- 分佈式系統可能發生的故障:數據包丟失、順序紊亂、重複發送或者延遲、時鐘偏差、節點暫停(例如由於垃圾回收)甚至隨時崩潰
- 分佈式系統最重要的抽象之一就是共識:所有的節點就某一項提議達成一致 P303
- 爲了使系統可線性化,需要添加一個重要的約束:一旦某個讀操作返回了新值,之後所有的讀(包括相同或不同客戶端)都必須返回新值 P308
- 可線性化與可串行化的區別 P311
- 主從複製的系統需要確保有且只有一個主節點,否則會產生腦裂;選舉行的主節點的常見的方法是使用鎖:即每個啓動的節點都試圖獲得鎖,其中只有一個可以成功,即稱爲主節點。 P311
- 不管鎖具體如何實現,他必須滿足線性化:所有節點都必須同意哪個節點持有鎖,否則就會出現問題。
- 線性化本質上意味着“表現的好像只有一個數據副本,且其上的所有操作都是原子的 ”。 P313
- CAP理論 P317
- 不要求線性化的應用更能容忍網絡故障,這種思路通常被稱爲CAP定理
- CAP有時也代表一致性,可用性,分區容錯性,系統通常只能支持其中兩種特性。 P317
- 不過,上述理解存在誤導性,網絡區分是一種故障,不管喜歡還是不喜歡,它都可能發生,所以無法選擇或逃避區分的問題。
- 在網絡正常的時候,系統可以同時保證一致性(線性化)和可用性,而一旦發生了網絡故障,必須要麼選擇線性(一致性),要麼可用性。因此,更準確的稱呼應該是“網絡區分情況下,選擇一致還是可用”。
- 圍繞了CAP有太多的誤解與困擾,最後反而無法幫助我們更好的理解系統(書中建議所以最好避免使用CAP)
- 之所以放棄線性化的原因就是性能,而不是爲了容錯。 P318
- 在可線性化數據存儲中不存在併發操作,一定有一個時間線將所有操作都全序執行。 P321
- 可線性化一定因爲着因果關係 P322
- Lamport時間戳 P325
- Lamport時間戳與物理牆上時鐘並不存在直接對應關係,但它可以保證全序:給定兩個Lamport時間戳,計數器較大的那個時間戳大;如計數器值正好相同,則節點越大,時間戳越大。
- 全序關係廣播 P327
- 全序關係廣播正式數據複製所需要的:如果每條消息代表數據庫寫請求,並且每個副本都按相同的順序處理這些請求,那麼所有副本可以保持一致(或許有些滯後);該原則也被稱爲狀態機複製。 P328
- 分佈式事務與共識 P330
- 共識問題是分佈式計算中最重要也是最基本的問題之一。表面上看,目標只是讓幾個節點就某件事達成一致。這似乎很簡單,或者至少不應該太難。不幸的是,許多失敗的系統正式由於低估了這個問題所導致的。
- 需要集羣節點達成一致的部分重要場景 P331
- 主節點選舉
- 原子事務提交
- 兩階段提交(2PC)算法是解決原子提交最常見的方法。在各種數據庫、消息系統和應用服務器中都有實現。
- 單節點上,事務的提交非常依賴於數據持久寫入磁盤的順序關係:先寫入數據,然後在提交記錄。 P322
- 事務提交(或)終止的關鍵點在於磁盤完成日誌記錄的時刻:在完成日誌記錄寫之前如果發生了崩潰,則事務需要終止;
- 如果在日誌寫入完成之後,即使放生崩潰,事務也被安全提交。
- 通常2PC事務從應用程序在多數據庫節點上執行數據讀/寫開始。我們將這些數據庫節點稱爲事務中的參與者。當應用程序準備提交事務時,協調者開始階段1:發送一個準備請求到所有節點,詢問他們是否可以提交。協調周然後跟蹤參與者的迴應 P334
- 如果所有參與者回答“是”,表示他們已經準備好提交,那麼協調者接下來在階段2會發出提交請求,提交開始實際執行
- 如果有任何參數者會回覆“否”,則協調者在階段2中想所有節點發送放棄請求
- 2PC協議有兩個關鍵點 P336
- 當參與者投票“是”時,它做出肯定提交的承諾(儘管還取決於其他參與者的投票,協調者才能做出做後的決定)
- 協調者做出了提交(或者放棄)的決定,這個決定也是不可撤銷。正是這兩個承諾確保了2PC的原子性
- 單節點的原子提交其實是將兩個事件合二爲一,寫入事務日誌即提交。
- 協調者發生故障 P336
- 如果在決定到達之前,出現協調者崩潰或者網絡故障,則參與者只能無奈等待。此時參與者處在一種不確定的狀態。
- 2PC能夠順利完成的唯一方法是等待協調者恢復。
- 兩種不同的分佈式數據庫概念 P338
- 數據庫內部的分佈式事務
- 異構分佈式事務
- XA事務 P339
- XA事務解決了多個參與者之間如何達成一致這樣一個非常現實而重要的問題,但也引入了不少操作方面的限制 P341
- 共識問題總結 P341
- 通過使用共識算法來決定這些不相容的操作之中誰是獲勝者
- 共識算法必須滿足以下性質 P342
- 協商一致性,所有節點都接受相同的協議
- 誠實性,所有節點不能反悔,即對一項提議不能有兩次決定
- 合法性,如果決定了值v,則v一定是由某個節點所提議的
- 可終止性,節點如果不崩潰最終一定可以達成決議
- 全序關係廣播相當於持續的多輪共識(每一輪共識決定對應於一條消息) P343
- Epoch:世代編號,對於主從複製
- 如果法相當前的主節點失效,節點就開始一輪投票選舉新的主節點。
- 選舉會賦予一個單調遞增的epoch號
- 如果出現了兩個不同的節點對應於不同epoch號碼(例如上一個epoch號碼的主節點其實並沒有正真掛掉),則具有更高epoch號碼的主節點將獲勝
- 共識的侷限性 P345
- ZooKeeper和etcd主要針對保存少量、可完全載入內存的數據(雖然他們最終仍要寫入磁盤以支持持久性)而設計,所以不要用他們保存大量的數據。他們通常採用容錯的全序廣播算法在所有節點上覆制這些數據從而實現高可靠 P347
- 小結 P349
參考文檔
《數據密集型應用系統設計》