主从复制
首先为什么需要主从复制呢?就是即使redis的写速度非常快,但是也会产生性能瓶颈,特别是在读压力下,所以就需要配置从机器来以读为主。然后的话,与哨兵模式配合,可以实现高可用。 主从复制的话,复制类型可分为全量同步和增量同步。全量同步的话,一般是发生在salve的初始阶段,slave需要将master上的数据复制一份。具体步骤的话,slave连接master,发送PSYNC命令,master接收到PSYNC命令后,执行BGSAVE命令产生RDB文件,在这过程中间将来的写命令写入缓冲区(所以是非阻塞的),rdb文件生成之后,向所有slave发送rdb文件,slave收到文件后,丢弃所有的旧数据,载入收到的数据。slave完成数据的载入后,就可以接收命令了,之后进行的就是增量同步,执行来自master缓冲区的写命令,同时,开始接受用户的读请求。
哨兵模式
(监控,通知,故障转移) 嗯。首先就是哨兵会不断的检测master和slave直接是否运行正常,如果当监控的某个节点出现问题,哨兵可以通过API向应用程序发送通知。然后就是故障转移了,就是当一个master不能正常工作时,哨兵会开始一次自动故障转移操作,它会将失效master的一个slave提升为master,并让失效master和其他的slave成为这个新master的slave,然后当客户端想去连接失效的master时,会向客户端返回这个新master的地址,这样就可以使用新master代替失效的master。 工作原理的话就是哨兵会每一秒会发送一个ping给master、slave、和其他哨兵,然后来判断对方的状态,如果在一定时间内ping连接无效,则认为对方为主观下线。然后向其他哨兵询问是否也判断那个服务器下线,当超过一半数量的哨兵认为服务器下线,则将那个服务器视为客观下线。如果是master被视为客观下线,哨兵间就会商量然后选出一个主哨兵进行故障转移工作。 (商量规则是使用了raft算法,需要的话可以说)
集群
一台redis服务器所能够容纳的数据量的一定的,当我们需要支撑更大数据量的缓存时,就得扩容更多的master节点,形成集群,来进行分布式的存储,同时也提高系统的高可用性。既然是分布式的话,那我们就要去考虑怎么对key进行一个路由(分片),一种是客户端路由(SDK),一种是服务端路由(Proxy)。
- 客户端路由
首先是客户端路由Redis Cluster,集群中有16384个槽,好像是2的14次方个槽,当集群正常工作时,集群中的每个master都会负责一部分的槽,当客户端进行数据写入的时候,会进行hash然后取模,映射到某个master负责的槽,然后由这个master负责为这个key提供服务,至于哪个master节点负责哪个槽,这是可以由用户指定的,也可以在初始化的时候自动生成。 这里面就有问题了,就是客户端怎么知道哪个槽是由哪个redis实例负责的? 就是集群中的redis会向其他实例传播自己负责的hash槽有哪些,这样一来每台redis实例就可以记录有hash槽与实例的映射关系,同时客户端也会缓存一份在本地中,就可以知道这个槽要去找哪个实例。redis间的通讯,包括可以表现在redis实例的增加和删除,增加和删除之后,槽位的映射肯定是会发送变化的,也是需要实例之间的通讯去改变槽位的变动,但这个时候其实客户端是不感知的,它还是会去原来的实例上找,这里就分为两种情况了,如果数据已经迁移完毕,原来的实例会返回moved命令,告诉客户端要去新的实例上找,客户端收到消息后,就知道要去请求新的实例了,同时也会更新客户端的槽位与实例映射的缓存。如果还没迁移完毕,原来的实例会返回客户端ask命令,让客户端去新实例找,但是客户端不会更新本地缓存。
- 服务端路由
还有一种是基于服务端路由的方式,有个代理层Proxy专门对接客户端的请求,然后再转发到Redis集群进行处理,有现在比较流行的Codis,具体的这块还不是很了解,待笔者学到再来补充。TODO
