redis主从同步的原理,哨兵和集群的区别
# Redis主从复制
单节点的Redis服务我们支起来了,但是实际应用中,单节点的问题会会很明显:数据备份问题和数据体量较大时的性能问题。
Redis已经为我们提供了解决方案,就是Redis主从模式。
主从模式指的是使用一个Redis实例作为主机,其余的实例作为备份机。
主机和从机的数据完全一致,主机支持数据的写入和读取等各项操作,而从机则只支持与主机数据的同步和读取,也就是说,客户端可以将数据写入到主机,由主机自动将数据的写入操作同步到从机。
主从模式很好的解决了数据备份问题,并且由于主从服务数据几乎是一致的,因而可以将写入数据的命令发送给主机执行,而读取数据的命令发送给不同的从机执行,从而达到读写分离的目的。
# Redis的主从复制机制
当一个 master 实例和一个 slave 实例连接正常时, master 会发送一连串的命令流来保持对 slave 的更新,以便于将自身数据集的改变复制给 slave :包括客户端的写入、key 的过期或被逐出等等。 当 master 和 slave 之间的连接断开之后,因为网络问题、或者是主从意识到连接超时, slave 重新连接上 master 并会尝试进行部分重同步:这意味着它会尝试只获取在断开连接期间内丢失的命令流。 当无法进行部分重同步时, slave 会请求进行全量重同步。这会涉及到一个更复杂的过程,例如 master 需要创建所有数据的快照,将之发送给 slave ,之后在数据集更改时持续发送命令流到 slave 。
搭建Redis主从复制环境 BB了这么多,下面来搭建一下Redis主从复制模式环境。 主从模式的配置主要的配置点有两个:
# Redis Sentinel 哨兵
因为每个客户端连接Redis实例的时候都是指定了ip和端口号的,如果所连接的Redis实例因为故障下线了,而主从模式也没有提供一定的手段通知客户端另外可连接的客户端地址,因而需要手动更改客户端配置重新连接。 另外,主从模式下,如果主节点由于故障下线了,那么从节点因为没有主节点而同步中断,因而需要人工进行故障转移工作。
Redis Sentinel架构提供了解决方案。
Sentinel是哨兵的意思,Redis Sentinel,顾名思义,Redis的哨兵,也就是监控的意思。
Redis Sentinel为Redis提供高可用性。在实践中,这意味着使用Sentinel你可以创建一个Redis部署,在没有人为干预的情况下抵抗某些类型的故障-自动转移故障。
Redis Sentinel还提供其他附带任务,如监控、通知,并充当客户端的配置提供者。
- 监控(Monitoring): Sentinel 会不断地检查你的主服务器和从服务器是否运作正常。
- 提醒(Notification): 当被监控的某个 Redis 服务器出现问题时, Sentinel 可以通过 API 向管理员或者其他应用程序发送通知。
- 自动故障迁移(Automatic failover): 如果一个主服务器不能正常工作,哨兵可以启动一个故障转移过程,其中一个副本被提升为主服务器,其他额外的副本被重新配置为使用新的主服务器,并且使用Redis服务器的应用程序被告知在连接时使用的新地址。
- 配置中心(Configuration provider):哨兵充当客户端服务发现:客户端连接到哨兵,以询问负责给定服务的当前Redis主服务器的地址。如果发生故障转移,哨兵将报告新地址。
# Sentinel故障转移原理
Redis主节点 192.168.2.20(以下简称20,下面的IP地址均如此简称)因故障下线,Redis Sentinel进行故障转移的过程:
- 某个Sentinel节点(假设是30这个Sentinel节点)发送监测消息给20,如果在指定时间内收不到回复,该Sentinel认为20主节点已经下线
- 30这个Sentinel节点发消息给31/32这两个Sentinel,询问他们是否认为 20 master 已经下线
- 31/32这两个哨兵收到消息后也会监测20 Redis主节点,如果它也认为master下线,则回复30 Sentinel节点(就是第2步中的询问者):“我也认为master已经下线”
- 当30节点最先收到超过2(配置文件中配置的数目和当前Sentinel节点集合数的一半,这里两个数目的较大值)的Sentinel节点回复说当前主节点已下线,那么其就会对主节点进行故障转移工作
- 向某个从节点(前面的实验选中的从节点为192.168.2.21)发送 replicaof no one,使其成为新的主节点
- Sentinel哨兵向其余22/23节点发送replicaof 192.168.2.21 9736命令,使22/23两个Redis节点成为21的从节点
- Sentinel选出新的master之后,仍然会继续监控之前下线的20节点,如果其重新上线,那么Sentinel哨兵向其发送replicaof 192.168.2.21 9736命令,也成为了新主节点的从节点
哨兵之间通信: redis pub/sub 机制
# Redis Cluster 集群
# Redis集群原理
Redis集群中数据是和槽(slot)挂钩的。
- 其总共定义了16384个槽,所有的数据根据一致性哈希算法会被映射到这16384个槽中的某个槽中;
- 另一方面,这16384个槽是按照设置被分配到不同的Redis节点上的,比如启动了三个Redis实例:Redis-A,Redis-B和Redis-C,这里将0-5460号槽分配给Redis-A,将5461-10922号槽分配给Redis-B,将10923-16383号槽分配给Redis-C(总共有16384个槽,但是其标号类似数组下标,是从0到16383)。
- 也就是说数据的存储只和槽有关,并且槽的数量是一定的,由于一致性Hash算法是一定的,因而将这16384个槽分配给无论多少个Redis实例,对于确认的数据其都将被分配到确定的槽位上。
Redis集群通过这种方式来达到Redis的高效和高可用性目的。
一致哈希算法根据数据的key值计算映射位置时和所使用的节点数量有非常大的关系。
一致哈希分区的实现思路是为系统中每个节点分配一个token,范围一般在0~2^32,这些token构成一个哈希环,数据读写执行节点查找操作时,先根据key计算hash值,然后顺时针找到第一个大于等于该hash值的token节点,需要操作的数据就保存在该节点上。
一致哈希分区存在如下问题:
- 加减节点会造成哈希环中部分数据无法命中,需要手动处理或忽略这部分数据;
- 当使用少量节点时,节点变化将大范围影响环中数据映射,因此这种方式不适合少量节点的分布式方案;
- 普通的一致性哈希分区在增减节点时需要增加一倍或减去一半节点才能保证数据和负载的平衡。
Redis的应对方案是,使用了虚拟槽来处理分区时节点变化的问题,也即将所有的数据映射到16384个虚拟槽位上,当Redis节点变化时数据映射的槽位将不会变化,并且这也是Redis进行节点扩张的基础。