Merge pull request #93 from kemingy/fix-ch5

ch5: fix markdown and some typos
This commit is contained in:
Feng Ruohang 2020-12-01 10:42:40 +08:00 committed by GitHub
commit e663d950be
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

10
ch5.md
View File

@ -242,7 +242,7 @@
**图5-4 用户首先从新副本读取,然后从旧副本读取。时光倒流。为了防止这种异常,我们需要单调的读取。**
**单调读Monotonic reads**【23】是这种异常不会发生的保证。这是一个比**强一致性strong consistency**更弱,但比**最终一致性eventually consistency**更强的保证。当读取数据时,您可能会看到一个旧值;单调读取仅意味着如果一个用户顺序地进行多次读取,则他们不会看到时间后退,即,如果先前读取到较新的数据,后续读取不会得到更旧的数据。
**单调读Monotonic reads**【23】保证这种异常不会发生。这是一个比 **强一致性strong consistency** 更弱,但比 **最终一致性eventually consistency** 更强的保证。当读取数据时,您可能会看到一个旧值;单调读取仅意味着如果一个用户顺序地进行多次读取,则他们不会看到时间后退,即,如果先前读取到较新的数据,后续读取不会得到更旧的数据。
实现单调读取的一种方式是确保每个用户总是从同一个副本进行读取不同的用户可以从不同的副本读取。例如可以基于用户ID的散列来选择副本而不是随机选择副本。但是如果该副本失败用户的查询将需要重新路由到另一个副本。
@ -447,7 +447,7 @@
**图5-8 三个可以设置多领导者复制的示例拓扑。**
最普遍的拓扑是全部到全部([图5-8 [c]]()其中每个领导者将其写入每个其他领导。但是也会使用更多受限制的拓扑例如默认情况下MySQL仅支持**环形拓扑circular topology**【34】其中每个节点接收来自一个节点的写入并将这些写入加上自己的任何写入转发给另一个节点。另一种流行的拓扑结构具有星形的形状[^v]。个指定的根节点将写入转发给所有其他节点。星型拓扑可以推广到树。
最普遍的拓扑是全部到全部([图5-8 [c]]()其中每个领导者将其写入每个其他领导。但是也会使用更多受限制的拓扑例如默认情况下MySQL仅支持**环形拓扑circular topology**【34】其中每个节点接收来自一个节点的写入并将这些写入加上自己的任何写入转发给另一个节点。另一种流行的拓扑结构具有星形的形状[^v]。个指定的根节点将写入转发给所有其他节点。星型拓扑可以推广到树。
[^v]: 不要与星型模式混淆(请参阅“[分析模式:星型还是雪花](ch2.md#分析模式:星型还是雪花)”),其中描述了数据模型的结构,而不是节点之间的通信拓扑。
@ -538,7 +538,7 @@
**图5-11 如果$w + r > n$读取r个副本至少有一个r副本必然包含了最近的成功写入**
如果少于所需的w或r节点可用则写入或读取将返回错误。 由于许多原因,节点可能不可用:因为由于执行操作的错误(由于磁盘已满而无法写入)导致节点关闭(崩溃,关闭电源),由于客户端和服务器之间的网络中断 节点,或任何其他原因。 我们只关心节点是否返回了成功的响应,而不需要区分不同类型的错误。
如果少于所需的w或r节点可用则写入或读取将返回错误。 由于许多原因,节点可能不可用:因为执行操作的错误(由于磁盘已满而无法写入)导致节点关闭(崩溃,关闭电源),由于客户端和服务器之间的网络中断节点,或任何其他原因。 我们只关心节点是否返回了成功的响应,而不需要区分不同类型的错误。
@ -584,7 +584,7 @@
在一个大型的群集中节点数量明显多于n个网络中断期间客户端可能连接到某些数据库节点而不是为了为特定值组成法定人数的节点们。在这种情况下数据库设计人员需要权衡一下
* 将错误返回给我们无法达到w或r节点的法定数量的所有请求是否更好
* 或者我们是否应该接受写入,然后将它们写入一些可达的节点,但不在n值通常存在的n个节点之间
* 或者我们是否应该接受写入,然后将它们写入一些可达的节点,但不在这些值通常存在的n个节点之间
后者被认为是一个**宽松的法定人数sloppy quorum**【37】写和读仍然需要w和r成功的响应但是那些可能包括不在指定的n个“主”节点中的值。比方说如果你把自己锁在房子外面你可能会敲开邻居的门问你是否可以暂时停留在沙发上。
@ -700,7 +700,7 @@
以购物车为例,一种合理的合并兄弟方法就是集合求并。在[图5-14](img/fig5-14.png)中,最后的两个兄弟是[牛奶,面粉,鸡蛋,熏肉]和[鸡蛋,牛奶,火腿]。注意牛奶和鸡蛋出现在两个,即使他们每个只写一次。合并的价值可能是像[牛奶,面粉,鸡蛋,培根,火腿],没有重复。
然而,如果你想让人们也可以从他们的手推车中**删除**东西而不是仅仅添加东西那么把兄弟求并可能不会产生正确的结果如果你合并了两个兄弟手推车并且只在其中一个兄弟值里删掉了它那么被删除的项目会重新出现在兄弟的并集中【37】。为了防止这个问题一个项目在删除时不能简单地从数据库中删除;相反,系统必须留下一个具有合适版本号的标记,以指示合并兄弟时该项目已被删除。这种删除标记被称为**墓碑tombstone**。 (我们之前在“[哈希索引”](ch3.md#哈希索引)中的日志压缩的上下文中看到了墓碑。)
然而,如果你想让人们也可以从他们的手推车中**删除**东西而不是仅仅添加东西那么把兄弟求并可能不会产生正确的结果如果你合并了两个兄弟手推车并且只在其中一个兄弟值里删掉了它那么被删除的项目会重新出现在兄弟的并集中【37】。为了防止这个问题一个项目在删除时不能简单地从数据库中删除相反,系统必须留下一个具有合适版本号的标记,以指示合并兄弟时该项目已被删除。这种删除标记被称为**墓碑tombstone**。 (我们之前在“[哈希索引”](ch3.md#哈希索引)中的日志压缩的上下文中看到了墓碑。)
因为在应用程序代码中合并兄弟是复杂且容易出错的,所以有一些数据结构被设计出来用于自动执行这种合并,如“[自动冲突解决]()”中讨论的。例如Riak的数据类型支持使用称为CRDT的数据结构家族【38,39,55】可以以合理的方式自动合并兄弟包括保留删除。