Paxos
可靠分布式系
统
基
础
:
paxos
的直
观
解
释
2015-07-02
@drdrxp
背景
多个
节
点一起完成一件事情
.
分布式中唯一的一个
问题
:
对
某事达成一致
.
Paxos:
分布式系
统
的核心算法
.
目
录
1.
问题
2.
复制策略
3. Paxos
算法
4. Paxos
优
化
问题
对
系
统
的需求
:
持久性要达到:
99.99999999%
我
们
可以用的基
础设
置
:
磁
盘
:
4%
年
损
坏率
服
务
器宕机
时间
:
0.1%
或更
长
IDC
间丢
包率
:
5% ~ 30%
解决方案
(
可能
)
多副本
x<n
个副本
损
坏不会
丢
数据
多副本的可靠性
:
1
副本
: ~ 0.63%
2
副本
: ~ 0.00395%
3
副本
: < 0.000001%
n
副本
: = 1 - x^n
/* x =
单
副本
损
坏率
*/
解决方案
.
如何
实
施
‘
复制
’?
除了副本数之外,
还
有
:
可用性
原子性
一致性
...
基
础
的复制算法
主从异步复制
主从同步复制
主从半同步复制
多数派写(
读
)
如
Mysql
的
binlog
复制
.
1.
主接到写
请
求
.
2.
主写入本磁
盘
.
3.
主
应
答
‘OK’.
4.
主复制数据到从
库
.
如果磁
盘
在复制前
损
坏:
→
数据
丢
失
.
主从异步复制
Time
Master
Client
Slave.1
Slave.2
Disk Failure
主从同步复制
1.
主接到写
请
求
.
2.
主复制日志到从
库
.
3.
从
库这时
可能阻塞
...
4.
客
户
端一直在等
应
答
’OK’
,直到
所有从
库
返回
.
一个失
联节
点造成整个系
统
不可用
.
:
没有数据
丢
失
.
:
可用性降低
.
Time
Master
Client
Slave.1
Slave.2
主从半同步复制
1.
主接到写
请
求
.
2.
主复制日志到从
库
.
3.
从
库这时
可能阻塞
...
4.
如果
1<=x<=n
个从
库
返回
‘OK’
,
则
返回客
户
端
‘OK’.
:
高可靠性
.
:
高可用性
.
:
可能任何从
库
都不完整
→
我
们
需要
多数派写
(
读
)
Time
Master
Client
Slave.1
Slave.2
多数派写
Dynamo / Cassandra
客
户
端写入
W >=N/2+1
个
节
点
.
不需要主
.
多数派
读
:
W + R > N; R >= N/2+1
容忍最多
(N-1)/2
个
节
点
损
坏
.
Time
Node.1
Client
Node.2
Node.3
多数派写
.
后写入
优胜
最后
1
次写入覆盖先前写
入
.
所有写入操作需要有
1
个全
局
顺
序:
时间
戳
Time
Node.1
Client
Node.2
Node.3
:
高可靠性
.
:
高可用性
.
:
数据完整性有保
证
.
够
了
吗
?
多数派写
..
多数派写
... W + R > N
一致性
:
最
终
一致性
事
务
性
:
非原子更新
脏读
更新
丢
失
问题
http://en.wikipedia.org/wiki/Concurrency_control
一个假想存
储
服
务
●
一个有
3
个存
储节
点的存
储
服
务
集群
.
●
使用多数派
读
写的策略
.
●
只存
储
1
个
变
量
“i”.
●
“i”
的每次更新
对应
有多个版本
: i1, i2, i3…
●
这
个存
储
系
统
支持
3
个命令
:
get
/*
读
最新的
“i” */
set <n>
/*
设
置下个版本的
i
的
值为
<n> */
inc <n>
/*
对
“i”
加
<n>
,也生成
1
个新版本
*/
我
们
将用
这
个存
储
系
统
来演示多数派
读
写策略的不足,
以及如何用
paxos
解决
这
些
问题
.
一个假想存
储
服
务
.
实现
命令
实现
:
"set" →
直接
对应
多数派写
.
"inc" → (
最
简单
的事
务
型操作
):
1.
通
过
多数派
读
,
读
取最新的
“i”: i1
2. Let i2 = i1 + n
3. set i2
X
set i2=3
X
get i
2
1
2
1
0
0
3
2
2
1
3
2
X
get i1=2
i2 = i1 + 1
3
2
2
1
3
2
set i2=3
OK
set i2=4
一个假想存
储
服
务
..
并
发问题
X
X
get i
2
1
2
1
0
0
3
2
2
1
3
2
5
3
2
1
5
3
X
get i1=2
i2 = i1 + 1
我
们
期待最
终
X
可以
读
到
i3=5,
这
需要
Y
能知道
X
已
经
写入了
i2
。如何
实现这
个机制?
Y
get i1=2
Y
i2 = i1 + 2
3
2
2
1
3
2
此
时为
了保
证
正确,
Y
必
须
重新运行多数派
读
,然后再
进
行一次多数派写
这
1
步
Y
必
须
失
败
。
否
则
X
写入的
值
会
丢
失。
一个假想存
储
服
务
...
在
X
和
Y
的
2
次
“inc”
操作后,
为
了得到正确的
i3
:
整个系
统
里
对
i
的某个版本
(i2)
,只能有
1
次成功写入
.
推广
为
:
在存
储
系
统
中,一个
值
(1
个
变
量的
1
个版本
)
在被
认为
确定
(
客
户
端接到
OK)
之后,就不允
许
被修改
().
如何定
义
“
被确定的
”?
如何避免修改
“
被确定的
”
值
?
如何确定一个
值
X
Y
Any value set?
X
No
X
X
-
-
-
-
Any value set?
-
-
-
Y
Yes, Y gives up
X
X
X
-
X
X
-
方案
:
每次写入一个
值
前,先运行一次多数派
读
,来确
认
是
否
这
个
值
(可能)已
经
被写
过
了
.