原则上 , ACID属性(原子性、一致性、隔离性、持久性)中定义的事务系统的一致性属性是一种不同类型的一致性保证 。在ACID中 , 一致性指的是保证事务完成时数据库处于一致状态;例如 , 当从一个账户向另一个账户转账时 , 两个账户中的总金额不应改变 。在基于acid的系统中 , 这种一致性通常是编写事务的开发人员的责任 , 但是数据库管理完整性约束可以帮助实现这种一致性 。
一致性:客户端和服务器有两种观察一致性的方法 。一个是从开发人员/客户的角度:他们如何观察数据更新 。第二种方法来自服务器端:更新如何流经系统 , 以及系统对更新可以提供哪些保证 。
客户端一致性客户端有以下组件:
- 一个存储系统 。目前 , 我们将把它看作一个黑盒 , 但是我们应该假设它是一个大规模的、高度分布式的东西 , 并且构建它是为了保证持久性和可用性 。
- 进程a 。这是一个读写存储系统的进程 。
- 进程B和进程c是独立于进程A的两个进程 , 它们对存储系统进行读写 。它们是同一个进程中的进程还是线程无关紧要;重要的是 , 他们是独立的 , 需要交流来共享信息 。
- 客户端一致性与观察者(在本例中是进程A、B或C)如何以及何时看到存储系统中数据对象的更新有关 。在下面演示不同类型一致性的例子中 , 进程A对数据对象进行了更新:
- 强烈的一致性 。更新完成后 , 任何后续访问(A、B或C)都将返回更新后的值 。
- 弱一致性 。系统不保证后续访问将返回更新后的值 。在返回值之前 , 需要满足许多条件 。从更新到保证任何观察者都能看到更新值这段时间被称为不一致窗口 。
- 最终一致性 。这是弱一致性的一种特殊形式;存储系统保证 , 如果没有对对象进行新的更新 , 最终所有访问都将返回最后更新的值 。如果没有发生故障 , 可以根据通信延迟、系统负载和复制方案中涉及的副本数量等因素确定不一致窗口的最大大小 。实现最终一致性的最普遍的系统是DNS(域名系统) 。对名称的更新根据配置的模式进行分发 , 并与时间控制的缓存相结合;最终 , 所有客户端都将看到更新 。
- 因果一致性 。如果进程A通知进程B它已经更新了一个数据项 , 那么进程B的后续访问将返回更新后的值 , 并且保证一次写操作将取代之前的写操作 。进程C的访问与进程A没有因果关系 , 遵循通常的最终一致性规则 。
- “读己之所写”一致性 。这是一个重要的模型 , 流程A在更新了数据项之后 , 总是访问更新后的值 , 永远不会看到旧的值 。这是因果一致性模型的一个特例 。
- 会话一致性 。这是前一个模型的实际版本 , 其中进程在会话上下文中访问存储系统 。只要会话存在 , 系统就保证“读己之所写”一致性 。如果会话因为某种失败场景而终止 , 则需要创建一个新的会话 , 并且保证会话不会重叠 。
- 单调读一致性 。如果进程已经看到了该对象的特定值 , 那么任何后续访问都不会返回任何以前的值 。
- 单调写一致性 。在这种情况下 , 系统保证序列化同一个进程的写操作 。不能保证这种级别一致性的系统是出了名的难以编程 。
正如您可以从这些变化中看到的 , 相当多的不同场景是可能的 。能否处理这些后果取决于特定的应用程序 。
最终一致性并不是极端分布式系统的神秘属性 。许多提供主备份可靠性的现代rdbms(关系数据库管理系统)同时以同步和异步模式实现它们的复制技术 。在同步模式下 , 副本更新是事务的一部分 。在异步模式下 , 更新以延迟的方式到达备份 , 通常通过日志传送 。在后一种模式中 , 如果主备份在发送日志之前发生故障 , 从提升后的备份读取数据将产生旧的、不一致的值 。另外 , 为了支持更好的可伸缩读性能 , rdbms已经开始提供从备份中读取数据的能力 , 这是提供最终一致性保证的经典案例 , 在这种情况下 , 不一致性窗口取决于日志传送的周期 。
推荐阅读
- 漫谈分层架构:为什么要进行架构分层?
- 图解Raft:应该是最容易理解的分布式一致性算法
- 探索3种顶级「集成框架」Apache、Spring和Mule
- 分布式系统核心问题简介
- 从 Spring Boot 程序启动深入理解 Netty 异步架构原理
- 什么是链路追踪?分布式系统如何实现链路追踪?
- 双活无共享数据库架构
- Android Jetpack 架构浅析
- 你的平台有这四大技术架构群吗?
- 分布式系统全局唯一ID的几种实现方式