在阅读raft论文的时候,考虑两个问题:
- 为什么要用Replicated State Machine?没有其他方式吗
- 为什么要先写日志再应用到Replicated State Machine,直接应用到Replicated State Machine刷磁盘不行吗?
1 Replicated State Machine
在raft协议中,每一个server中都有一个Replicated State Machine,只要每个server接收到的输入命令是相同的,那么Replicated State Machine最后的结果就是相同的,也就达到了最终的共识性。那么我们可以考虑下,如果不使用Replicated State Machine,还有其他的方式吗。其实一共两种方式的复制方式:
为了令进程实现高可用,我们可以对进程进行备份,而实现进程的主从备份主要有两种方法
- State Transfer(状态转移):主服务器将完整的状态内容都传输给备份服务器
- Replicated State Machine(备份状态机):将需要备份的服务器视为一个确定性状态机 —— 主备以相同的状态启动,以相同顺序导入相同的输入,最后它们就会进入相同的状态、给出相同的输出
第二种就是刚才所说的Replicated State Machine。假设考虑使用第一种,我们需要将server中整个数据复制到每个其他server, 性能成本显然是不可行的,所以在多副本复制的情况下都采用Replicated State Machine,只需要将增量命令应用于状态机就能达到最终的共识。
2 WAL
WAL,Write-Ahead Logging。WAL的中心思想是对数据文件的修改必须发生在这些修改已经记录到日志之后,也就是先写日志落盘然后写数据。如果遵循这一过程,就不需要每次提交事务的时候把数据块刷回磁盘,因为出现奔溃的情况下可以用日志来恢复数据。
那么这有什么好处呢?为什么不直接落盘呢?
- 使用WAL主要的好处就是显著地减少了写磁盘的次数,因为在日志提交的时候只需要把日志文件刷新到磁盘,而不是事务修改的所有数据文件,而且日志文件是顺序写的,因此同步日志的开销远比同步数据块的开销要小。这里我们就回答了刚才的问题,关键点是性能。
- 使用日志还支持回滚等操作
因此,在raft中,leader将log复制到follower后就表示该操作已经被持久化,而复制到大多数后就表示该消息在整个系统中已经不会丢失了(个人理解)