Redis专栏合集
【专栏】基础篇04| Redis 该怎么保证数据不丢失(上)
【专栏】基础篇05| Redis 该怎么保证数据不丢失(下)
通过前两节我们了解了在单实例下Redis是如何保证数据不丢失的,而作为NoSql的分布式键值数据库,往往以集群的方式提供服务才能保证所谓的”高可用“,而复杂度也会随着服务模式的改变而提升,多个实例之间的复制延迟导致的数据不一致、宕机实例的发现与切换等问题随之产生,这几乎是所有分布式存储都会遇到的问题,因此我们这一节抛开Redis,从存储高可用的角度看看背后的运作模式与规律。
主备与主从
我们经常会听到主备模式主从模式,这其实属于双机架构中的模式,双机架构顾名思义简化为两台机器扮演不同集群角色,主备模式是一台主实例一台备用实例,主实例负责提供读写服务,备用实例提供对主实例的数据备份工作,主备模式通过备库实现数据冗余保证高可用,但是问题在于备库不提供服务,会造成资源浪费。
主从模式的从库可以提供读服务,这也是读写分离的基本架构,读写分离基于的场景是读多写少,可以有效利用从库分担主库压力,也避免了资源浪费。但是主从模式对于客户端来说需要主动区分读写,并且由于主从同步延迟可能造成数据不一致。
双机架构本质的做法就是冗余一份数据保证集群下的Crash Safe,那么我们套用事前事中与事后的模板,看看在故障发生前中后需要做什么。首先发生前,需要知道双机的各自状态是健康还是故障;当感知到故障时,就需要做双机切换,这个步骤由人工完成或者自动完成;完成切换后,需要补充新的实例保证双机结构完整。无论是主从还是主备都存在故障切换的问题,而在这个问题的处理过程中,就有一个问题:谁来判断故障并完成切换。
双机互联切换
这种方式是由实例自己来完成切换,在主从架构下可以主从建立连接,从库监听嗅探主库是否正常,当判断为故障时将自己”选举“为新主库从而完成主从故障切换。这里提到了”选举“,是由于双机架构是数据架构原型,一主多从、多主多从都属于双机架构,而在多个从库下从库判断主库故障后会”毛遂自荐“成为主库,当然最后只有一个从库会成为主库,这也是分布式下经典的”共识“问题,这里就不展开了。
双机互联有个问题在于从库多了就有很多心跳连接,而网络本身具有不可靠性,因此如果从库判断出现问题,则可能会有主库假死,而从库又升级为主库导致的双主库现象,也叫做”脑裂“。脑裂是指左右脑互相感知不到,导致各自向身体发出指令的现象。
中间代理切换
”计算机世界一切问题可以加一个中间层解决“,中间代理模式就是加一个中间角色,每个实例向这个中间人汇报自己的状态,最后由这个角色进行状态判断与故障切换的工作。
中间角色的引入简化了连接上的管理,统一收口到一方,但是也引入了新的问题就是中间角色本身的高可用问题,如果这个中间代理故障了,那么就会影响整个集群的故障切换,因此陷入了为了保证存储高可用而需要保证中间代理高可用的循环。所以通常我们采用有高可用方案的稳定方案比如zookeeper,其中的ZAB算法是一个复杂的共识算法,保证了我们刚才说的唯一实例成为主库的问题。
当我们有海量的数据需要存储的时候,在存储架构上我们会想到纵向扩容与横向扩容,这两种方式也映射到了数据集群中的集中式存储与分片式存储两种模式。
集中式存储
刚才我们提到主从、主备都是数据集中式存储的架构,可以理解为主库和从库直接存储全量数据,我们拿全球人员信息这份数据举例,放到主从架构上那么主库和从库都需要存储全量的人员信息,因此集中式存储存在一个很根本的问题,它的集群存储能力受单机限制,这也是Mysql被称作单机架构存储的原因,虽然Mysql有分库分表等方案,但是会引入更多的问题,对于分库分表都是”能不用就不用“的态度,Mysql本身不具有Auto Sharding(动态拓展)的能力,这也是传统关系型数据库与分布式数据库的区别之一。
分片式存储
其实我们可以将全球人员信息按照其国籍进行划分,把一份数据切分成多份小数据,而后将不同的分片存储到不同的实例上去。分片式存储有个很重要的能力就是横向扩展,可以非常方便的通过增加实例来提高集群的存储能力,这也是符合云计算环境下的集群模式。
而数据分片引入的问题则是当我写一条数据的时候,应该写到哪里;读的时候,又从哪里去读,这就依赖数据分片时的一个分区键,比如我们刚才将全球人员按照国籍划分则国籍就是我们的分区键。而将读写请求分流的工作,又引出了不同的方式比如通过第三方代理,读写请求先发送到代理,统一由代理负责转发;或者由集群本身提供其中的某台实例来分配;甚至可以直接在客户端做。
这一小节我们讲了存储高可用下的集群模式,许多存储中间件都是使用了这些模式来保证存储高可用,因此掌握这些基本架构对于理解除了Redis以外的任何数据库集群方案都有很大帮助。下一节我们会回到Redis,看看Redis中更详细的方案。