广告
返回顶部
首页 > 资讯 > 数据库 >如何验证线性一致性
  • 112
分享到

如何验证线性一致性

2024-04-02 19:04:59 112人浏览 独家记忆
摘要

线性一致性(Linearizability)是分布式系统中常见的一致性保证。那么如何验证系统是否正确地提供了线性一致性服务呢?本文希望从‘什么是线性一致性’,‘如何验证线性一致性’,问题复杂度,常见的通用算

线性一致性(Linearizability)是分布式系统中常见的一致性保证。那么如何验证系统是否正确地提供了线性一致性服务呢?本文希望从‘什么是线性一致性’,‘如何验证线性一致性’,问题复杂度,常见的通用算法,以及工程实现五个部分,直观、易懂地回答这个问题。

什么是线性一致性

MAURICE P. HERLIHY 和 JEANNETTE M. WING曾在“ Linearizability: A Correctness Condition for Concurrent Objects ” 中对线性一致性给出了形式化的定义和证明,对分布式系统来说,简单的讲就是即使发生网络分区或机器节点异常,整个集群依然能够像单点一样提供一致的服务,即依次原子地执行每一条操作。假如我们可以站在最终操作执行的视角,将整个系统看做一个整体,一个保证线性一致性的服务应该如下图所示进行服务:
如何验证线性一致性

由于每条操作是依次、原子的执行,相互之间没有重叠,为了方便理解,可以把一个操作在图上简化为一个点。如下图所示:

如何验证线性一致性

然而,实际情况中,分布式系统通常是很多节点作为一个整体对外提供服务,并在内部处理网络或节点异常,我们无法站在上帝视角看到其执行序列。同时,我们真正关心的也是其作为一个整体对外的表现,而不是其中的每个单独节点。我们所能做的是站在客户端的角度,通过读写事件的发起和结束来感知整个系统。正如站在地球上仰望星空,通过光来感知天体,看到的每一次闪烁,可能真正发生在上万年之前。因此,下图才是真正可以看到的情况:
如何验证线性一致性

上图,展示了在每个客户端看来,其请求从发起到结束的时间点。因此,我们希望通过一系列客户端的执行和返回序列来判断系统是否正确提供了线性一致性服务。

如何验证线性一致性

为了判断系统是否正确提供了线性一致性,首先在运行过程中获得一系列不同的执行历史,接着验证每组历史是否满足线性一致性,只要有一个不满足,便可以说系统不满足线性一致性。但如果没有发现不满足的历史,也不证明系统一定正确。然而,在工程中通过对大量的执行历史的验证,使得我们对自己的系统更充满信心,这就足够了。那么现在的问题转变为:如何验证一组执行历史是否满足线性一致性

通过客户端可以看到一个读写请求的发起和结束时间,而其真正在服务端的执行可能发生在开始和结束中间的任意一点。因此,验证线性一致性的关键就是找到一组依次执行的序列,如果这组执行序列存在,则可以说这组执行历史是满足线性一致的,如下图所示:
如何验证线性一致性
明显的,存在这么一组序列,因此我们说这组执行历史是符合线性一致性的。再来看一个不符合线性一致性的例子,如下图,可以看出,由于Client 3已经读到1,说明在Client 3请求结束前Client 2已经写成功,而又没有其他请求再次修改x的值,因此Client 4不应该在之后读到0。
如何验证线性一致性
实践中,通常会通过在频繁注入异常的情况下,随机生成请求序列,收集执行的发起和结束历史,并寻找合理的线性执行序列,如Jespen。

问题复杂度

直观来看,这个问题是一个排序问题,极端情况下的时间复杂度为O(N!)。事实上,Phillip B. Gibbons和Ephraim Korach在Testing Shared Memories中已经证明其是一个NP-Complete问题。虽然Gavin Lowe在Testing for Linearizability中给出了一些特殊限制下的多项式甚至是线性复杂度的算法,但在通用场景下,判定线性一致性并不是一个容易解决的问题,其搜索空间会随着执行历史的规模急速膨胀。

通用算法

虽然判定线性一致性的复杂度极高,但我们还是能够通过一些技巧,在大多数场景下,在工程可接受的时间内给出结果,这里介绍三个常见的,且一脉相承的通用算法。在此之前,先对算法面临的问题进行抽象,以下图执行历史为例,给出算法的输入和期待的输出:

如何验证线性一致性

Input: 调用历史

1,Client1: Invoke Put x=0
2,Client2: Invoke Put x=1
3,Client1: Return Put x=0
4,Client3: Invoke Get x
5,CLient4: Invoke Get x
6,Client3: Return Get 1
7,Client4: Return Get 0
8,Client2: Return Put x=1

Output: 执行序列

Client1 Put x=0
Client4 Get 0
Client2 Put x=1
Client3 Get 1
1,WG算法

请求的调用历史中,存在着一种偏序关系:Prev,如果一个请求的Return发生时间早于另一请求的Invoke,我们便称其Prev另一个请求。显而易见,这种偏序关系是一致性验证算法必须要保留的。祸兮福所倚,也正是这种对偏序关系的保留,给了算法加速的可能。WG算法的思路非常简单:从调用历史中找出没有Prev的项,将其对应的请求执行并取出,之后对剩下的调用历史重复该算法,直到没有更多的调用历史或执行结果不满足。

如上述例子中,“Client1 Put x=0” 和 “Client2 Put x=1” 由于其Invoke前没有任何请求Return,可以首先被取出。假如选择“Client1 Put x=0”,将其对应的Invoke和Return从调用历史中取出,得到新的历史:

2,Client2: Invoke Put x=1
4,Client3: Invoke Get x
5,CLient4: Invoke Get x
6,Client3: Return Get 1
7,Client4: Return Get 0
8,Client2: Return Put x=1

和一条已经序列化的请求:

Client1 Put x=0

此时可以看到剩余的历史中,每一个请求的Invoke前都没有其他请求的Return,因此都可以作为下一个取出的选择。假设这次选择Client3 Get 1,然而,明显这个时候执行Get得到应该是0,与该请求的实际执行结果返回1不同,此时,需要回退并尝试其他取出策略。可以看出WG算法其实是树的深度优先搜索,其搜索树如下图,其中每个节点标识的是本次尝试序列化的请求对应的调用历史中的Invoke序号:

由于找到一个线性序列便可以停止,因此其中虚线部分是不会被实际执行的。

2,WGL算法

WGL算法由Gavin Lowe在WG算法的基础上进行改进,其改进的方式主要是对搜索树的剪枝:通过缓存已经见过的配置,来减少重复的搜索缓存配置有两部分组成:

  • 当前已经序列化的请求

  • 当前x值

由上面的搜索过程可知,如果当前序列化的请求和当前的x值完全相同,则后续的搜索过程一定一致,因此可以略过。

3,P-compositionality算法

P-compositionality算法利用了线性一致性的Locality原理,即如果一个调用历史的所有子历史都满足线性一致性,那么这个历史本身也满足线性一致性。因此,可以将一些不相关的历史划分开来,形成多个规模更小的子历史,转而验证这些子历史的线性一致性,例如kv数据结构中对不同key的操作。上面提到了算法的计算时间随着历史规模的增加急速膨胀,P-compositionality相当于用分治的办法来降低历史规模,这种方法在可以划分子问题的场景下会非常有用。

为什么Solitaire

工程实践中,不只分布式系统,还包括需要并行访问的系统,都可能需要验证系统对外暴露的线性一致性功能。当然也有不少验证线性一致性的工具,比如大名鼎鼎的Jespen使用的Knossos,是一个Clojure版本的WGL的算法实现;Porcupine是一个Go版本的P-compositionality实现;linearizability-checker是P-compositionality算法作者自己实现的一个样例。但使用中还有几个问题没有解决:

  • 计算速度慢:由于上面提到的复杂度,一致性算法验证时间通常是相关测试中的瓶颈。尽可能的加快其计算速度,可以在相同时间内验证更多的历史,对发现系统中的潜在问题至关重要。

  • 数据模型单一:大多数的验证工具面向的都是KV接口,这就要求使用者将千差万别的系统实际接口转化为KV接口使用,而这层转换会掩盖系统中的众多复杂性,比如将Device接口转化为KV后会丢失对相互覆盖操作的验证。

  • 具体问题具体分析:对一些数据模型来说,可能存在多项式甚至是线性复杂度的算法,那么针对这些数据模型使用通用的WGL算法就舍近求远了。

Solitaire(https://GitHub.com/CatKang/Solitaire)是一个c++实现,更快速,支持多数据模型的线性一致性检测工具,致力于解决上述问题。其命名来源于上世纪著名的windows桌面纸牌游戏,要求玩家在保证大小先序关系的限制下,将打乱的扑克牌整理为有序。可以说与我们的线性一致性验证工作非常契合了。

参考

  • Linearizability: A Correctness Condition for Concurrent Objects

  • Testing for Linearizability

  • Faster linearizability checking via P -compositionality

  • Testing Distributed Systems for Linearizability

  • Testing Shared Memories

  • 线性一致性理论

  • Solitaire: 一个更快的,适配更多数据模型的一致性验证工具

  • knossos: Jespen所使用的一致性验证工具,WGL算法实现

  • porcupine: go版本P-compositionality算法实现

  • linearizability-checker: P-compositionality算法实现

  • Jespen

原文链接:Https://mp.weixin.qq.com/s/calyZj0-ZfiYuDlJWQoHaA

您可能感兴趣的文档:

--结束END--

本文标题: 如何验证线性一致性

本文链接: https://www.lsjlt.com/news/46635.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • 如何验证线性一致性
    线性一致性(Linearizability)是分布式系统中常见的一致性保证。那么如何验证系统是否正确地提供了线性一致性服务呢?本文希望从‘什么是线性一致性’,‘如何验证线性一致性’,问题复杂度,常见的通用算...
    99+
    2022-10-18
  • jQuery如何实现验证表单密码一致性
    这篇文章将为大家详细讲解有关jQuery如何实现验证表单密码一致性,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。jQuery 脚本<script type...
    99+
    2022-10-19
  • 数据表迁移数据一致性验证
    在迁移数据库的时候做一些必要的验证还是很有用的,比如说迁移前后的数据条数是否一致,数据是否一致,这个时候怎么办呢,验证条数还好说,要是验证数据是否一致呢,对于重要的数据当然要每条都不会有差错,随机抽样验...
    99+
    2022-10-18
  • PHP Session 跨域的数据一致性验证机制
    随着互联网的发展,跨域访问成为了常见的需求,而在进行跨域访问时,保持数据一致性成为了一项重要的挑战。PHP提供了Session机制用于在不同请求间保持数据的一致性,但默认情况下,Session的跨域访问是无法实现的。本文将介绍一种基于Tok...
    99+
    2023-10-21
    PHP session 跨域
  • rabbitmq如何保证数据的一致性
    RabbitMQ 通过以下方式来保证数据的一致性: 事务: RabbitMQ 支持事务机制,可以将多条消息发送到队列中原子操作。...
    99+
    2023-10-26
    rabbitmq
  • 验证MySQL主从一致性(pt-table-checksum&pt-table-sync)
    percona-toolkit-2.2.8-1.noarch.rpm有两个工具可以验证MySQL主从数据的一致性 安装tookkit需要一些依赖包 yum install perl pe...
    99+
    2022-10-18
  • Redis与MySQL双写一致性如何保证
    🔔什么是双写一致性 指的是当我们更新了数据库的数据之后redis中的数据 也要同步去更新。使用redis读取数据的流程,当用户访问数据的时候,会先从缓存中读取数据,如果命中缓存的话,那...
    99+
    2023-09-13
    redis mysql 缓存
  • MySQL和Redis如何保证数据一致性
    MySQL与Redis都是常用的数据存储和缓存系统。为了提高应用程序的性能和可伸缩性,很多应用程序将MySQL和Redis一起使用,其中MySQL作为主要的持久存储,而Redis作为主要的缓存。在这种情况下,应用程序需要确保MySQL和Re...
    99+
    2023-08-22
    mysql redis 数据库
  • VerifyCodeServlet(一次性验证码)
    通过在表单中总是需要使用一次性验证码,这一问题可以使用VerifyCodeServlet来处理。让<img>元素的src指向VerifyCodeServlet即可在页面中生成一次性验证码。而且VerifyCodeServlet还...
    99+
    2023-05-31
    verifycodeservlet 验证码 一次性
  • 如何保证缓存和数据库一致性
    [TOC] 多年前在一次面试中,被问到如果数据更新,先修改数据库还是先修改缓存。因为没有想过,所以比较懵逼,时候赶紧搜索,发现这里面很有学问。基本上所有的文章最终都指向了两个地方,就是Oracle和Hazelcast对缓存更新策略的介绍。 ...
    99+
    2015-01-22
    如何保证缓存和数据库一致性
  • Java中如何保证缓存一致性问题
    目录前言:方案分析方案一:更新缓存,更新数据库方案二:更新数据库,更新缓存方案三:删除缓存,更新数据库方案四:更新数据库,删除缓存方案对比总结推荐方案延迟双删实际场景写缓存策略读缓存...
    99+
    2022-11-13
  • 聊一聊Redis与MySQL双写一致性如何保证
    1 什么是一致性? 一致性就是数据保持一致,在分布式系统中,可以理解为多个节点中数据的值是一致的。 强一致性: 这种一致性级别是最符合用户直觉的,它要求系统写入什么,读出来的也会是...
    99+
    2022-11-12
  • Ajax如何验证用户的唯一性
    这篇文章主要为大家展示了“Ajax如何验证用户的唯一性”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“Ajax如何验证用户的唯一性”这篇文章吧。具体内容如下浏览效...
    99+
    2022-10-19
  • mysql怎么保证数据一致性
    在MySQL中,可以采取以下几种方式来保证数据的一致性:1. 使用事务:事务可以将一系列操作单独的执行单元,要么全部成功提交,要么全...
    99+
    2023-09-15
    mysql
  • canal怎么保证数据一致性
    canal可以通过以下方式来保证数据一致性: 基于事务日志解析:canal通过解析数据库的事务日志来获取数据变更的信息。由于数据...
    99+
    2023-10-22
    canal
  • redis怎么保证数据一致性
    一般来说,只要你用到了缓存,不管是Redis还是memcache,就可能会涉及到数据库缓存与数据的一致性问题,这里我们以Redis为例。我们该如何保证Redis与数据库的一致性呢? So easy: (推荐...
    99+
    2017-04-27
    redis
  • redis事务能保证一致性吗
    Redis事务能保证一致性,但是对于并发操作来说,并不能保证数据的一致性。Redis事务使用的是乐观锁,即在开始事务前和执行事务命令...
    99+
    2023-08-24
    redis
  • MySQL与Redis如何保证数据一致性详解
    前言 由于缓存的高并发和高性能已经在各种项目中被广泛使用,在读取缓存这方面基本都是一致的,大概都是按照下图的流程进行操作: 但是在更新缓存方面,是更新完数据库再更新缓存还是直接删...
    99+
    2022-11-12
  • 缓存与数据库一致性保证
    全是干货!本文主要讨论这么几个问题:(1)啥时候数据库和缓存中的数据会不一致(2)不一致优化思路(3)如何保证数据库与缓存的一致性一、需求缘起当数据发生变化时,“先淘汰缓存,再修改数据库”这个点是大家讨论的...
    99+
    2022-10-18
  • MySQL保证数据一致性的方式
    这篇文章主要讲解了“MySQL保证数据一致性的方式”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“MySQL保证数据一致性的方式”吧!一、MySQL事务模型A...
    99+
    2022-10-18
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作