一致性高于可用性:rqlite如何处理CAP定理

rqlite是一个轻量级的、用户友好的、开源的分布式关系数据库。它是用Go编写的,使用SQLite作为存储引擎。

当涉及到分布式系统时,CAP定理是一个基本概念。分布式数据库不可能同时提供一致性、可用性和容错性。面临的挑战是,在网络分区面前,数据库只能是可用的或一致的,但不能两者兼而有之。

让我们来看看CAP定理,看看rqlite如何适应这个基本的权衡。


了解一致性、可用性和分区容差
一致性(C):一致的系统确保分布式集群中的所有节点同时具有相同的数据。这意味着任何读请求都将返回最近写入的数据。
可用性(A):可用的系统确保每个请求都收到响应,而不管网络问题如何。即使某些节点无法访问,系统也会继续运行,但不能保证数据是最新的。
分区容忍(P):即使网络故障将系统划分为孤立的节点组,分区容忍系统也会继续运行。
当出现网络分区时,必须做出选择。您是通过不响应分区“坏”端的请求来优先考虑一致性,还是通过继续服务请求来优先考虑可用性,即使这意味着可能服务陈旧的数据?这是CP和AP之间的核心权衡。

CP与AP系统
CP(Consistency-Partition Tolerant)系统优先考虑一致性。如果出现网络分区,系统将阻止群集少数侧的写入,以防止数据不一致。这确保了写入的任何数据都是一致的,并且当分区被解析时,系统将不会发生冲突。

AP(兼容性分区容忍)系统优先考虑可用性。它继续接受分区两端的写请求,即使它有数据发散的风险。分区修复后,系统必须处理潜在的冲突数据。

rqlite的适用范围:CP系统
rqlite是一个CP系统。它建立在Raft共识协议之上,该协议本质上优先考虑一致性。如果出现网络分区,rqlite集群将仅在包含大多数节点的分区一侧保持可用。另一端将停止接受写入请求。

这种设计保证了写入多数方的任何数据在所有可用节点上保持一致。一旦解决了网络分区,少数节点将被更新,群集将恢复正常、一致的操作。这种CP方法确保了数据的正确性和完整性,使rqlite成为数据一致性是核心需求的应用程序的重要工具。

读一致性:超越CAP定理
虽然rqlite基本上是一个CP系统,但它通过其可选择的读取一致性级别(弱、可线性化、强和无),为您提供了对C和A权衡的细粒度控制。这些级别允许您平衡性能和数据正确性,并为您的应用程序选择最佳折衷。最重要的是,您甚至可以在每次读取请求的基础上选择一致性级别。

弱:很棒但不完美
弱一致性是rqlite的默认设置,通常是大多数应用程序的正确选择。对于弱一致性,接收到读请求的节点检查它是否是leader,如果是,则读取其本地SQLite数据库。如果节点不是领导者,它将透明地将请求转发给领导者,等待响应,然后返回客户端。最终结果是非常快的读取,几乎总是完全一致的。

然而,使用弱一致性,有一个非常小的时间窗口,节点可能会认为它是被丢弃后的领导者,并且已经发生了写入,可能导致陈旧的读取。虽然这种风险在稳定的集群中是最小的,但这是一个重要的考虑因素。有趣的是,这是rqlite最早修复的问题之一。

Strong:一个测试工具,不用于生产
强一致性通过Raft日志本身发送读请求,提供最高级别的数据更新。这可确保在执行读取之前应用所有已提交的条目。虽然这消除了对数据陈旧性的任何怀疑,但它带来了显著的性能损失,使其通常不适合生产使用。它主要用于某些测试场景,并且它的使用是rqlite测试套件中的一个关键模式。

可线性化:两全其美
对于最新数据至关重要但strong强一致性的性能成本太高的应用程序,线性化读取是答案。此方法通过让leader首先与follower仲裁确认其状态,确保返回的数据绝对是最新的。这提供了与strong读取相同的强一致性保证,但延迟显著减少,使其成为性能和数据正确性的理想解决方案。

无一致性:最高速度,(几乎)零保证
在没有一致性的情况下,接收读请求的节点只是查询其本地SQLite数据库,而不进行任何Leadership或集群连接检查。这是最快的读取速度,但无法保证数据的新鲜度。该节点可以与集群的其余部分完全断开连接,但仍然为请求提供服务。此级别在与只读节点一起使用时特别有效,您可以将其与freshness参数联合收割机组合以添加一层安全性,确保节点不会与leader失去联系太久。