物理时钟
同步两个协议:
1、NTP(Network Time Protocal)–>广泛使用
机器周期向时间服务器获取准确时间
2、没有协议名称
−
>
->
−>没有广泛使用
时间服务器周期扫描所有机器,计算时间平均值,告知机器怎么调节时间;导致时间服务器负载大,不广泛使用
逻辑时钟(logical clock)
是一种次序时间,而非准确物理时钟(an ordering time,not exact time)
a.先发生关系(happened-before relation)
1、假设
a
,
b
a,b
a,b是同一进程的两个事件,
a
a
a在
b
b
b前发生,则
a
−
>
b
a->b
a−>b
2、
a
a
a发送消息,
b
b
b接收消息则
a
−
>
b
a->b
a−>b
3、
a
−
>
b
且
b
−
>
c
a->b且b->c
a−>b且b−>c,则
a
−
>
c
a->c
a−>c
b.若无法判断
a
−
>
b
a->b
a−>b还是
b
−
>
a
b->a
b−>a(即先后顺序未知):a,b是并发事件(concurrent)
逻辑时刻(logical timestamp)
记事件event的逻辑时刻(logical timestamp)为
C
(
e
v
e
n
t
)
C(event)
C(event)。
①a和b是同一过程中的两个事件,若
a
−
>
b
a->b
a−>b,
或者
②a发送消息,b接收消息
⋙则
C
(
a
)
<
C
(
b
)
C(a)<C(b)
C(a)<C(b)
如果没有中心结点如何计算逻辑时刻??:
每个进程
P
i
P_i
Pi都维护一个本地计数器
C
i
C_i
Ci,并根据以下规则调整该计数器
1、对于进程
P
i
P_i
Pi,有事件发生时
C
i
=
C
i
+
1
C_i = C_i + 1
Ci=Ci+1
2、有消息发送时,消息中带有时间戳
t
s
(
m
)
=
C
i
ts(m) = C_i
ts(m)=Ci
3、对于收到消息的进程
P
j
P_j
Pj,更新本地
C
j
=
m
a
x
{
C
j
,
t
s
(
m
)
}
C_j=max\{C_j,ts(m)\}
Cj=max{Cj,ts(m)},然后
C
j
=
C
j
+
1
C_j = C_j+1
Cj=Cj+1
将消息传给应用程序前???
例子:
全序多播(totally-ordered multicast)
为提升查询效率,将一个数据库复制两份存在两地。一个查询操作总是在最近的副本上,每次更新操作也在最近的副本执行。但导致如下问题
对于员工奖励,是先增加100元、再提成1%?还是先提成1%、再增加100元?假如员工和经理都会向自己的服务器(员工服务器、经理服务器)发送更新。由于顺序的原因,员工服务器是先增加100元、再提成1%,经理服务器是先提成1%、再增加100元。最终两个服务器数据同步时,会发生冲突。
解决方案:面临的问题是每个副本的两个更新应该以相同的顺序执行。进行一次全序多播,即一次将所有消息以相同的顺序传送给每个接收的多播操作,可以借助逻辑时刻可以用于以完全分布式的方式实现全序多播。
逻辑时钟的硬性问题
1、
a
−
>
b
,则推导出
C
(
a
)
<
C
(
b
)
a->b,则推导出C(a)<C(b)
a−>b,则推导出C(a)<C(b)
2、但是
C
(
a
)
<
C
(
b
)
,不能推导出
a
−
>
b
C(a)<C(b),不能推导出a->b
C(a)<C(b),不能推导出a−>b
A,B进程之间进行交流。C是监控进程(所以都要向C发送一份),对于C来说,r先到a后到,则C( r )<C(a),但是实际上a->b
矢量时钟(Vector clock)
矢量时钟更新规则
在执行过程中为每个计算事件
e
e
e分配一个值
V
(
e
)
V(e)
V(e),这样
a
−
>
b
a -> b
a−>b 当仅当
V
(
a
)
<
V
(
b
)
V (a) < V (b)
V(a)<V(b)。
运行步骤:
1、对于每个进程
P
i
P_i
Pi,有向量
V
C
i
[
1
,
.
.
.
.
.
n
]
VC_i[1,.....n]
VCi[1,.....n],
n
n
n为总的进程数,所有元素初始化为0
2、进程
P
i
P_i
Pi发送消息
m
m
m,则
V
C
i
[
i
]
+
1
VC_i[i]+1
VCi[i]+1,以及发送的消息
m
m
m带上
V
C
i
VC_i
VCi作为消息的向量时间戳
V
t
(
m
)
Vt(m)
Vt(m),一旦到达,接收者就知道
P
i
P_i
Pi的时间戳了
3、进程
P
j
P_j
Pj从
P
i
P_i
Pi接收消息
m
m
m和矢量时间戳
t
s
(
m
)
=
V
t
(
m
)
ts(m) =Vt(m)
ts(m)=Vt(m)
1.更新
V
C
j
VC_j
VCj,对于
V
C
j
VC_j
VCj的每个元素
V
C
j
[
k
]
=
m
a
x
{
V
C
j
[
k
]
,
t
s
(
m
)
[
k
]
}
VC_j[k] = max\{VC_j[k],ts(m)[k]\}
VCj[k]=max{VCj[k],ts(m)[k]}
2.
V
C
j
[
j
]
+
1
VC_j[j]+1
VCj[j]+1
例题
解释:P0,P1,P2初始均为(0,0,0)。
首先
P
0
P_0
P0发生事件
a
a
a,更新
V
C
0
[
0
]
=
0
+
1
VC_0[0] = 0+1
VC0[0]=0+1,且发送消息
t
s
(
m
)
=
(
1
,
0
,
0
)
ts(m) = (1,0,0)
ts(m)=(1,0,0),同时
P
1
P_1
P1发生事件
c
c
c,更新
V
C
1
[
1
]
=
0
+
1
VC_1[1] = 0+1
VC1[1]=0+1,没有发送消息;然后
P
1
P_1
P1发生事件
d
d
d,接收来自
P
0
P_0
P0的消息
m
m
m,更新
V
C
1
[
k
]
=
m
a
x
{
V
C
1
[
k
]
,
t
s
(
m
)
[
k
]
}
VC_1[k] = max\{VC_1[k],ts(m)[k]\}
VC1[k]=max{VC1[k],ts(m)[k]},得到(1,1,0),然后
V
C
1
[
1
]
+
1
VC_1[1]+1
VC1[1]+1,最终得到(1,2,0)。接下来是一个道理
矢量时钟的大小关系
V,W是两个n维整数向量
讨论:在大型网络中,那种时钟合适(物理、逻辑、矢量)??
答:同步是为了进行数据同步,保证数据一致性,在超大型网路中,数据同步需求低(Oracle最多支持9个数据副本同步);在小批量网络中,矢量时钟最合适,逻辑时钟具有发生冲突的根本矛盾。
互斥(mutual exclusion)
资源的数量有限的;多个进程可能希望同时访问一个资源;有些人会读,但其他人可能会写,发生冲突。
三大要求:
1.safety:在任何给定的时间点,最多一个进程可以在关键部分执行任务。(只有一个进程在给定时间进入临界区工作)
2.liveness:请求进入与退出都会成功—即每个进程不会一直待在临界区内
3.fairness:先来后到,先请求先服务(如果一个进入关键部分的请求在另一个请求之前发出,则这些请求将按相同的顺序接受服务。)
进程根据token进入临界区工作
有中心结点
由中心结点进行调度,
初始状态下,等待队列为空,没有进程在临界区工作。1先发送请求,此时没有进程在临界区,中心结点3回复OK,1进入工作;2后发送请求,此时1正在工作,根据安全原则,则中心结点3不回复,2进入等待队列,直至1发出释放信号(Liveness),则3向2发送OK,2进入临界区工作(Fairness)。
无中心结点
基于逻辑环
有令牌的进程才能进入临界区工作
运行情况:每个进程分配了一个它在环中的位置,知道谁在它的下一个位置上,当环初始化时,进程0得到一个令牌(token)。该令牌绕着环运行,点对点的方式把该令牌从进程k传到进程k+1(以环大小为模)。进程从它邻近的进程得到令牌后,检查自己是否需要访问资源。如果要,那么它就继续,完成它要做的工作,然后释放资源;如果一个进程得到了邻近进程传来的令牌,但是它并不想访问资源,那么它就把令牌沿环往下传递。因而,当没有进程要访问资源时,令牌就绕环高速地传递。
不会发生饿死现象,有fairness。
不准许进程在释放资源后,使用同一令牌立即再次访问资源,有safe,liveness。
有Safe, 有live, 有fair?
RA算法(Ricart-Agrawala)基于多播
请求临界区:
1、站点
S
i
S_i
Si想进入临界区时,向其它所有站点发送带有时间戳的REQUEST广播消息
2、站点
S
j
S_j
Sj收到站点
S
i
S_i
Si的请求。
若站点
S
j
S_j
Sj没有请求临界区、也没有在临界区工作,则立即返回REPLY消息。
若站点
S
j
S_j
Sj正在请求临界区,但其时间戳大于站点
S
i
S_i
Si的请求时间戳,则立即返回REPLY消息。
否则,站点
S
j
S_j
Sj将延迟回复REPLY消息,并将请求放进队列中;直至
S
j
S_j
Sj自己完成后再发送
Safe, live, fair?
满足这三个要求
执行临界区:站点
S
i
S_i
Si收到所有REPLY消息后进入临界区
释放临界区:一旦退出临界区,就发送REPLY消息给所有被延迟回复的请求,并从队列中删除
选举算法election algorithms
在某些分布式系统中(如实现互斥的集中式解决方案)可能需要领导(或协调员)。存在单点故障single point of failure)、瓶颈(bottleneck)等问题。
问题是:如何动态选举出一个特殊进程作为leader (选举算法解决了单点故障问题)
假设:1、每个进程均有相应的优先级(权值),一般按照编号来 2、优先级最高的成为leader 3、没有预先存在的领导者,谁触发选举不重要
Bully算法
任一进程发现协作者不再响应时,发起选举
规则:谁的 ID 最大或最小谁来当老大(一般选择 ID 大的)
主持一次选举过程
1.进程
p
p
p发现协作者不响应或相应超时,则发起选举
2.
p
p
p向所有编号比它大的进程发送ELECTION消息
3.若无人相应,则
p
p
p称为协作者
4.如果有编号比它大的进程响应,则有响应者接管选举工作,
p
p
p工作完成。
5.任何时候,一个进程只能从编号比它小的进程得到一个ELECTION 消息。当有ELECTION消息到达时,接收者回送一个OK消息给发送者,表明它仍然在运行,并且接管选举工作。然后接收者主持一个选举,除非它正有一个选举。最终,除了一个进程外,其他所有进程都将放弃,那个进程就是新的协作者。它将选举获胜的消息发送给所有进程,通知 这些进程自己是新的协作者
故障结点复活了,是否抢回leader位---->否,可以容忍一些,直到下次选举
优先级大的结点一直当leader,持续高负荷工作,内存碎片增加,工作效率降低
首先进程4发现协调者7不工作,发起选举,进程4向编号比它大的(5,6,7)发送ELECTION消息,(5,6)向进程4回复OK消息,此时进程(5,6)接管选举,(5,6)向编号比他大的发送ELECTION消息,由于进程7坏了,进程6向进程5回复OK消息,此时进程6是最大的。最后进程6向所有进程发送确认信息
Ring(基于环)
message绕环一圈,就有了全局的信息,知道有哪些结点,将最大编号的作为leader
将进程组织成一个(逻辑)环
◦任何进程都可以通过向后继进程发送选举消息来启动选举。如果后继者故障,则将消息传递给下一个后继者。
◦如果消息被传递,发送者将自己添加到列表中。当它回到发起者那里时,每个人都有机会让它的存在为人所知。
◦发起者在环上发送一个包含所有活进程列表的协调器消息。优先级最高的人被选为协调员。
RA算法参考:https://blog.csdn.net/happy990/article/details/95032371