「分布式架构」“一切都是分布式”说最终一致性( 二 )


原则上 , ACID属性(原子性、一致性、隔离性、持久性)中定义的事务系统的一致性属性是一种不同类型的一致性保证 。在ACID中 , 一致性指的是保证事务完成时数据库处于一致状态;例如 , 当从一个账户向另一个账户转账时 , 两个账户中的总金额不应改变 。在基于acid的系统中 , 这种一致性通常是编写事务的开发人员的责任 , 但是数据库管理完整性约束可以帮助实现这种一致性 。
一致性:客户端和服务器有两种观察一致性的方法 。一个是从开发人员/客户的角度:他们如何观察数据更新 。第二种方法来自服务器端:更新如何流经系统 , 以及系统对更新可以提供哪些保证 。
客户端一致性客户端有以下组件:

  • 一个存储系统 。目前 , 我们将把它看作一个黑盒 , 但是我们应该假设它是一个大规模的、高度分布式的东西 , 并且构建它是为了保证持久性和可用性 。
  • 进程a 。这是一个读写存储系统的进程 。
  • 进程B和进程c是独立于进程A的两个进程 , 它们对存储系统进行读写 。它们是同一个进程中的进程还是线程无关紧要;重要的是 , 他们是独立的 , 需要交流来共享信息 。
  • 客户端一致性与观察者(在本例中是进程A、B或C)如何以及何时看到存储系统中数据对象的更新有关 。在下面演示不同类型一致性的例子中 , 进程A对数据对象进行了更新:
  • 强烈的一致性 。更新完成后 , 任何后续访问(A、B或C)都将返回更新后的值 。
  • 弱一致性 。系统不保证后续访问将返回更新后的值 。在返回值之前 , 需要满足许多条件 。从更新到保证任何观察者都能看到更新值这段时间被称为不一致窗口 。
  • 最终一致性 。这是弱一致性的一种特殊形式;存储系统保证 , 如果没有对对象进行新的更新 , 最终所有访问都将返回最后更新的值 。如果没有发生故障 , 可以根据通信延迟、系统负载和复制方案中涉及的副本数量等因素确定不一致窗口的最大大小 。实现最终一致性的最普遍的系统是DNS(域名系统) 。对名称的更新根据配置的模式进行分发 , 并与时间控制的缓存相结合;最终 , 所有客户端都将看到更新 。
最终一致性模型有许多重要的变化需要考虑:
  • 因果一致性 。如果进程A通知进程B它已经更新了一个数据项 , 那么进程B的后续访问将返回更新后的值 , 并且保证一次写操作将取代之前的写操作 。进程C的访问与进程A没有因果关系 , 遵循通常的最终一致性规则 。
  • “读己之所写”一致性 。这是一个重要的模型 , 流程A在更新了数据项之后 , 总是访问更新后的值 , 永远不会看到旧的值 。这是因果一致性模型的一个特例 。
  • 会话一致性 。这是前一个模型的实际版本 , 其中进程在会话上下文中访问存储系统 。只要会话存在 , 系统就保证“读己之所写”一致性 。如果会话因为某种失败场景而终止 , 则需要创建一个新的会话 , 并且保证会话不会重叠 。
  • 单调读一致性 。如果进程已经看到了该对象的特定值 , 那么任何后续访问都不会返回任何以前的值 。
  • 单调写一致性 。在这种情况下 , 系统保证序列化同一个进程的写操作 。不能保证这种级别一致性的系统是出了名的难以编程 。
这些属性中有许多是可以组合的 。例如 , 可以结合会话级别一致性获得单调的读取 。从实际的角度来看 , 这两个属性(单调读取和read-your-write)在最终的一致性系统中是最理想的 , 但并不总是必需的 。这两个属性使开发人员更容易构建应用程序 , 同时允许存储系统放松一致性并提供高可用性 。
正如您可以从这些变化中看到的 , 相当多的不同场景是可能的 。能否处理这些后果取决于特定的应用程序 。
最终一致性并不是极端分布式系统的神秘属性 。许多提供主备份可靠性的现代rdbms(关系数据库管理系统)同时以同步和异步模式实现它们的复制技术 。在同步模式下 , 副本更新是事务的一部分 。在异步模式下 , 更新以延迟的方式到达备份 , 通常通过日志传送 。在后一种模式中 , 如果主备份在发送日志之前发生故障 , 从提升后的备份读取数据将产生旧的、不一致的值 。另外 , 为了支持更好的可伸缩读性能 , rdbms已经开始提供从备份中读取数据的能力 , 这是提供最终一致性保证的经典案例 , 在这种情况下 , 不一致性窗口取决于日志传送的周期 。


推荐阅读