我对Lamport Logical Clock的理解

建议先看论文原文再来看这篇文章,我不会对论文中的各个点都具体说明。仅仅是写一些我自己的想法,帮助理解。

大家都知道。分布式环境下。确定各个事件发生的顺序非常重要,不然就会发生一些麻烦的问题。

考虑一下这个问题:小明要用同学给的优惠码在京东上买一本书。如果京东的后台架构如图一所看到的。A是前端代理server,负责接收用户请求,B是优惠码验证server,当用户请求使用优惠码的时候,A会把请求发给B。让B来验证。C是日志server。专门存放日志。系统中的不论什么一个操作都会记录到日志server中。非常显然,这是一个分布式系统。

图一  后台架构

小明的买书过程分为3个步骤:

  1. 请求到达A。A发送一条消息给C,让C记录一条日志[小明下了订单XXX号]
  2. A是异步工作的。发送完1后,A发现小明使用了优惠码,就把优惠码发送给B进行验证
  3. B验证了优惠码发现是合法的。就发送消息给C,使之记录日志[XXX号订单使用了优惠码YYY]

至此,买书过程结束。假设一切正常的话,那日志server上会依次产生[小明下了订单XXX号],[XXX号订单使用了优惠码YYY]这两条日志。

但事情没有这么简单,假设A跟C之间的网络比較慢,导致3在1之前到达C,那么C上就会产生顺序相反的两条日志。这样就出问题了。由于是1的发生才导致了3的发生,这两者能够看成是有因果关系的,可是生成的日志却是相反的。

有什么办法能让系统识别事件的因果关系呢?比較easy想到的是让server每次发送消息的时候带上时间戳,C收到消息之后比对时间戳。就知道谁先谁后了。

问题是,在分布式环境下。各个机器的时钟是无法100%同步的,所以这样的方法不靠谱。

那有没有办法在不借助物理时钟的情况下给分布式环境下的全部事件排序呢?

这就须要借助Lamport大神在1978年提出的Logical Clock。

Happend-before关系

Lamport在文章中首先定义了一种关系,叫做Happend-before,我个人的理解是相当于因果关系,用->表示,比方a->b就叫做a Happend-before b。即b是由a引起的。

若两个事件a,b满足以下任一条件,则记作a->b:

  1. 假设a b是在同一进程内的两个事件。而且a发生在b之前,那么a->b
  2. 假设a代表了某个进程的消息发送事件,b代表还有一进程中针对这同一个消息的接收事件,那么a->b

以下这张图非常好地展示了Happend-before这一关系。

图二  Happend-before关系

P和Q是两个独立的进程,也能够理解为分布式系统中的两台server;时间从上往下递增。圆圈表示事件。

图中红色的箭头就是上述的Happend-before关系。a,b和e,f各自是同一进程中的先后两个事件,满足条件1,b和f各自是消息的发送事件和接受事件。满足条件2。那么事件a和e。b和e。各自是什么关系呢?事实上他们之间没有因果关系。能够觉得他们是并发的。正由于他们没有因果关系,所以从系统的角度来看,他们谁发生在前谁发生在后不重要,仅仅要能辨别清楚有因果关系的事件。使得因果关系不会倒转,那么整个分布式系统就可觉得是正确的,至少从逻辑上不会非常出错。至于那些没有因果关系的并发事件,不用关注他们的先后顺序。(理解这段话是非常重要的,这正是Logical
Clock的精髓所在。

可以这么理解。Logical Clock解决的问题是找到一种方法,给分布式系统中全部时间定一个序,这个序可以正确地排列出具有因果关系的事件(注意,是不能保证并发事件的真实顺序的),使得分布式系统在逻辑上不会发生因果倒置的错误。

那么怎样利用Happend-before关系来定义顺序呢?继续往下看。

Logical Clock

如今我们给系统中全部的事件打上一个时间戳(事实上就是一个递增的序号)。每一个进程维护一个自己的时间戳。时间戳的添加遵循以下两点规则:

  1. 假设两个事件发生在同一个进程上。而且不是接受消息的事件。那么后面事件的时间戳为前面的+1
  2. 假设一个事件是接受消息。那么他的时间戳为本进程前续事件的时间戳与接受到的消息的时间戳中较大者+1

图三  时间戳演示

上图展示了打完时间戳后的样子,可见这个时间戳确保了在因果条件的事件中是递增的。可是并发的事件(如a和e),他们的时间戳是没有可比性的。谁大谁小说明不了问题。记C(a)为事件a的时间戳,那么:

  1. 若a->b,即a与b有因果关系,那么C(a)>C(b)
  2. 若a与b没有因果关系,那么C(a)与C(b)可能是随意关系(大于 小于 等于)

也就是说,依据这个时间戳。是没法反过来判断事件发生的真实顺序的,由于对于并发事件来说。尽管C(a)>C(b),但或许a与b的真实顺序是t(a) < t(b)。

那么C(a)>C(b)就没有意义了?换个角度想想,既然上面说过,并发事件的顺序不重要。不会影响系统的正确性。那么我们任意定一个顺序不就完了吗?就当作时间戳大的事件肯定是发生在后面,时间戳小的事件肯定是发生在前面,这样一来不就统一了因果事件和并发事件的排序了吗?可是另一个问题,两个并发事件的时间戳一样怎么办?那就再加一层假定,给分布式系统中的server编号。当两个时间戳一样时,编号小的server就当他发生在先.

总结一下上面说的,我们能够定义这样一个全序关系”=>”:如果a是进程Pi中事件。b是进程Pj中的事件。那么当且仅当满足例如以下条件之中的一个时:(1)Ci(a)<Cj(b);(2)Ci(a)=Cj(b)且Pi<Pj,那么我们就觉得“a=>b”。

这样一来,我们就完毕了对分布式系统中全部事件的定义。可是大家可能会疑惑,这样是不是有点太任意了。非常不靠谱的感觉。

确实,Lamport也承认这一点,他在论文最后也说了:

The total ordering defined by the algorithm is somewhat arbitrary. It can produce anomalous behavior if it disagrees with the ordering perceived by the system’s users.

可是至少这种方法给出了一个定义分布式系统中事件顺序的方法,他确保的是全部因果关系的事件不会发生逻辑错误,但他并不保证系统的公平性(比方两台server同一时候并发地请求一个资源,物理时间上先发出请求的进程不一定会先得到这个资源。但这顶多会造成不公平,不会造成错误)。

怎么理解呢?看一下以下两个样例。

Logical Clock应用

如今让我们回过头看看文章开头提到的问题。怎么利用Logical Clock保证日志的顺序正确呢?Lamport在论文的后半部分提出了一个算法,能够解决问题。

可是这个算法基于一个前提:对于随意的两个进程Pi和Pj,它们之间传递的消息是依照发送顺序被接收到的。这个如果并只是分,TCP就能够满足要求。

  1. 首先。每一个进程会维护各自在本地维护一个请求队列。

    算法是由例如以下5个规则定义的。

    方便起见,每条规则定义的行为会被做为一个独立事件。

  2. 为请求该项资源(在这个问题中,资源就是日志server),进程Pi发送一个(Tm,Pi)资源请求消息给其它全部进程,并将该消息放入自己的请求队列,在这里Tm代表了消息的时间戳
  3. 当进程Pj收到(Tm,Pi)资源请求消息后,将它放到自己的请求队列中。并发送一个带时间戳的确认消息给Pi。(注:假设Pj已经发送了一个时间戳大于Tm的消息,那就能够不发送)
  4. 释放该项资源时。进程Pi从自己的消息队列中删除(Tm,Pi)资源请求。同一时候给其它全部进程发送一个带有时间戳的Pi资源释放消息
  5. 当进程Pj收到Pi资源释放消息后,它就从自己的消息队列中删除(Tm,Pi)资源请求
  6. 当同一时候满足例如以下两个条件时,就将资源分配给进程Pi:

a) 依照“=>”关系排序后。(Tm,Pi)资源请求排在它的请求队列的最前面

b) Pi已经从全部其它进程都收到了时间戳>Tm的消息

为什么这个算法能够保证日志server能被依照正确的顺序分配呢?细致想一想5中的a b两个条件,仅仅有当一个进程收到全部其它进程>Tm的消息后才会对自己的队列进行排序。

那么如果其它进程在他之前请求了这个资源,可是由于网络慢还没收到,怎么办?由于前面已经提出如果,对于随意的两个进程Pi和Pj,它们之间传递的消息是依照发送顺序被接收到的。

所以既然收到>Tm消息,那么说明其它全部进程在Tm之前的消息也都已经被收到了,所以这个时候自己的队列中肯定已经收到了全部的对资源的请求。这个时候仅仅须要依照“=>”关系排序。排在最前面的就是最先发出请求的。

可见利用Logical Clock确实能够解决这样的问题。那么我们再来看还有一种问题。如果京东的后台架构例如以下图所看到的:

图四  还有一种情况

有多台前端代理server。用户请求会随机地分配到各个代理server上。

假设小明在物理时间7点50下单买了一本书,大明在7点51分下单,正好书仅仅有一本。小明的请求被分配到了serverA,大明的被分配到了serverB。假设在这之前,A的Logical Clock走到了200。而B的Logical Clock走到150。那么在这个情况下。假设运用上述算法,B会先获得资源,下单买到票。所以从道理上说。这个算法是不公平的,可是换个角度想想,这样充其量也仅仅是不公平。不会导致系统发生因果错误。由于小明和大明的请求在系统看来是并发事件,没有因果关系,所以系统无法判定并发事件的真实顺序。

这就是之前我说的“这种方法给出了一个定义分布式系统中事件顺序的方法,他确保的是全部因果关系的事件不会发生逻辑错误,但他并不保证系统的公平性(比方两台server同一时候并发地请求一个资源。物理时间上先发出请求的进程不一定会先得到这个资源。但这顶多会造成不公平,不会造成错误)。

參考文献:

  1. Lamport, L. (1978). “Time,
    clocks, and the ordering of events in a distributed system”
  2. Why vector clocks are more powerful than Lamport
    timestamps
  3. Lamport论文中文翻译加感想
  4. 数据一致性: 时间戳策略
  5. 分布式数据库的数据版本号合并

原文地址:http://www.orzace.com/lamport-logical-clock/

时间: 2024-10-26 05:09:39

我对Lamport Logical Clock的理解的相关文章

Lamport Logical Clock 学习

1,导论 ①如何在分布式环境下定义系统中所有事件的发生顺序?②分布式环境下多个进程竞争资源时如何互斥?③什么是偏序,偏序的作用是什么,有什么不足?④什么是全序,全序的作用是什么,有什么不足?⑤为什么需要物理时钟,物理时钟如何同步?下面来进行介绍. 2,偏序的定义.发生在先(happened before)关系 考虑单一的进程A,在某时刻发生了事件E1,经过一段时间后,发生事件E2,可以说:E1发生在E2前面.考虑多个进程,进程A向进程B发送消息,进程A发送消息时记为事件E1,进程B接收到进程A发

(转)一些经典的计算机书籍

以下列表中的计算机书籍(中文版)来自微博:@程序员的那些事 粉丝的推荐.按推荐次数,从高到低往下排.如果大家还有其他计算机相关的经典书籍推荐,请在评论中留言,或者在这条微博的评论中留言,我们将继续扩充这个列表.1. 算法导论(第2版)2. 代码大全(第2版)3. C++ Primer中文版(第4版)4. 设计模式:可复用面向对象软件的基础5. 浪潮之巅6. Java编程思想(第4版)7. Java核心技术 卷1:基础知识8. Java核心技术 卷2:高级特性9. 人月神话10. Linux内核编

Java内存模型-jsr133规范介绍

原文地址:http://www.cnblogs.com/aigongsi/archive/2012/04/26/2470296.html; 最近在看<深入理解Java虚拟机:JVM高级特性与最佳实践>讲到了线程相关的细节知识,里面讲述了关于java内存模型,也就是jsr 133定义的规范. 系统的看了jsr 133规范的前面几个章节的内容,觉得受益匪浅.废话不说,简要的介绍一下java内存规范. 什么是内存规范 在jsr-133中是这么定义的 A memory model describes,

后端技术:分布式系统理论 - 从放弃到入门

分布式系统理论 - 从放弃到入门随承载用户数量的增加和容灾的需要,越来越多互联网后台系统从单机模式切换到分布式集群.回顾自己毕业五年来的工作内容,同样有这样的转变. 毕业头两年负责维护运行在刀片机上的业务,在机房里拔插单板的日子是我逝去的青春.设备之间通过VCS组成冷备,但即使有双机软件保护,宕机.网络丢包等问题发生时业务仍会受影响.这样的系统架构下为保证SLA,有时候需要深入 Linux系统内核或硬件层面分析机器重启的原因. 接下来负责维护承载在分布式集群上的业务,相比前面的工作,这个阶段主要

分布式系统理论进阶 - Raft、Zab

引言 <分布式系统理论进阶 - Paxos>介绍了一致性协议Paxos,今天我们来学习另外两个常见的一致性协议——Raft和Zab.通过与Paxos对比,了解Raft和Zab的核心思想.加深对一致性协议的认识. Raft Paxos偏向于理论.对如何应用到工程实践提及较少.理解的难度加上现实的骨感,在生产环境中基于Paxos实现一个正确的分布式系统非常难[1]: There are significant gaps between the description of the Paxos al

MySQL 5.7 Replication 相关新功能说明

背景: MySQL5.7在主从复制上面相对之前版本多了一些新特性,包括多源复制.基于组提交的并行复制.在线修改Replication Filter.GTID增强.半同步复制增强等.因为都是和复制相关,所以本文将针对这些新特性放一起进行说明,篇幅可能稍长,本文使用的MySQL版本是5.7.13. 1,多源复制(多主一从) MySQL在5.7之后才支持多源复制,之前介绍过MariaDB 多主一从 搭建测试说明,现在介绍如何在MySQL上做多主一从,具体的方法说明可以查看官方文档. 原理:多源复制加入

分布式系统理论基础 - 时间、时钟和事件顺序

十六号…… 四月十六号.一九六零年四月十六号下午三点之前的一分钟你和我在一起,因为你我会记住这一分钟.从现在开始我们就是一分钟的朋友,这是事实,你改变不了,因为已经过去了.我明天会再来. —— <阿飞正传> 现实生活中时间是很重要的概念,时间可以记录事情发生的时刻.比较事情发生的先后顺序.分布式系统的一些场景也需要记录和比较不同节点间事件发生的顺序,但不同于日常生活使用物理时钟记录时间,分布式系统使用逻辑时钟记录事件顺序关系,下面我们来看分布式系统中几种常见的逻辑时钟. 物理时钟 vs 逻辑时

[转载] 架构领域学习资料

原文: http://qing.blog.sina.com.cn/2244218960/85c41050330031zq.html 系统架构领域的一些学习材料 标签:架构学习材料系统systemresearch 系统架构是一个工程和研究相结合的领域,既注重实践又依赖理论指导,入门容易但精通很难,有时候还要讲点悟性,很具有“伪科学”的特征.要在此领域进阶,除了要不断设计并搭建实际系统,也要注意方法论和设计理念的学习和提炼. 经常有同学询问如何学习,特贴一篇学习材料,供大家参考.09年时写的,在系统

redis学习六 集群的原理(转载)

转载自 http://shift-alt-ctrl.iteye.com/blog/2285470 一.Redis Cluster主要特性和设计     集群目标 1)高性能和线性扩展,最大可以支撑到1000个节点:Cluster架构中无Proxy层,Master与slave之间使用异步replication,且不存在操作的merge.(即操作不能跨多个nodes,不存在merge层) 2)一定程度上保证writes的安全性,需要客户端容忍一定程度的数据丢失:集群将会尽可能(best-effort