化茧成蝶:Go在FreeWheel服务化中的实践
上QQ阅读APP看本书,新人免费读10天
设备和账号都新为新人

WAL日志持久化时机优化

首先考察WAL(Write-Ahead-Log)日志处理机制。在V1中WAL日志是随着每个消息的到来同步写磁盘的,使得集群稳定性对磁盘稳定性很敏感。

Fig 4.1.1 V1中WAL日志直接写磁盘

Fig 4.1.1中是V0.4.9(此前的版本这部分实现没有变化)中的代码片段。在appendEntries里让我有些疑惑的地方是前后加了两次锁,从实现上来看,就是希望写入WAL的操作绝对互斥,非常容易成为整个系统的瓶颈。

同步写磁盘的弊端一方面会导致后续的命令处理都被阻塞,节点可能会丢失心跳,最后整个集群会不稳定;另一方面整个集群的可靠性非常依赖磁盘的稳定性,任何一次写入失败都可能损坏数据。道理很简单,多次写磁盘就会导致本来小概率的事件被放大成大概率事件了。

从V2开始,WAL的文件改为异步写,不是每个请求都写文件,转而用一个时钟来控制,事件到来时先写入Unstable队列,这是内存中的一个数组,然后批量写入WAL文件。