You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

95 lines
9.2 KiB
Markdown

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

# 12 | Quorum NWR算法想要灵活地自定义一致性没问题
你好,我是韩健。
不知道你在工作中有没有遇到这样的事儿你开发实现了一套AP型的分布式系统我在[04讲](https://time.geekbang.org/column/article/200717)提到了AP型系统的特点你可以回顾一下实现了最终一致性。业务也接入了运行正常一起看起来都那么美好。
可是,突然有同事说,我们要拉这几个业务的数据做实时分析,希望数据写入成功后,就能立即读取到新数据,也就是要实现强一致性([Werner Vogels提出的客户端侧一致性模型](https://www.allthingsdistributed.com/2008/12/eventually_consistent.html),不是指线性一致性),数据更改后,要保证用户能立即查询到。这时你该怎么办呢?首先你要明确最终一致性和强一致性有什么区别。
* 强一致性能保证写操作完成后,任何后续访问都能读到更新后的值;
* 最终一致性只能保证如果对某个对象没有新的写操作了,最终所有后续访问都能读到相同的最近更新的值。也就是说,写操作完成后,后续访问可能会读到旧数据。
其实在我看来为了一个临时的需求我们重新开发一套系统或者迁移数据到新系统肯定是不合适的。因为工作量比较大而且耗时也长而我建议你通过Quorum NWR解决这个问题。
也就是说在原有系统上开发实现一个新功能就可以满足业务同学的需求了。因为通过Quorum NWR你可以自定义一致性级别通过临时调整写入或者查询的方式当W + R > N时就可以实现强一致性了。
其实在AP型分布式系统中比如Dynamo、Cassandra、InfluxDB企业版的DATA节点集群Quorum NWR是通常都会实现的一个功能很常用。对你来说掌握Quorum NWR不仅是掌握一种常用的实现一致性的方法更重要的是后续用户可以根据业务的特点灵活地指定一致性级别。
为了帮你掌握Quorum NWR除了带你了解它的原理外我还会以InfluxDB企业版的实现为例带你看一下它在实际场景中的实现这样你可以在理解原理的基础上掌握Quorum NWR的实战技巧。
首先你需要了解Quorum NWR中的三个要素N、W、R。因为它们是Quorum NWR的核心内容我们就是通过组合这三个要素实现自定义一致性级别的。
## Quorum NWR的三要素
N表示副本数又叫做复制因子Replication Factor。也就是说N表示集群中同一份数据有多少个副本就像下图的样子
![](https://static001.geekbang.org/resource/image/8a/bb/8a582c39e4795429a986955a6a1c9ebb.jpg "图1")
从图中你可以看到在这个三节点的集群中DATA-1有2个副本DATA-2有3个副本DATA-3有1个副本。也就是说副本数可以不等于节点数不同的数据可以有不同的副本数。
需要你注意的是在实现Quorum NWR的时候你需要实现自定义副本的功能。也就是说用户可以自定义指定数据的副本数比如用户可以指定DATA-1具有2个副本DATA-2具有3个副本就像图中的样子。
当我们指定了副本后就可以对副本数据进行读写操作了。那么这么多副本你要如何执行读写操作呢先来看一看写操作也就是W。
W又称写一致性级别Write Consistency Level表示成功完成W个副本更新才完成写操作
![](https://static001.geekbang.org/resource/image/1b/7b/1b175952d815d40de45c0d0aba99ac7b.jpg "图2")
从图中你可以看到DATA-2的写副本数为2也就说对DATA-2执行写操作时完成了2个副本的更新比如节点A、C才完成写操作。
那么有的同学会问了DATA-2有3个数据副本完成了2副本的更新就完成了写操作那么如何实现强一致性呢如果读到了第三个数据副本比如节点B不就可能无法读到更新后的值了吗别急我讲完如何执行读操作后你就明白了。
R又称读一致性级别Read Consistency Level表示读取一个数据对象时需要读R个副本。你可以这么理解读取指定数据时要读R副本然后返回R个副本中最新的那份数据
![](https://static001.geekbang.org/resource/image/5b/5c/5b634d40032cceeffcbc66c3e177735c.jpg "图3")
从图中你可以看到DATA-2的读副本数为2。也就是说客户端读取DATA-2的数据时需要读取2个副本中的数据然后返回最新的那份数据。
这里需要你注意的是无论客户端如何执行读操作哪怕它访问的是写操作未强制更新副本数据的节点比如节点B但因为W(2) + R(2) > N(3)也就是说访问节点B执行读操作时因为要读2份数据副本所以除了节点B上的DATA-2还会读取节点A或节点C上的DATA-2就像上图的样子比如节点C上的DATA-2而节点A和节点C的DATA-2数据副本是强制更新成功的。这个时候返回给客户端肯定是最新的那份数据。
你看通过设置R为2即使读到前面问题中的第三份副本数据比如节点B也能返回更新后的那份数据实现强一致性了。
除此之外关于NWR需要你注意的是N、W、R值的不同组合会产生不同的一致性效果具体来说有这么两种效果
* 当W + R > N的时候对于客户端来讲整个系统能保证强一致性一定能返回更新后的那份数据。
* 当W + R <= N的时候对于客户端来讲整个系统只能保证最终一致性可能会返回旧数据。
你可以看到Quorum NWR的原理并不复杂也相对比较容易理解但在这里我想强调一下掌握它的关键在于如何根据不同的场景特点灵活地实现Quorum NWR所以接下来我带你具体问题具体分析以InfluxDB企业版为例讲解一下。
## 如何实现Quorum NWR
在InfluxDB企业版中可以在创建保留策略时设置指定数据库Database对应的副本数具体的命令就像下面的样子
* create retention policy “rp\_one\_day” on “telegraf” duration 1d replication 3
通过replication参数指定了数据库telegraf对应的副本数为3。
需要你注意的在InfluxDB企业版中副本数不能超过节点数据。你可以这么理解多副本的意义在于冗余备份如果副本数超过节点数就意味着在一个节点上会存在多个副本那么这时冗余备份的意义就不大了。比如机器故障时节点上的多个副本是同时被影响的。
InfluxDB企业版支持“any、one、quorum、all”4种写一致性级别具体的含义是这样的。
* any任何一个节点写入成功后或者接收节点已将数据写入Hinted-handoff缓存也就是写其他节点失败后本地节点上缓存写失败数据的队列就会返回成功给客户端。
* one任何一个节点写入成功后立即返回成功给客户端不包括成功写入到Hinted-handoff缓存。
* quorum当大多数节点写入成功后就会返回成功给客户端。此选项仅在副本数大于2时才有意义否则等效于all。
* all仅在所有节点都写入成功后返回成功。
我想强调一下对时序数据库而言读操作常会拉取大量数据查询性能是挑战是必须要考虑优化的因此在InfluxDB企业版中不支持读一致性级别只支持写一致性级别。另外我们可以通过设置写一致性级别为all来实现强一致性。
你看如果我们像InfluxDB企业版这样实现了Quorum NWR那么在业务临时需要实现强一致性时就可以通过设置写一致性级别为all来实现了。
## 内容小结
以上就是本节课的全部内容了本节课我主要带你了解了Quorum NWR的原理、InfluxDB企业版的Quorum NWR实现。我希望你明确这样几个重点。
1. 一般而言,不推荐副本数超过当前的节点数,因为当副本数据超过节点数时,就会出现同一个节点存在多个副本的情况。当这个节点故障时,上面的多个副本就都受到影响了。
2. 当W + R > N时可以实现强一致性。另外如何设置N、W、R值取决于我们想优化哪方面的性能。比如N决定了副本的冗余备份能力如果设置W = N读性能比较好如果设置R = N写性能比较好如果设置W = (N + 1) / 2、R = (N + 1) / 2容错能力比较好能容忍少数节点也就是(N - 1) / 2的故障。
最后我想说的是Quorum NWR是非常实用的一个算法能有效弥补AP型系统缺乏强一致性的痛点给业务提供了按需选择一致性级别的灵活度建议你的开发实现AP型系统时也实现Quorum NWR。
## 课堂思考
我提到实现Quorum NWR时需要实现自定义副本的能力那么一般设置几个副本就可以了为什么呢欢迎在留言区分享你的看法与我一同讨论。
最后,感谢你的阅读,如果这篇文章让你有所收获,也欢迎你将它分享给更多的朋友。