一片文章说明白分布式系统NRW,Paxos,Raft

引言

今天看到一篇文章提高分布式系统中service宕机的问题,其中作者提到了分布式系统中的一个基本问题。假如有两个service A和B,每个service当然有很多instance。如果A调用B进行数据更新操作,B在接受后未处理前宕机了,怎么办?数据丢失了怎么办?

我们从系统架构的演进来梳理一下各个架构时代这个问题的处理方法

单节点时期

最早的架构很简单,都是单节点。所有请求都由一个节点处理,没有同步,没有扩展。这个时候数据备份主要依靠日志或者其他外部存储设备。但是问题很多,比如请求处理能力弱,无法扩展等等各种问题。

主从时期

为了提高系统的处理能力,我们进入了主从结构,这个结构带来了很多优点。第一:实现负载均衡,读写分离,写操作在master节点,读操作在slave节点。第二 主从异步复制,进行数据备份。但是问题是毕竟是异步复制,存在数据丢失的可能。如果改成同步复制呢?可以解决这个问题,但是影响系统性能。redis 3.0之前没有cluster架构,采用的就是主从架构,异步复制就存在数据丢失的问题,后来3.0之后该用cluster架构,架构的核心就是采用quorum算法。稍后细说quorum算法

主从架构的关键问题,第一数据异步复制可能丢失问题;第二主从架构适合于读多写少的场景,如果并发量大系统性能不理想,无法满足业务要求。第三,不便于扩展,可以无限扩展从节点,但是无法扩展主节点。于是架构进一步演进,出现了分布式架构

分布式架构

分布式架构重要的使命是处理高并发请求,提高数据一致性。如何实现呢?显然分布式结构中,每个节点都可以单独独立读写请求,那么分布式协调就成为最大的问题。

为了避免一个写节点带来的问题,我们分布式系统中所有的节点也就是服务都是对等的,可以同时读写,那么问题来了,谁写的数据是最新的?数据一致性怎么办?读取到脏数据怎么办?要解决这两个问题,就有了分布式系统中的核心概念quorum算法和NRW算法。

分布式写

先说写的问题,为了保证写成功,显然不能写入一个instance就可以,那么写入多少个?需要写入大于n/2个节点就可以。比如3个节点,需要写入2个,超过半数就可以。为什么一定要超过半数呢?保证了数据的串行化修改。一份数据的冗余拷贝不可能同时被两个写请求修改。

继续我们的case,现在写入大于N/2个节点后,写入的节点就是Raft算法选举出来的leader,然后leader负责同步日志到其他follower节点。其中的follower崩溃,leader崩溃都是Raft算法的处理内容。写入过程到此结束,我们看读取。

分布式读

在分布式环境中,写入只要满足大于N/2就认为是成功的,那么必然存在脏读的情况。因为更新了过半数得节点,不是全部?怎么读取呢。这就需要权衡系统是强一致性,还是若一致性,或者最终一致性。

一种方法:数据更新到所有节点再读取,显然是强一致性,但是性能比较低,尤其是读多写少的场景。

第二种方法:根据鸽巢原理,10个鸽子放到9个笼子里面,必然有一个笼子有两个鸽子。所以写入新数据的节点是N/2+1,我们读取的时候读取N-W+1个节点,就必然有一份数据是最新的,然后根据时间戳进行比较就可以。公式表达如下:

r>=n-w+1,也就是r>n-w,即使r+w>n

所以两个重要的原则:

1. R+W>N   保证返回数据至少有一个是最新数据

2. W>N/2   保证了数据的串行化修改。一份数据的冗余拷贝不可能同时被两个写请求修改。

猜你喜欢

转载自blog.csdn.net/hanruikai/article/details/86520055