Jepsen的使用与线性一致性

注: 本文转载自: Jepsen的使用与线性一致性 , 用于自己学习记录。

背景

对于分布式系统的测试是整个系统开发过程中重要的部分,我们需要对系统进行完整的正确性测试才能确保系统符合我们的设计。Jepsen是Kyle Kingsbury使用Clojure编写的分布式系统测试框架,Jepsen通过并发运行一组Client对系统进行操作,再利用验证模块knossos对操作的History进行正确性的验证。Jepsen也会生成关于性能和可用性的图表,帮助使用者确认系统响应不通的注入错误时的状态。这里的正确性定义为线性一致性,即分布式领域著名的CAP定理中的C。

Jepsen的架构

Jepsen测试系统由一个Control node和多个DB node组成。Jepsne需要使用者将待测DB系统的启动部署和Client的连接和DB操作等模块预先编写至测试脚本中。

Jepsen的测试脚本:

  • Operation

    Operation指Client对待测DB系统的操作调用,常用的包括read,writecompare-and-set

  • Client

    Client模块由使用者编写,每个Client封装了setup!invoke!close!函数,setup!是连接DB的函数,invoke!是对DB的Operation调用,close!是关闭连接

  • DB

    DB模块封装了待测系统的部署,启动,关闭接口,由Jepsen的os模块预先优化配置环境,通过调用DB模块中的setup!一键启动

Jepsen测试框架的核心模块:

  • generator

    嵌入至Client模块,生成一系列的随机操作。

  • nemesis

    Jepsen的核心模块,与generator搭配,对DB node引入一系列的错误故障,包括网络分区,丢包,延迟,DB系统的宕机和节点时钟修改。

  • checker

    由作者编写的另一个库knossos来验证整个Operation的History是否符合线性一致性。

下面是三个核心模块混合搭配使用的例子:

(defn create-partition-node-test
  "Cuts the network into randomly nodes."
  [opts]
  (create-test
               (merge opts
               { :nemesis   (nemesis/partition-random-node) ;引入随机节点隔离的故障类型
                 :generator (->> (gen/mix [r w])
                                 (gen/stagger 1/10)
                                 (gen/delay 1/10)
                                 (gen/nemesis
                                 (gen/seq (cycle [(gen/sleep 10)
                                              {:type :info :f :start}
                                              (gen/sleep 10)
                                              {:type :info :f :stop}])))
                                  (gen/time-limit (:time-limit opts)))
                              }))

分布式系统的正确性测试

对于分布式系统来说,正确性是最重要的特性,而正确性是很难证明的,尤其是分布式系统的正确性。所以我们对于分布式系统的测试往往从形式化验证和软件工程的测试方法:

形式化验证

对于分布式系统的算法模型,需要进行形式化验证,利用数学语言证明算法满足正确性。目前比较常用的是TLA+,TLA+是图灵奖得主Leslie Lamport发明的专门用来描述并验证复杂系统行为的形式化方法,使用TLA+可以帮助我们在设计时,基于系统层面的抽象对系统的正确性做形式化、规范的描述,并且定义出设计的正确性属性,自动化地加以验证,以正确性为驱动进行系统建模和设计。

工业化测试

而在实际的生产环境里,多节点,交互复杂的分布式系统中,节点异常,网络异常,配置变更等场景不常发生但不可避免。为了应对这些可能出现的场景,我们对系统的测试必须尽可能提高这些事件发生的概率,比如Leadership changes, Partial network outage,从而测试整个系统的正确性。所以常见的做法如下:

  1. 让系统的某些参数设置的不合理, 但是不违反正确性, 这样可以让那些极端的场景下的问题暴露出来。比如Election timeout 设置成非常低, Heartbeat 的间隔非常高 这样就导致更频繁的Leader Changes. 更频繁的快照等等这些操作.
  2. 让运行的环境出现频繁的外部环境变化, 比如频繁进程随意启停, 网络丢包, 断网, 频繁Membership change 等等
  3. 长时间的压力测试运行,引入稳定性压力测试和极限负载情况下导致系统崩溃的破坏性压力测试。

而在错误注入这个方向,Jepsen是一个很强有力的工具。

正确性

既然要测试一个系统的正确性,我们先来定义什么是正确性。这里的正确性就定义为Linearizability Consistency,即CAP定理中的C。

Linearizability Consistency是Maurice P. Herlihy与Jeannette M. Wing在1987年共同提出的关于并行对象行为正确性的一个条件模型,两人在1990年发表了关于Linearizability的论文。在论文中讨论了关于Linearizability的定义和形式化证明, 其中对线性一致性的系统的正确性,作者给出了两点要求:

  • each operation should appear to “take effect” instantaneously
  • the order of nonconcurrent operations should be preserved.

即每一个操作都会立即生效,非并行的情况下的Operation结果会对下一个Operation产生影响。

在论文中引入了一个FIFO(first in, first out)的队列操作来讲述这个观点:

accept

上图中的Enq代表入列,Deq代表出列,x,y,z,均为操作的值,A,B为操作的进程. 即E(x) A ,D(x) B分别代表A进程将x值入列,B进程将x值出列。一个时间轴代表操作的invoke和resp的返回时间片,在一个线性一致性的系统里面,任何操作都可能在调用或者返回之间原子和瞬间执行。通过标明线性一致性的点,我们可以得出结论上图是符合线性一致性的。

not accept

这个例子是很明显不符合线性一致性的,即D(y) A是非法的操作,因为根据FIFO队列的原理,xy之前入列,但y却在x还没有被出列之前被dequeue。

  • Locality(局部性)

    如果每一个独立的对象是线性线性一致性的,那么这个系统也是符合线性一致性的。即将各个独立的对象的线性历史组合起来也是符合线性一致性的。

  • Nonblocking(非阻塞性)

    整个操作过程中不会被阻塞,即任意一个Operation无需等待其他的Operation的完成。

为什么一个分布式系统需要具备线性一致性? Linearizability站在Client的角度上来说,假如一个系统是符合线性一致性的,那么多个Client在指定的一个时间点所读到value是一致的,这就符合了CAP理论中的C。

在利用Jepsen测试我们的系统的过程中,我们对分布式系统的测试有了更全面的认识和实际的测试经验,关于Jepsen的使用我们也有以下几点经验之谈:

  • 丰富的故障类型引入,方便使用者全面的测试系统。在实际的生成环境中,网络分区,时钟同步,节点失效都是很容易发生的故障,Jepsen测试分布式系统在这些故障模型下的行为。
  • 黑盒测试,不需要接触系统的源码。
  • 假如配置的参数time-limit过长容易造成Jepsen的分析过程发生OOM的情况。
  • Clojure的使用门槛过高,函数式编程让自定义协议的系统无法引用现成的测试用例,必须重新编写测试脚本。
  • Jepsen对系统的并发压力有限,所以这里仅仅验证了系统的算法正确性。

在完全通过一致性测试框架Jepsen后,我们后续也将从引入形式化验证即TLA+验证算法的正确性。

分布式系统测试的思考

关于分布式系统测试是一件复杂的事情,在测试分布式系统的正确性时,使用错误注入是一个很必须的手段。在工程验证方面已经有Jepsen等框架,而形式化证明也能够保证一个分布式系统的正确性,比如Raft目前已经有了用TLA+编写的形式化证明

虽然我们这里使用Jepsen框架完成系统的正确性测试,但系统的测试内容不仅仅限于正确性,即使协议算法被证明是正确的,也仍然很难在实现中避免Bug。而其他的测试内容,包括系统的性能测试和可靠性测试,因为分布式系统中的并发情况造成的不确定性,使系统的问题往往在高并发的压测环境下才有可能触发。所以对于系统的其他方面测试,我们还需要对系统引入上述所说的多种故障类型的同时,提高对整个系统的并发压力,才有可能在一些极端情况下发现系统的问题。最后对于分布式系统的测试,我们还需要完整的覆盖率测试,通过实际的业务场景对整个系统进行白盒测试,从而提高系统的代码质量和鲁棒性。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,457评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,837评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,696评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,183评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,057评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,105评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,520评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,211评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,482评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,574评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,353评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,213评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,576评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,897评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,174评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,489评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,683评论 2 335

推荐阅读更多精彩内容