原文地址:http://blog.sina.com.cn/s/blog_4b99f86c0100073d.html
分布式同步(synchronization)
集中式系统中,由于只有一个时间源,所以同步不是问题。分布式 系统中,每个进程都运行在不同的机器上,所以 很难对时间达成一致。这会影响程序的正确性,比如unix里面的make。 1 时钟同步 由于绝 对的 同步无法达到,那么需要了解分布式的时钟的基本要求: -没有交互的进程之间时钟不需要同步 -进程间不是需要一个统一的时间,而是需要知道事件发生的先后顺序 -逻辑时钟可以满足上面要求 逻辑时钟:不需要和实际时间一致,只要能表示顺序就行 物理时钟:必须和实际时间一致(UTC) 物理时钟同步 Christian算法 一种集中式的时间服务器拥有标准时间,所有机器都通过周期性询问的方式与这个时间服务器同步。 Berkeley算法 集中式的时间守护进程(daemon)没有标准时间,通过周期性询问所有的机器得到它们的时间,然后对这个时间取平均,再告诉每个机器如何同步(快几分钟或慢几分钟)。 逻辑时钟同步 目的是确定事件之间的happens-before关系。Happens-before关系定义为: -同一进程内a发生先于b,则a->b(箭头->表示happens-before关系) -a是进程1发送消息的事件,而b是进程2接收到那个消息的事件,则a->b -happens-before关系是可传递的,a->b and b->c则a->c -如果以上都不能确定关系的x和y,称它们为并行的事件(a||b) Lamprot Timestamp 当要确定两个事件的先后顺序的时候,通过比较时间戳来确定。时间戳可以是一个二元组(Ti, i),其中Ti是事件发生时进程i的逻辑时钟,而i是进程i的进程id,其作用在于当两个事件的逻辑时钟相等时,双方依然还是能够给出一个一致的对于顺序看法。 Lamport算法其实也就是双方互相比较Lamport时间戳,同步到比较快的时间。 Lamport算法 使用时间戳确定事件的先后顺序。每个进程有一个逻辑时钟,本质上也就是一个不断增加的计数器。 Lamport算法的问题: 1 不反映事件真实的顺序; 2 也无法反映事件的因果关系。 解决办法使用向量时钟。 向量时钟(vector clock) 向量时钟也就是每个进程都有一个逻辑时钟向量,其中保存了它对所有其他进程逻辑时钟的观点(也就是它以为别的进程的逻辑时钟是什么)。每个进程间的通信的消息都会带上逻辑时间戳,而接收进程可以通过这个时间戳来更新它自己的时间。更新的原则是比较向量中每个元素,取相应元素的最大值。 确定事件先后关系
如果两事件的时间戳向量的所有分量都相等就是事件是同时发生的。 如果事件a的时间戳的所有分量都小于事件b的时间戳,则说a->b。 如果无法通过上面两个办法判断,则说两事件是并行的(concurrent)。
2 全局状态和选举算法 2.1 全局状态 有些应用需要知道全局状态,比如垃圾回收(GC),死锁检测,进程的终止等。一个进程需要知道的全局状态包括进程本身的状态和当前要发送给该进程的消息。获得全局状态的算法主要是快照(snapshot)算法。 快照(Snapshot)算法 算法主要思想是通过一个特殊的消息(marker),把需要获得全局状态那个时刻与当前进程相关的信道的消息都挤空。 算法过程: 发起: a) 进程1需要知道全局状态,则向所有其他进程发送marker消息,并开始记录发送过marker消息的信道的状态。 记录: a) 当进程从某个信道第一次收到marker消息的时候,则开始记录该信道状态。并且向所有其他信道发送marker。 b) 若进程从某个信道第二次收到marker消息的时候,则结束记录该信道状态。将记录到的信息当作该信道状态。 假设系统进程之间的联系可以表示成有向完全图。如果把初始进程开始记录消息看作是由于收到一个虚拟信道(不存在的)来的marker的话。那么可以看出,每个进程第一次收到一个marker的时候,该进程的记录就开始了,以后任何信道来的marker作用都只是结束记录了。那么,显然每个进程都发送了n-1条消息,那么n个进程共发送了(n-1)*n条消息,刚好覆盖了所有的边,每个信道刚好是一出一进,一开一关,所以算法最终会结束,而每个进程都会记录到与之有关的全局状态。 2.2 竞选问题 假设: -每个进程有唯一数字ID -每个机器只有一个进程 -每个进程都知道其他全部进程 -进程并不知道哪些进程正常工作,那些已经出故障 大欺小(Bully)算法: 1 某个进程x发起选举,向所有id大于它的进程发选举消息 2 如果接收到大id进程的回复,则放弃选举 3 接收到选举消息的进程最回复以后,会自己发起选举,转1 4 如果没有收到任何回复,则x通知所有进自己作为协调者 选举结果就是当前存在的id最大的进程会胜出。 环(Ring)算法 将所有进程组织成环,如果协调进程崩溃了,发现协调者崩溃的进程发起一个选举,首先把自己的进程号传给下一个进程,每个进程收到选举消息以后把自己的进程号加进去然后传给下一个,如果下一个进程崩溃了,则传给再下一个。当消息第二次回到发起进程时,消息就变成了确定协调者。发起进程再把确定消息发送出去,每个进程看到这个消息都以消息中编号最大的进程作为协调者,当消息传完这一圈以后就消失。
3 共享资源的同步 互斥 临界区的访问问题。三个互斥条件:
ME1 同一时间只有一个进程在临界区中执行(safty) ME2 进入和推出临界区的请求都要在有限时间内满足(liveness) ME3 如果一个请求先于另外一个,那么临界区的授权也必须按照这个顺序(order)
集中式算法 由单一管理进程管理临界区的使用。进入和推出都要求管理进程的同意。 分布式算法(Ricart & Agrawala) 每个要进入临界区的进程先向所有其他进程发消息,得到全部同意后才可进入。当有两个进程同时想进入的时候,比较时间戳,小的可以进入。通过使用Lamport时间戳,可以使得所有进程对于进入请求达成一致。 令牌环 进程组织成环,令牌在环中按顺序传播,谁得到令牌谁能进入。 事务处理 事务模型、两阶段锁、私人工作区、写日志、线性化。
悲观锁 一次把所有将要用的资源都锁定 乐观锁 只是锁定当前要用的资源