File tree Expand file tree Collapse file tree 8 files changed +18
-18
lines changed
Expand file tree Collapse file tree 8 files changed +18
-18
lines changed Original file line number Diff line number Diff line change @@ -525,7 +525,7 @@ COMMIT;
525525
526526在 [ 第九章] ( ch9.md ) 中我们看到,在分布式环境中,强制执行唯一性约束需要共识:如果存在多个具有相同值的并发请求,则系统需要决定冲突操作中的哪一个被接受,并拒绝其他违背约束的操作。
527527
528- 达成这一共识的最常见方式是使单个节点作为领导,并使其负责所有决策。只要你不介意所有请求都挤过单个节点(即使客户端位于世界的另一端),只要该节点没有失效,系统就能正常工作。如果你需要容忍领导者失效,那么就又回到了共识问题(请参阅 “[ 单领导者复制与共识 ] ( ch9.md#单领导者复制与共识 ) ”)。
528+ 达成这一共识的最常见方式是使单个节点作为领导,并使其负责所有决策。只要你不介意所有请求都挤过单个节点(即使客户端位于世界的另一端),只要该节点没有失效,系统就能正常工作。如果你需要容忍领导者失效,那么就又回到了共识问题(请参阅 “[ 单主复制与共识 ] ( ch9.md#单主复制与共识 ) ”)。
529529
530530唯一性检查可以通过对唯一性字段分区做横向伸缩。例如,如果需要通过请求 ID 确保唯一性(如 [ 例 12-2] ( ) 所示),你可以确保所有具有相同请求 ID 的请求都被路由到同一分区(请参阅 [ 第六章] ( ch6.md ) )。如果你需要让用户名是唯一的,则可以按用户名的散列值做分区。
531531
Original file line number Diff line number Diff line change 3434
3535分区通常与复制结合使用,使得每个分区的副本存储在多个节点上。这意味着,即使每条记录属于一个分区,它仍然可以存储在多个不同的节点上以获得容错能力。
3636
37- 一个节点可能存储多个分区。如果使用主从复制模型,则分区和复制的组合如 [ 图 6-1] ( img/fig6-1.png ) 所示。每个分区领导者(主 )被分配给一个节点,追随者(从 )被分配给其他节点。 每个节点可能是某些分区的领导者,同时是其他分区的追随者 。
37+ 一个节点可能存储多个分区。如果使用主从复制模型,则分区和复制的组合如 [ 图 6-1] ( img/fig6-1.png ) 所示。每个分区领导者(主库 )被分配给一个节点,追随者(从库 )被分配给其他节点。 每个节点可能是某些分区的主库,同时是其他分区的从库 。
3838
3939我们在 [ 第五章] ( ch5.md ) 讨论的关于数据库复制的所有内容同样适用于分区的复制。大多数情况下,分区方案的选择与复制方案的选择是独立的,为简单起见,本章中将忽略复制。
4040
4141![ ] ( img/fig6-1.png )
4242
43- ** 图 6-1 组合使用复制和分区:每个节点充当某些分区的领导者,其他分区充当追随者 。**
43+ ** 图 6-1 组合使用复制和分区:每个节点充当某些分区的主库,其他分区充当从库 。**
4444
4545## 键值数据的分区
4646
Original file line number Diff line number Diff line change 313313
314314让我们考虑一个特别的情况,一件很有诱惑但也很危险的事情:依赖时钟,在多个节点上对事件进行排序。 例如,如果两个客户端写入分布式数据库,谁先到达? 哪一个更近?
315315
316- [ 图 8-3] ( img/fig8-3.png ) 显示了在具有多领导者复制的数据库中对时钟的危险使用 (该例子类似于 [ 图 5-9] ( img/fig5-9.png ) )。 客户端 A 在节点 1 上写入 ` x = 1 ` ;写入被复制到节点 3;客户端 B 在节点 3 上增加 x(我们现在有 ` x = 2 ` );最后这两个写入都被复制到节点 2。
316+ [ 图 8-3] ( img/fig8-3.png ) 显示了在具有多主复制的数据库中对时钟的危险使用 (该例子类似于 [ 图 5-9] ( img/fig5-9.png ) )。 客户端 A 在节点 1 上写入 ` x = 1 ` ;写入被复制到节点 3;客户端 B 在节点 3 上增加 x(我们现在有 ` x = 2 ` );最后这两个写入都被复制到节点 2。
317317
318318![ ] ( img/fig8-3.png )
319319
323323
324324尽管如此,[ 图 8-3] ( img/fig8-3.png ) 中的时间戳却无法正确排列事件:写入 ` x = 1 ` 的时间戳为 42.004 秒,但写入 ` x = 2 ` 的时间戳为 42.003 秒,即使 ` x = 2 ` 在稍后出现。当节点 2 接收到这两个事件时,会错误地推断出 ` x = 1 ` 是最近的值,而丢弃写入 ` x = 2 ` 。效果上表现为,客户端 B 的增量操作会丢失。
325325
326- 这种冲突解决策略被称为 ** 最后写入胜利(LWW)** ,它在多领导者复制和无领导者数据库 (如 Cassandra 【53】和 Riak 【54】)中被广泛使用(请参阅 “[ 最后写入胜利(丢弃并发写入)] ( ch5.md#最后写入胜利(丢弃并发写入) ) ” 一节)。有些实现会在客户端而不是服务器上生成时间戳,但这并不能改变 LWW 的基本问题:
326+ 这种冲突解决策略被称为 ** 最后写入胜利(LWW)** ,它在多主复制和无主数据库 (如 Cassandra 【53】和 Riak 【54】)中被广泛使用(请参阅 “[ 最后写入胜利(丢弃并发写入)] ( ch5.md#最后写入胜利(丢弃并发写入) ) ” 一节)。有些实现会在客户端而不是服务器上生成时间戳,但这并不能改变 LWW 的基本问题:
327327
328328* 数据库写入可能会神秘地消失:具有滞后时钟的节点无法覆盖之前具有快速时钟的节点写入的值,直到节点之间的时钟偏差消逝【54,55】。此方案可能导致一定数量的数据被悄悄丢弃,而未向应用报告任何错误。
329329* LWW 无法区分 ** 高频顺序写入** (在 [ 图 8-3] ( img/fig8-3.png ) 中,客户端 B 的增量操作 ** 一定** 发生在客户端 A 的写入之后)和 ** 真正并发写入** (写入者意识不到其他写入者)。需要额外的因果关系跟踪机制(例如版本向量),以防止违背因果关系(请参阅 “[ 检测并发写入] ( ch5.md#检测并发写入 ) ”)。
Original file line number Diff line number Diff line change 207207
208208* 共识算法(线性一致)
209209
210- 一些在本章后面讨论的共识算法,与单领导者复制类似 。然而,共识协议包含防止脑裂和陈旧副本的措施。正是由于这些细节,共识算法可以安全地实现线性一致性存储。例如,Zookeeper 【21】和 etcd 【22】就是这样工作的。
210+ 一些在本章后面讨论的共识算法,与单主复制类似 。然而,共识协议包含防止脑裂和陈旧副本的措施。正是由于这些细节,共识算法可以安全地实现线性一致性存储。例如,Zookeeper 【21】和 etcd 【22】就是这样工作的。
211211
212212* 多主复制(非线性一致)
213213
214214 具有多主程序复制的系统通常不是线性一致的,因为它们同时在多个节点上处理写入,并将其异步复制到其他节点。因此,它们可能会产生需要被解决的写入冲突(请参阅 “[ 处理写入冲突] ( ch5.md#处理写入冲突 ) ”)。这种冲突是因为缺少单一数据副本所导致的。
215215
216216* 无主复制(也许不是线性一致的)
217217
218- 对于无领导者复制的系统 (Dynamo 风格;请参阅 “[ 无主复制] ( ch5.md#无主复制 ) ”),有时候人们会声称通过要求法定人数读写( $w + r> n$ )可以获得 “强一致性”。这取决于法定人数的具体配置,以及强一致性如何定义(通常不完全正确)。
218+ 对于无主复制的系统 (Dynamo 风格;请参阅 “[ 无主复制] ( ch5.md#无主复制 ) ”),有时候人们会声称通过要求法定人数读写( $w + r > n$ )可以获得 “强一致性”。这取决于法定人数的具体配置,以及强一致性如何定义(通常不完全正确)。
219219
220220 基于日历时钟(例如,在 Cassandra 中;请参阅 “[ 依赖同步时钟] ( ch8.md#依赖同步时钟 ) ”)的 “最后写入胜利” 冲突解决方法几乎可以确定是非线性一致的,由于时钟偏差,不能保证时钟的时间戳与实际事件顺序一致。宽松的法定人数(请参阅 “[ 宽松的法定人数与提示移交] ( ch5.md#宽松的法定人数与提示移交 ) ”)也破坏了线性一致的可能性。即使使用严格的法定人数,非线性一致的行为也只是可能的,如下节所示。
221221
@@ -782,9 +782,9 @@ XA 事务解决了保持多个参与者(数据系统)相互一致的现实
782782
783783视图戳复制,Raft 和 Zab 直接实现了全序广播,因为这样做比重复 ** 一次一值(one value a time)** 的共识更高效。在 Paxos 的情况下,这种优化被称为 Multi-Paxos。
784784
785- #### 单领导者复制与共识
785+ #### 单主复制与共识
786786
787- 在 [ 第五章] ( ch5.md ) 中,我们讨论了单领导者复制 (请参阅 “[ 领导者与追随者] ( ch5.md#领导者与追随者 ) ”),它将所有的写入操作都交给主库,并以相同的顺序将它们应用到从库,从而使副本保持在最新状态。这实际上不就是一个全序广播吗?为什么我们在 [ 第五章] ( ch5.md ) 里一点都没担心过共识问题呢?
787+ 在 [ 第五章] ( ch5.md ) 中,我们讨论了单主复制 (请参阅 “[ 领导者与追随者] ( ch5.md#领导者与追随者 ) ”),它将所有的写入操作都交给主库,并以相同的顺序将它们应用到从库,从而使副本保持在最新状态。这实际上不就是一个全序广播吗?为什么我们在 [ 第五章] ( ch5.md ) 里一点都没担心过共识问题呢?
788788
789789答案取决于如何选择领导者。如果主库是由运维人员手动选择和配置的,那么你实际上拥有一种 ** 独裁类型** 的 “共识算法”:只有一个节点被允许接受写入(即决定写入复制日志的顺序),如果该节点发生故障,则系统将无法写入,直到运维手动配置其他节点作为主库。这样的系统在实践中可以表现良好,但它无法满足共识的 ** 终止** 属性,因为它需要人为干预才能取得 ** 进展** 。
790790
Original file line number Diff line number Diff line change @@ -525,7 +525,7 @@ COMMIT;
525525
526526在 [ 第九章] ( ch9.md ) 中我們看到,在分散式環境中,強制執行唯一性約束需要共識:如果存在多個具有相同值的併發請求,則系統需要決定衝突操作中的哪一個被接受,並拒絕其他違背約束的操作。
527527
528- 達成這一共識的最常見方式是使單個節點作為領導,並使其負責所有決策。只要你不介意所有請求都擠過單個節點(即使客戶端位於世界的另一端),只要該節點沒有失效,系統就能正常工作。如果你需要容忍領導者失效,那麼就又回到了共識問題(請參閱 “[ 單領導者複製與共識 ] ( ch9.md#單領導者複製與共識 ) ”)。
528+ 達成這一共識的最常見方式是使單個節點作為領導,並使其負責所有決策。只要你不介意所有請求都擠過單個節點(即使客戶端位於世界的另一端),只要該節點沒有失效,系統就能正常工作。如果你需要容忍領導者失效,那麼就又回到了共識問題(請參閱 “[ 單主複製與共識 ] ( ch9.md#單主複製與共識 ) ”)。
529529
530530唯一性檢查可以透過對唯一性欄位分割槽做橫向伸縮。例如,如果需要透過請求 ID 確保唯一性(如 [ 例 12-2] ( ) 所示),你可以確保所有具有相同請求 ID 的請求都被路由到同一分割槽(請參閱 [ 第六章] ( ch6.md ) )。如果你需要讓使用者名稱是唯一的,則可以按使用者名稱的雜湊值做分割槽。
531531
Original file line number Diff line number Diff line change 3434
3535分割槽通常與複製結合使用,使得每個分割槽的副本儲存在多個節點上。這意味著,即使每條記錄屬於一個分割槽,它仍然可以儲存在多個不同的節點上以獲得容錯能力。
3636
37- 一個節點可能儲存多個分割槽。如果使用主從複製模型,則分割槽和複製的組合如 [ 圖 6-1] ( ../img/fig6-1.png ) 所示。每個分割槽領導者(主 )被分配給一個節點,追隨者(從 )被分配給其他節點。 每個節點可能是某些分割槽的領導者,同時是其他分割槽的追隨者 。
37+ 一個節點可能儲存多個分割槽。如果使用主從複製模型,則分割槽和複製的組合如 [ 圖 6-1] ( ../img/fig6-1.png ) 所示。每個分割槽領導者(主庫 )被分配給一個節點,追隨者(從庫 )被分配給其他節點。 每個節點可能是某些分割槽的主庫,同時是其他分割槽的從庫 。
3838
3939我們在 [ 第五章] ( ch5.md ) 討論的關於資料庫複製的所有內容同樣適用於分割槽的複製。大多數情況下,分割槽方案的選擇與複製方案的選擇是獨立的,為簡單起見,本章中將忽略複製。
4040
4141![ ] ( ../img/fig6-1.png )
4242
43- ** 圖 6-1 組合使用複製和分割槽:每個節點充當某些分割槽的領導者,其他分割槽充當追隨者 。**
43+ ** 圖 6-1 組合使用複製和分割槽:每個節點充當某些分割槽的主庫,其他分割槽充當從庫 。**
4444
4545## 鍵值資料的分割槽
4646
Original file line number Diff line number Diff line change 313313
314314讓我們考慮一個特別的情況,一件很有誘惑但也很危險的事情:依賴時鐘,在多個節點上對事件進行排序。 例如,如果兩個客戶端寫入分散式資料庫,誰先到達? 哪一個更近?
315315
316- [ 圖 8-3] ( ../img/fig8-3.png ) 顯示了在具有多領導者複製的資料庫中對時鐘的危險使用 (該例子類似於 [ 圖 5-9] ( ../img/fig5-9.png ) )。 客戶端 A 在節點 1 上寫入 ` x = 1 ` ;寫入被複制到節點 3;客戶端 B 在節點 3 上增加 x(我們現在有 ` x = 2 ` );最後這兩個寫入都被複制到節點 2。
316+ [ 圖 8-3] ( ../img/fig8-3.png ) 顯示了在具有多主複製的資料庫中對時鐘的危險使用 (該例子類似於 [ 圖 5-9] ( ../img/fig5-9.png ) )。 客戶端 A 在節點 1 上寫入 ` x = 1 ` ;寫入被複制到節點 3;客戶端 B 在節點 3 上增加 x(我們現在有 ` x = 2 ` );最後這兩個寫入都被複制到節點 2。
317317
318318![ ] ( ../img/fig8-3.png )
319319
323323
324324儘管如此,[ 圖 8-3] ( ../img/fig8-3.png ) 中的時間戳卻無法正確排列事件:寫入 ` x = 1 ` 的時間戳為 42.004 秒,但寫入 ` x = 2 ` 的時間戳為 42.003 秒,即使 ` x = 2 ` 在稍後出現。當節點 2 接收到這兩個事件時,會錯誤地推斷出 ` x = 1 ` 是最近的值,而丟棄寫入 ` x = 2 ` 。效果上表現為,客戶端 B 的增量操作會丟失。
325325
326- 這種衝突解決策略被稱為 ** 最後寫入勝利(LWW)** ,它在多領導者複製和無領導者資料庫 (如 Cassandra 【53】和 Riak 【54】)中被廣泛使用(請參閱 “[ 最後寫入勝利(丟棄併發寫入)] ( ch5.md#最後寫入勝利(丟棄併發寫入) ) ” 一節)。有些實現會在客戶端而不是伺服器上生成時間戳,但這並不能改變 LWW 的基本問題:
326+ 這種衝突解決策略被稱為 ** 最後寫入勝利(LWW)** ,它在多主複製和無主資料庫 (如 Cassandra 【53】和 Riak 【54】)中被廣泛使用(請參閱 “[ 最後寫入勝利(丟棄併發寫入)] ( ch5.md#最後寫入勝利(丟棄併發寫入) ) ” 一節)。有些實現會在客戶端而不是伺服器上生成時間戳,但這並不能改變 LWW 的基本問題:
327327
328328* 資料庫寫入可能會神祕地消失:具有滯後時鐘的節點無法覆蓋之前具有快速時鐘的節點寫入的值,直到節點之間的時鐘偏差消逝【54,55】。此方案可能導致一定數量的資料被悄悄丟棄,而未嚮應用報告任何錯誤。
329329* LWW 無法區分 ** 高頻順序寫入** (在 [ 圖 8-3] ( ../img/fig8-3.png ) 中,客戶端 B 的增量操作 ** 一定** 發生在客戶端 A 的寫入之後)和 ** 真正併發寫入** (寫入者意識不到其他寫入者)。需要額外的因果關係跟蹤機制(例如版本向量),以防止違背因果關係(請參閱 “[ 檢測併發寫入] ( ch5.md#檢測併發寫入 ) ”)。
Original file line number Diff line number Diff line change 207207
208208* 共識演算法(線性一致)
209209
210- 一些在本章後面討論的共識演算法,與單領導者複製類似 。然而,共識協議包含防止腦裂和陳舊副本的措施。正是由於這些細節,共識演算法可以安全地實現線性一致性儲存。例如,Zookeeper 【21】和 etcd 【22】就是這樣工作的。
210+ 一些在本章後面討論的共識演算法,與單主複製類似 。然而,共識協議包含防止腦裂和陳舊副本的措施。正是由於這些細節,共識演算法可以安全地實現線性一致性儲存。例如,Zookeeper 【21】和 etcd 【22】就是這樣工作的。
211211
212212* 多主複製(非線性一致)
213213
214214 具有多主程式複製的系統通常不是線性一致的,因為它們同時在多個節點上處理寫入,並將其非同步複製到其他節點。因此,它們可能會產生需要被解決的寫入衝突(請參閱 “[ 處理寫入衝突] ( ch5.md#處理寫入衝突 ) ”)。這種衝突是因為缺少單一資料副本所導致的。
215215
216216* 無主複製(也許不是線性一致的)
217217
218- 對於無領導者複製的系統 (Dynamo 風格;請參閱 “[ 無主複製] ( ch5.md#無主複製 ) ”),有時候人們會聲稱透過要求法定人數讀寫( $w + r> n$ )可以獲得 “強一致性”。這取決於法定人數的具體配置,以及強一致性如何定義(通常不完全正確)。
218+ 對於無主複製的系統 (Dynamo 風格;請參閱 “[ 無主複製] ( ch5.md#無主複製 ) ”),有時候人們會聲稱透過要求法定人數讀寫( $w + r > n$ )可以獲得 “強一致性”。這取決於法定人數的具體配置,以及強一致性如何定義(通常不完全正確)。
219219
220220 基於日曆時鐘(例如,在 Cassandra 中;請參閱 “[ 依賴同步時鐘] ( ch8.md#依賴同步時鐘 ) ”)的 “最後寫入勝利” 衝突解決方法幾乎可以確定是非線性一致的,由於時鐘偏差,不能保證時鐘的時間戳與實際事件順序一致。寬鬆的法定人數(請參閱 “[ 寬鬆的法定人數與提示移交] ( ch5.md#寬鬆的法定人數與提示移交 ) ”)也破壞了線性一致的可能性。即使使用嚴格的法定人數,非線性一致的行為也只是可能的,如下節所示。
221221
@@ -782,9 +782,9 @@ XA 事務解決了保持多個參與者(資料系統)相互一致的現實
782782
783783檢視戳複製,Raft 和 Zab 直接實現了全序廣播,因為這樣做比重複 ** 一次一值(one value a time)** 的共識更高效。在 Paxos 的情況下,這種最佳化被稱為 Multi-Paxos。
784784
785- #### 單領導者複製與共識
785+ #### 單主複製與共識
786786
787- 在 [ 第五章] ( ch5.md ) 中,我們討論了單領導者複製 (請參閱 “[ 領導者與追隨者] ( ch5.md#領導者與追隨者 ) ”),它將所有的寫入操作都交給主庫,並以相同的順序將它們應用到從庫,從而使副本保持在最新狀態。這實際上不就是一個全序廣播嗎?為什麼我們在 [ 第五章] ( ch5.md ) 裡一點都沒擔心過共識問題呢?
787+ 在 [ 第五章] ( ch5.md ) 中,我們討論了單主複製 (請參閱 “[ 領導者與追隨者] ( ch5.md#領導者與追隨者 ) ”),它將所有的寫入操作都交給主庫,並以相同的順序將它們應用到從庫,從而使副本保持在最新狀態。這實際上不就是一個全序廣播嗎?為什麼我們在 [ 第五章] ( ch5.md ) 裡一點都沒擔心過共識問題呢?
788788
789789答案取決於如何選擇領導者。如果主庫是由運維人員手動選擇和配置的,那麼你實際上擁有一種 ** 獨裁型別** 的 “共識演算法”:只有一個節點被允許接受寫入(即決定寫入複製日誌的順序),如果該節點發生故障,則系統將無法寫入,直到運維手動配置其他節點作為主庫。這樣的系統在實踐中可以表現良好,但它無法滿足共識的 ** 終止** 屬性,因為它需要人為干預才能取得 ** 進展** 。
790790
You can’t perform that action at this time.
0 commit comments