我很早有一个想法,就是能不能etcd不用fsync,这样就可以提升集群性能。
我自己尝试修改etcd代码,可以参考我之前的尝试:[修改etcd代码],然后测试证明是可行的(但不保证稳定,因为毕竟修改了源码)。
近发现,在新版本etcd 3.5里,官方已经加入了类似的特性,所以建议大家使用官方的解决方案。
但思想一致,都是绕开磁盘的fsync,从而带来集群性能的提升。
即启动etcd时,带入下面的参数
./etcd --unsafe-no-fsync
## 事情没有这么简单
但我们要知道上面的做法是有风险的。
当你不用fsync时,也就意味着如果某个etcd node崩溃了,你不能立即用旧数据启动这个node,因为这时磁盘上的数据可能是坏的。
所以,我们必须删除crash node上的旧数据,然后从集群删除这个node,然后可以用同一个IP再次以全新的node加入集群。
这样就解决了这个问题。
具体操作方法可以参考:[用同一机器替换一个损坏的集群节点]
但这是一个trade off。因为如果etcd集群数据有一定量,比如几十个G,这不是很快能完成的工作,同步数据以及写盘几十个G需要时间。
还有一个更好的方案,就是在整个集群旁边放一个etcd learner,当发现crash member node时,先从集群里删除旧的机器,然后提升(promote)这个learner成为新的集群节点,这样就大大缩减了故障恢复时间,trade off是你需要多增加一台机器做learner。这个方案可以结合我上面的文档再参考官方文档去做,并不复杂。
## 测试结果
可以参考[三机器etcd集群优化测试报告]
对于各个测试你用例,普遍有30%的性能(Throughput)的提升。
还有一个很有趣的现象:如果这个优化放在MacOS上跑,性能可以高提升50倍。具体可以参考[单机MacOS测试报告]
## 总结
假设你的etcd集群很稳定,比如一年有一个node会损坏。你可以冒一点风险,用这个优化带来一年的任何时刻的30%性能提升,同时承担一个小风险:万一node坏了,花点时间(应该是分钟级,我猜的,如果对于大的数据集而言,具体请自行测试)用上面的工具来恢复整个集群。
如果进一步用learner解决方案,集群恢复时间可以降低到秒级。
注意:恢复时间并不是集群不可用时间(或者故障时间)。即使etcd一个节点坏了,对于三节点的集群而言,仍可以正常工作,所以一定时间的恢复在很多工作场景下是值得的。
而且,我认为这是分布式下可以普遍适用的一个尝试和方法,可以参考:Tony:分布式思考:我们需要fsync吗?
而且,可以进一步用我另外两个方法做更深入的尝试: