在分布式系统中,我们通常增加数据的冗余来达到较高的数据可靠性,多副本和纠删码是最常用的两种数据冗余技术。Quorum 机制则是经常配合冗余副本管理的一种机制。
我们先考虑一个简单的场景,你的系统是 3 副本设计,怎么读写流程比较好?直观来讲,写的时候 3 副本都写成功才报告成功,那么读的时候随便读哪个副本都是可以的。这个是最简单的副本策略:write-all-read-one,简称 WARO,也是最常用的一种副本策略。
Write-all-read-one
对于多副本冗余的系统来说,写的时候,所有的副本节点写都成功才算成功(write all),读的时候就可以随便读一个副本即可(read one)。这个就很容易理解,因为有这么个假设存在:只要写成功了,那么多副本的数据就是一致的,你随便读哪个都是正确的数据(不考虑静默或其他问题,静默导致的问题用数据自校验解决)。
现在我们想一个问题,为什么 WARO 的模式下,在读的时候可以随便读任一副本的数据?
关键在于:我们读的是写成功的数据,这个是 Write-All 这个前提保证的。现在思考下优缺点:
优点:
- 实现简单,无需考虑复杂的异常处理,读的时候高效;
缺点:
- 写的可用性不大好,由于更新写操作需要在所有的 N 个副本都成功,写操作才算成功,所以一旦有一个副本异常,写失败,则更新操作不可用。对于更新服务来说,虽然系统由 N 个副本,但系统却无法容忍任何一个副本异常;
- 读的可用性挺好的,N 个副本中,只要由一个副本正常提供服务,系统就可以提供读服务,换句话说,系统可以容忍 N-1 个副本异常;
所以,我们看到 WARO 读写可用性的区别,更新服务的可用性太低了,系统虽然使用了多副本,但是更新操作的可用性等效于没有副本。
能优化这个吗?可以的,其实就是 CAP 理论,WARO 保证了数据的高度一致性,但是牺牲了写更新的可用