mirror of
https://github.com/Vonng/ddia.git
synced 2024-12-06 15:20:12 +08:00
update translations in ch5.md
This commit is contained in:
parent
63915347a2
commit
1a4321904e
29
ch5.md
29
ch5.md
@ -230,22 +230,22 @@
|
||||
|
||||
### 单调读
|
||||
|
||||
从异步从库读取第二个异常例子是,用户可能会遇到 **时光倒流(moving backward in time)**。
|
||||
在从异步从库读取时可能发生的异常的第二个例子是用户可能会遇到 **时光倒流(moving backward in time)**。
|
||||
|
||||
如果用户从不同从库进行多次读取,就可能发生这种情况。例如,[图 5-4](img/fig5-4.png) 显示了用户 2345 两次进行相同的查询,首先查询了一个延迟很小的从库,然后是一个延迟较大的从库(如果用户刷新网页,而每个请求被路由到一个随机的服务器,这种情况是很有可能的)。第一个查询返回最近由用户 1234 添加的评论,但是第二个查询不返回任何东西,因为滞后的从库还没有拉取写入内容。在效果上相比第一个查询,第二个查询是在更早的时间点来观察系统。如果第一个查询没有返回任何内容,那问题并不大,因为用户 2345 可能不知道用户 1234 最近添加了评论。但如果用户 2345 先看见用户 1234 的评论,然后又看到它消失,那么对于用户 2345,就很让人头大了。
|
||||
如果用户从不同从库进行多次读取,就可能发生这种情况。例如,[图 5-4](img/fig5-4.png) 显示了用户 2345 两次进行相同的查询,首先查询了一个延迟很小的从库,然后是一个延迟较大的从库(如果用户刷新网页时每个请求都被路由到一个随机的服务器,这种情况就很有可能发生)。第一个查询返回了最近由用户 1234 添加的评论,但是第二个查询不返回任何东西,因为滞后的从库还没有拉取到该写入内容。实际上可以认为第二个查询是在比第一个查询更早的时间点上观察系统。如果第一个查询没有返回任何内容,那问题并不大,因为用户 2345 可能不知道用户 1234 最近添加了评论。但如果用户 2345 先看见用户 1234 的评论,然后又看到它消失,这就会让人觉得非常困惑了。
|
||||
|
||||
![](img/fig5-4.png)
|
||||
|
||||
**图 5-4 用户首先从新副本读取,然后从旧副本读取。时光倒流。为了防止这种异常,我们需要单调的读取。**
|
||||
**图 5-4 用户首先从新副本读取,然后从旧副本读取。时间看上去回退了。为了防止这种异常,我们需要单调的读取。**
|
||||
|
||||
**单调读(Monotonic reads)**【23】保证这种异常不会发生。这是一个比 **强一致性(strong consistency)** 更弱,但比 **最终一致性(eventual consistency)** 更强的保证。当读取数据时,你可能会看到一个旧值;单调读取仅意味着如果一个用户顺序地进行多次读取,则他们不会看到时间后退,即,如果先前读取到较新的数据,后续读取不会得到更旧的数据。
|
||||
**单调读(monotonic reads)**【23】可以保证这种异常不会发生。这是一个比 **强一致性(strong consistency)** 更弱,但比 **最终一致性(eventual consistency)** 更强的保证。当读取数据时,你可能会看到一个旧值;单调读仅意味着如果一个用户顺序地进行多次读取,则他们不会看到时间回退,也就是说,如果已经读取到较新的数据,后续的读取不会得到更旧的数据。
|
||||
|
||||
实现单调读取的一种方式是确保每个用户总是从同一个副本进行读取(不同的用户可以从不同的副本读取)。例如,可以基于用户 ID 的散列来选择副本,而不是随机选择副本。但是,如果该副本失败,用户的查询将需要重新路由到另一个副本。
|
||||
实现单调读的一种方式是确保每个用户总是从同一个副本进行读取(不同的用户可以从不同的副本读取)。例如,可以基于用户 ID 的散列来选择副本,而不是随机选择副本。但是,如果该副本出现故障,用户的查询将需要重新路由到另一个副本。
|
||||
|
||||
|
||||
### 一致前缀读
|
||||
|
||||
第三个复制延迟例子违反了因果律。 想象一下 Poons 先生和 Cake 夫人之间的以下简短对话:
|
||||
第三个复制延迟异常的例子违反了因果律。 想象一下 Poons 先生和 Cake 夫人之间的以下简短对话:
|
||||
|
||||
*Mr. Poons*
|
||||
> Mrs. Cake,你能看到多远的未来?
|
||||
@ -255,7 +255,7 @@
|
||||
|
||||
这两句话之间有因果关系:Cake 夫人听到了 Poons 先生的问题并回答了这个问题。
|
||||
|
||||
现在,想象第三个人正在通过从库来听这个对话。 Cake 夫人说的内容是从一个延迟很低的从库读取的,但 Poons 先生所说的内容,从库的延迟要大的多(见 [图 5-5](img/fig5-5.png))。 于是,这个观察者会听到以下内容:
|
||||
现在,想象第三个人正在通过从库来听这个对话。 Cake 夫人说的内容是从一个延迟很低的从库读取的,但 Poons 先生所说的内容,从库的延迟要大的多(见 [图 5-5](img/fig5-5.png))。于是,这个观察者会听到以下内容:
|
||||
|
||||
*Mrs. Cake*
|
||||
> 通常约十秒钟,Mr. Poons.
|
||||
@ -263,28 +263,27 @@
|
||||
*Mr. Poons*
|
||||
> Mrs. Cake,你能看到多远的未来?
|
||||
|
||||
对于观察者来说,看起来好像 Cake 夫人在 Poons 先生提问前就回答了这个问题。
|
||||
这种超能力让人印象深刻,但也会把人搞糊涂。【25】。
|
||||
对于观察者来说,看起来好像 Cake 夫人在 Poons 先生提问前就回答了这个问题。这种超能力让人印象深刻,但也会把人搞糊涂。【25】。
|
||||
|
||||
![](img/fig5-5.png)
|
||||
|
||||
**图 5-5 如果某些分区的复制速度慢于其他分区,那么观察者在看到问题之前可能会看到答案。**
|
||||
**图 5-5 如果某些分区的复制速度慢于其他分区,那么观察者可能会在看到问题之前先看到答案。**
|
||||
|
||||
防止这种异常,需要另一种类型的保证:**一致前缀读(consistent prefix reads)**【23】。 这个保证说:如果一系列写入按某个顺序发生,那么任何人读取这些写入时,也会看见它们以同样的顺序出现。
|
||||
要防止这种异常,需要另一种类型的保证:**一致前缀读(consistent prefix reads)**【23】。这个保证的意思是说:如果一系列写入按某个顺序发生,那么任何人读取这些写入时,也会看见它们以同样的顺序出现。
|
||||
|
||||
这是 **分区(partitioned)** 或 **分片(sharded)** 数据库中的一个特殊问题,将在 [第六章](ch6.md) 中讨论。如果数据库总是以相同的顺序应用写入,则读取总是会看到一致的前缀,所以这种异常不会发生。但是在许多分布式数据库中,不同的分区独立运行,因此不存在 **全局写入顺序**:当用户从数据库中读取数据时,可能会看到数据库的某些部分处于较旧的状态,而某些处于较新的状态。
|
||||
这是 **分区(partitioned)** 或 **分片(sharded)** 数据库中的一个特殊问题,我们将在 [第六章](ch6.md) 中讨论分区数据库。如果数据库总是以相同的顺序应用写入,而读取总是看到一致的前缀,那么这种异常不会发生。但是在许多分布式数据库中,不同的分区独立运行,因此不存在 **全局的写入顺序**:当用户从数据库中读取数据时,可能会看到数据库的某些部分处于较旧的状态,而某些则处于较新的状态。
|
||||
|
||||
一种解决方案是,确保任何因果相关的写入都写入相同的分区。对于某些无法高效完成这种操作的应用,还有一些显式跟踪因果依赖关系的算法,本书将在 “[“此前发生” 的关系和并发](#“此前发生”的关系和并发)” 一节中返回这个主题。
|
||||
一种解决方案是,确保任何因果相关的写入都写入相同的分区,但在一些应用中可能无法高效地完成这种操作。还有一些显式跟踪因果依赖关系的算法,我们将在 “[“此前发生” 的关系和并发](#“此前发生”的关系和并发)” 一节中回到这个话题。
|
||||
|
||||
### 复制延迟的解决方案
|
||||
|
||||
在使用最终一致的系统时,如果复制延迟增加到几分钟甚至几小时,则应该考虑应用程序的行为。如果答案是 “没问题”,那很好。但如果结果对于用户来说是不好体验,那么设计系统来提供更强的保证是很重要的,例如 **写后读**。明明是异步复制却假设复制是同步的,这是很多麻烦的根源。
|
||||
在使用最终一致的系统时,如果复制延迟增加到几分钟甚至几小时,则应该考虑应用程序的行为。如果答案是 “没问题”,那很好。但如果结果对于用户来说是不好的体验,那么设计系统来提供更强的保证(例如 **写后读**)是很重要的。明明是异步复制却假设复制是同步的,这是很多麻烦的根源。
|
||||
|
||||
如前所述,应用程序可以提供比底层数据库更强有力的保证,例如通过主库进行某种读取。但在应用程序代码中处理这些问题是复杂的,容易出错。
|
||||
|
||||
如果应用程序开发人员不必担心微妙的复制问题,并可以信赖他们的数据库 “做了正确的事情”,那该多好呀。这就是 **事务(transaction)** 存在的原因:**数据库通过事务提供强大的保证**,所以应用程序可以更加简单。
|
||||
|
||||
单节点事务已经存在了很长时间。然而在走向分布式(复制和分区)数据库时,许多系统放弃了事务。声称事务在性能和可用性上的代价太高,并断言在可伸缩系统中最终一致性是不可避免的。这个叙述有一些道理,但过于简单了,本书其余部分将提出更为细致的观点。第七章和第九章将回到事务的话题,并讨论一些替代机制。
|
||||
单节点事务已经存在了很长时间。然而在走向分布式(复制和分区)数据库时,许多系统放弃了事务,声称事务在性能和可用性上的代价太高,并断言在可伸缩系统中最终一致性是不可避免的。这个叙述有一些道理,但过于简单了,本书其余部分将提出更为细致的观点。我们将在 [第七章](ch7.md) 和 [第九章](ch9.md) 回到事务的话题,并将在 [第三部分](part-iii.md) 讨论一些替代机制。
|
||||
|
||||
|
||||
## 多主复制
|
||||
|
29
zh-tw/ch5.md
29
zh-tw/ch5.md
@ -230,22 +230,22 @@
|
||||
|
||||
### 單調讀
|
||||
|
||||
從非同步從庫讀取第二個異常例子是,使用者可能會遇到 **時光倒流(moving backward in time)**。
|
||||
在從非同步從庫讀取時可能發生的異常的第二個例子是使用者可能會遇到 **時光倒流(moving backward in time)**。
|
||||
|
||||
如果使用者從不同從庫進行多次讀取,就可能發生這種情況。例如,[圖 5-4](../img/fig5-4.png) 顯示了使用者 2345 兩次進行相同的查詢,首先查詢了一個延遲很小的從庫,然後是一個延遲較大的從庫(如果使用者重新整理網頁,而每個請求被路由到一個隨機的伺服器,這種情況是很有可能的)。第一個查詢返回最近由使用者 1234 新增的評論,但是第二個查詢不返回任何東西,因為滯後的從庫還沒有拉取寫入內容。在效果上相比第一個查詢,第二個查詢是在更早的時間點來觀察系統。如果第一個查詢沒有返回任何內容,那問題並不大,因為使用者 2345 可能不知道使用者 1234 最近添加了評論。但如果使用者 2345 先看見使用者 1234 的評論,然後又看到它消失,那麼對於使用者 2345,就很讓人頭大了。
|
||||
如果使用者從不同從庫進行多次讀取,就可能發生這種情況。例如,[圖 5-4](../img/fig5-4.png) 顯示了使用者 2345 兩次進行相同的查詢,首先查詢了一個延遲很小的從庫,然後是一個延遲較大的從庫(如果使用者重新整理網頁時每個請求都被路由到一個隨機的伺服器,這種情況就很有可能發生)。第一個查詢返回了最近由使用者 1234 新增的評論,但是第二個查詢不返回任何東西,因為滯後的從庫還沒有拉取到該寫入內容。實際上可以認為第二個查詢是在比第一個查詢更早的時間點上觀察系統。如果第一個查詢沒有返回任何內容,那問題並不大,因為使用者 2345 可能不知道使用者 1234 最近添加了評論。但如果使用者 2345 先看見使用者 1234 的評論,然後又看到它消失,這就會讓人覺得非常困惑了。
|
||||
|
||||
![](../img/fig5-4.png)
|
||||
|
||||
**圖 5-4 使用者首先從新副本讀取,然後從舊副本讀取。時光倒流。為了防止這種異常,我們需要單調的讀取。**
|
||||
**圖 5-4 使用者首先從新副本讀取,然後從舊副本讀取。時間看上去回退了。為了防止這種異常,我們需要單調的讀取。**
|
||||
|
||||
**單調讀(Monotonic reads)**【23】保證這種異常不會發生。這是一個比 **強一致性(strong consistency)** 更弱,但比 **最終一致性(eventual consistency)** 更強的保證。當讀取資料時,你可能會看到一箇舊值;單調讀取僅意味著如果一個使用者順序地進行多次讀取,則他們不會看到時間後退,即,如果先前讀取到較新的資料,後續讀取不會得到更舊的資料。
|
||||
**單調讀(monotonic reads)**【23】可以保證這種異常不會發生。這是一個比 **強一致性(strong consistency)** 更弱,但比 **最終一致性(eventual consistency)** 更強的保證。當讀取資料時,你可能會看到一箇舊值;單調讀僅意味著如果一個使用者順序地進行多次讀取,則他們不會看到時間回退,也就是說,如果已經讀取到較新的資料,後續的讀取不會得到更舊的資料。
|
||||
|
||||
實現單調讀取的一種方式是確保每個使用者總是從同一個副本進行讀取(不同的使用者可以從不同的副本讀取)。例如,可以基於使用者 ID 的雜湊來選擇副本,而不是隨機選擇副本。但是,如果該副本失敗,使用者的查詢將需要重新路由到另一個副本。
|
||||
實現單調讀的一種方式是確保每個使用者總是從同一個副本進行讀取(不同的使用者可以從不同的副本讀取)。例如,可以基於使用者 ID 的雜湊來選擇副本,而不是隨機選擇副本。但是,如果該副本出現故障,使用者的查詢將需要重新路由到另一個副本。
|
||||
|
||||
|
||||
### 一致字首讀
|
||||
|
||||
第三個複製延遲例子違反了因果律。 想象一下 Poons 先生和 Cake 夫人之間的以下簡短對話:
|
||||
第三個複製延遲異常的例子違反了因果律。 想象一下 Poons 先生和 Cake 夫人之間的以下簡短對話:
|
||||
|
||||
*Mr. Poons*
|
||||
> Mrs. Cake,你能看到多遠的未來?
|
||||
@ -255,7 +255,7 @@
|
||||
|
||||
這兩句話之間有因果關係:Cake 夫人聽到了 Poons 先生的問題並回答了這個問題。
|
||||
|
||||
現在,想象第三個人正在透過從庫來聽這個對話。 Cake 夫人說的內容是從一個延遲很低的從庫讀取的,但 Poons 先生所說的內容,從庫的延遲要大的多(見 [圖 5-5](../img/fig5-5.png))。 於是,這個觀察者會聽到以下內容:
|
||||
現在,想象第三個人正在透過從庫來聽這個對話。 Cake 夫人說的內容是從一個延遲很低的從庫讀取的,但 Poons 先生所說的內容,從庫的延遲要大的多(見 [圖 5-5](../img/fig5-5.png))。於是,這個觀察者會聽到以下內容:
|
||||
|
||||
*Mrs. Cake*
|
||||
> 通常約十秒鐘,Mr. Poons.
|
||||
@ -263,28 +263,27 @@
|
||||
*Mr. Poons*
|
||||
> Mrs. Cake,你能看到多遠的未來?
|
||||
|
||||
對於觀察者來說,看起來好像 Cake 夫人在 Poons 先生提問前就回答了這個問題。
|
||||
這種超能力讓人印象深刻,但也會把人搞糊塗。【25】。
|
||||
對於觀察者來說,看起來好像 Cake 夫人在 Poons 先生提問前就回答了這個問題。這種超能力讓人印象深刻,但也會把人搞糊塗。【25】。
|
||||
|
||||
![](../img/fig5-5.png)
|
||||
|
||||
**圖 5-5 如果某些分割槽的複製速度慢於其他分割槽,那麼觀察者在看到問題之前可能會看到答案。**
|
||||
**圖 5-5 如果某些分割槽的複製速度慢於其他分割槽,那麼觀察者可能會在看到問題之前先看到答案。**
|
||||
|
||||
防止這種異常,需要另一種型別的保證:**一致字首讀(consistent prefix reads)**【23】。 這個保證說:如果一系列寫入按某個順序發生,那麼任何人讀取這些寫入時,也會看見它們以同樣的順序出現。
|
||||
要防止這種異常,需要另一種型別的保證:**一致字首讀(consistent prefix reads)**【23】。這個保證的意思是說:如果一系列寫入按某個順序發生,那麼任何人讀取這些寫入時,也會看見它們以同樣的順序出現。
|
||||
|
||||
這是 **分割槽(partitioned)** 或 **分片(sharded)** 資料庫中的一個特殊問題,將在 [第六章](ch6.md) 中討論。如果資料庫總是以相同的順序應用寫入,則讀取總是會看到一致的字首,所以這種異常不會發生。但是在許多分散式資料庫中,不同的分割槽獨立執行,因此不存在 **全域性寫入順序**:當用戶從資料庫中讀取資料時,可能會看到資料庫的某些部分處於較舊的狀態,而某些處於較新的狀態。
|
||||
這是 **分割槽(partitioned)** 或 **分片(sharded)** 資料庫中的一個特殊問題,我們將在 [第六章](ch6.md) 中討論分割槽資料庫。如果資料庫總是以相同的順序應用寫入,而讀取總是看到一致的字首,那麼這種異常不會發生。但是在許多分散式資料庫中,不同的分割槽獨立執行,因此不存在 **全域性的寫入順序**:當用戶從資料庫中讀取資料時,可能會看到資料庫的某些部分處於較舊的狀態,而某些則處於較新的狀態。
|
||||
|
||||
一種解決方案是,確保任何因果相關的寫入都寫入相同的分割槽。對於某些無法高效完成這種操作的應用,還有一些顯式跟蹤因果依賴關係的演算法,本書將在 “[“此前發生” 的關係和併發](#“此前發生”的關係和併發)” 一節中返回這個主題。
|
||||
一種解決方案是,確保任何因果相關的寫入都寫入相同的分割槽,但在一些應用中可能無法高效地完成這種操作。還有一些顯式跟蹤因果依賴關係的演算法,我們將在 “[“此前發生” 的關係和併發](#“此前發生”的關係和併發)” 一節中回到這個話題。
|
||||
|
||||
### 複製延遲的解決方案
|
||||
|
||||
在使用最終一致的系統時,如果複製延遲增加到幾分鐘甚至幾小時,則應該考慮應用程式的行為。如果答案是 “沒問題”,那很好。但如果結果對於使用者來說是不好體驗,那麼設計系統來提供更強的保證是很重要的,例如 **寫後讀**。明明是非同步複製卻假設複製是同步的,這是很多麻煩的根源。
|
||||
在使用最終一致的系統時,如果複製延遲增加到幾分鐘甚至幾小時,則應該考慮應用程式的行為。如果答案是 “沒問題”,那很好。但如果結果對於使用者來說是不好的體驗,那麼設計系統來提供更強的保證(例如 **寫後讀**)是很重要的。明明是非同步複製卻假設複製是同步的,這是很多麻煩的根源。
|
||||
|
||||
如前所述,應用程式可以提供比底層資料庫更強有力的保證,例如透過主庫進行某種讀取。但在應用程式程式碼中處理這些問題是複雜的,容易出錯。
|
||||
|
||||
如果應用程式開發人員不必擔心微妙的複製問題,並可以信賴他們的資料庫 “做了正確的事情”,那該多好呀。這就是 **事務(transaction)** 存在的原因:**資料庫透過事務提供強大的保證**,所以應用程式可以更加簡單。
|
||||
|
||||
單節點事務已經存在了很長時間。然而在走向分散式(複製和分割槽)資料庫時,許多系統放棄了事務。聲稱事務在效能和可用性上的代價太高,並斷言在可伸縮系統中最終一致性是不可避免的。這個敘述有一些道理,但過於簡單了,本書其餘部分將提出更為細緻的觀點。第七章和第九章將回到事務的話題,並討論一些替代機制。
|
||||
單節點事務已經存在了很長時間。然而在走向分散式(複製和分割槽)資料庫時,許多系統放棄了事務,聲稱事務在效能和可用性上的代價太高,並斷言在可伸縮系統中最終一致性是不可避免的。這個敘述有一些道理,但過於簡單了,本書其餘部分將提出更為細緻的觀點。我們將在 [第七章](ch7.md) 和 [第九章](ch9.md) 回到事務的話題,並將在 [第三部分](part-iii.md) 討論一些替代機制。
|
||||
|
||||
|
||||
## 多主複製
|
||||
|
Loading…
Reference in New Issue
Block a user