数据库中的错误, 最终一致性和CAP理论
Posted 数据库技术汇
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数据库中的错误, 最终一致性和CAP理论相关的知识,希望对你有一定的参考价值。
最近,大家对CAP定理产生了极大的兴趣,CAP定理主要适用于跨多个站点数据库系统(DBMS)。简而言之,这个理论说一个DBMS系统和下面三个有趣的特性有关:
C: Consistency. 目标是允许跨越多个站点的事务具备大家习惯的all-or-nothing语义,因为这个语义是被大多数传统商业数据库系统广泛支持的。除此之外,当一个系统支持副本时,大家期望副本始终处于一个一致性的状态。
A: Availability. 目标是支持一个DBMS系统始终可用,换句话说,当故障发生的时候,系统依然可以继续工作,必要的时候切换到某个副本去。20多年前,Tandem Computers推广了这一功能。
P: Partition-tolerance. 如果遭遇网络分区把这些处理节点分成了2组,他们之间不能项目通讯。这个特性的目标允许工作继续在这两个分组中进行。
CAP理论是一个悲观的结论:在错误出现的时候,系统不能同时达成上述3个目标,因此你必须考虑选择一个而丢弃另外一个。
在NoSQL社区中,这个定理被用作放弃一致性的理由。 由于大多数NoSQL系统通常不允许跨越节点边界的事务,因此一致性仅适用于副本。 因此,CAP定理用于证明放弃一致的副本,用“最终一致性”替换这个目标。通过这种放松的概念,人们只能保证所有副本最终会收敛到相同的状态,即当网络连接重新建立并且经历了足够的后续时间来用于复制清理。 放弃C的理由是可以保留A和P.
这篇博客文章的目的是断言上述分析是可疑的,并且从错误中恢复还需要考虑更多维度。 我们假设使用LAN网络将本地处理和存储节点集合的典型硬件模型组装到一个集群中。 多个集群间使用WAN网络连接在一起。
让我们首先讨论导致数据库错误的原因。 以下至少是部分列表:
应用错误。 应用程序执行了一个或多个不正确的更新。通常,此后几分钟到几小时内未发现这种情况。 必须将数据库备份到违规事务之前的某个点,然后重新执行后续活动。
可重复的DBMS错误。 DBMS在一个处理节点崩溃。 在另外一个副本处理节点上执行相同的事务将导致备份崩溃。 这些错误被称为玻尔漏洞。
不可重复的DBMS错误。 数据库崩溃,但副本可能没问题。 这些通常是由处理异步操作的奇怪corner case引起的,并且被称为Heisen bugs。
操作系统错误,某个节点的OS崩溃,产生了“蓝屏”错误。
本地集群遭遇硬件错误,包含内存错误,磁盘错误等。通常,这些会导致OS或DBMS的“无理由停止”。 然而,有时这些失败表现为Heisenbugs。
本地集群发生网络分区,节点不能相互通讯。
灾难,本地集群遭遇洪水、地震等,整个本地集群都毁灭了。
WAN连接故障,集群间的不能相互通讯。
首先,请注意错误1和2将导致任何高可用性方案出现问题。 在这两种情况下,没有办法继续前进; 即无法实现可用性。 而且,副本的一致性毫无意义; 当前的DBMS状态完全错误。 如果在确保已由另一个WAN连接的群集接收到该事务之后提交本地事务,才能恢复错误7。 很少有应用程序构建者愿意接受这种延迟。 因此,无法保证最终的一致性,因为如果在事务成功转发到其他地方之前在本地集群中发生灾难,则事务可能完全丢失。 换句话说,应用程序设计者选择在发生罕见事件(例如灾难)时遭受数据丢失,因为避免它的性能损失太高。
因此,错误1,2和7是CAP定理根本不适用的情况的示例。 在这些情况下,任何真实系统都必须准备好处理恢复。 CAP定理不能用于指导。
现在让我们转向CAP定理可能适用的情况。 考虑LAN分区的错误6。 根据我的经验,这是非常罕见的,特别是如果一个复制LAN(如Tandem所做的那样)。 考虑到本地故障(3,4,5和6),绝大多数会导致单个节点发生故障,这是网络分区的简并情况,很容易通过大量算法生存。 因此,在我看来放弃P而不是牺牲C会好得多。(在LAN环境中,我认为应该选择CA而不是AP)。 较新的SQL OLTP系统(例如,VoltDB和NimbusDB)似乎就是这样做的。
接下来,考虑错误8,即WAN网络中的分区。 今天的WAN中有足够的冗余设计,分区很少见。 我的经验是更可能发生本地故障和应用程序错误。 此外,最可能的WAN故障是将网络的一小部分与大多数网络分开。 在这种情况下,大多数人可以继续使用简单的算法,只有一小部分必须阻止。 因此,在相当罕见的情况下,一直放弃一致性以换取一小部分节点的可用性似乎是不明智的。
最后,考虑操作系统,DBMS或网络管理器的减速。 这可能是由于负载偏差,缓冲池问题或无数其他原因造成的。 在这些情况下,唯一可以做出的决定是“破坏”有问题的组件; 即,将慢响应时间变为前面提到的一种情况的失败。 在我看来,这几乎总是一件坏事。 一个人只是简单地将问题推到了其他地方,并增加了一个明显的处理负载来处理后续的恢复。 而且,这种问题总是在重负荷下发生 - 通过减去硬件的方向来处理错误的方向。
显然,人们应该编写可以处理负载高峰而不会失败的软件; 例如,通过减少负载或以降级模式操作。 此外,良好的监控软件将有助于尽早发现此类问题,因为真正的解决方案是增加更多容量。 最后,能够快速吸收额外资源的自我重新配置软件显然是一个好主意。
总而言之,不应该如此快地抛弃C,因为存在CAP不适用的真实错误情况,并且在许多其他情况下抛弃C似乎也是一个不好的权衡。
以上是关于数据库中的错误, 最终一致性和CAP理论的主要内容,如果未能解决你的问题,请参考以下文章