概述他们仨的关系:
- 我们来梳理一下redis主从,redis哨兵,redis集群的区别和关系。
- redis主从:是备份关系, 我们操作主库,数据也会同步到从库。 如果主库机器坏了,从库可以上。就好比你 D盘的片丢了,但是你移动硬盘里边备份有。
- redis哨兵:哨兵保证的是HA,保证特殊情况故障自动切换,哨兵盯着你的“redis主从集群”,如果主库死了,它会告诉你新的老大是谁。
- redis集群:集群保证的是高并发,因为多了一些兄弟帮忙一起扛。同时集群会导致数据的分散,整个redis集群会分成一堆数据槽,即不同的key会放到不不同的槽中。
- 主从保证了数据备份,哨兵保证了HA 即故障时切换,集群保证了高并发性。
1、redis高可用之主从复制
1)是什么?
- 也就是我们所说的主从复制,主机数据更新后根据配置和策略, 自动同步到备机的master/slaver机制,Master以写为主,Slave以读为主。
- Master既可以写也可以读,Slave只能读。
2)有什么用?
- 读写分离
- 容灾恢复
3)如何设置主从关系?
- 配从(库),不配主(库),可以通过 info replication 命令查看当前库的主从信息,默认为主库。
- 从库通过 slaveof 主库ip 主库端口 命令连接到主库(如果之前已经是其他redis的从库,那么会清除之前主库的旧数据)
- 从库可以通过 slaveof no one 将当前Redis与主Redis之间的同步停止,并将该从库转为主库。(不会清除之前的数据,转变主从角色关系)
4)主从关系的注意点
- 切入点问题?slave1、slave2是从头开始复制还是从切入点开始复制?比如从k4进来,那之前的123是否也可以复制?
- 答:从头开始复制;123也可以复制
- 从机是否可以写?set可否?
- 答:从机不可写,不可set,主机可写
- 主机shutdown后情况如何?从机是上位还是原地待命
- 答:从机还是原地待命(咸鱼翻身,还是咸鱼)
- 主机又回来了后,主机新增记录,从机还能否顺利复制?
- 答:能
- 其中一台从机down后情况如何?依照原有它能跟上大部队吗?
- 答:不能跟上,每次与master断开之后,都需要重新连接,除非你配置进redis.conf文件(具体位置:redis.conf搜寻#### REPLICATION ####)
5)复制原理
- 全量同步
- Redis全量复制一般发生在Slave初始化阶段,这时Slave需要将Master上的所有数据都复制一份。具体步骤如下:
- 从服务器连接主服务器,发送SYNC命令;
- 主服务器接收到SYNC命令后,开始执行BGSAVE命令生成RDB文件,并使用缓冲区记录此后执行的所有写命令;
- 主服务器BGSAVE执行完后,向所有从服务器发送快照文件,并在发送期间继续记录被执行的写命令;
- 从服务器收到快照文件后丢弃所有旧数据,载入收到的快照;
- 主服务器快照发送完毕后开始向从服务器发送缓冲区中的写命令;
- 从服务器完成对快照的载入,开始接收命令请求,并执行来自主服务器缓冲区的写命令;
- 增量同步
- Redis增量复制是指Slave初始化后开始正常工作时主服务器发生的写操作同步到从服务器的过程。
- 增量复制的过程主要是主服务器每执行一个写命令就会向从服务器发送相同的写命令,从服务器接收并执行收到的写命令。
- 注意:只要是重新连接master,一次完全同步(全量复制)将被自动执行。
6)复制的缺点
- 复制延时
- 由于所有的写操作都是先在Master上操作,然后同步更新到slave上,所以从Master同步到Slave机器有一定的延迟,当系统很繁忙的时候,延迟问题会更加严重,Slave机器数量的增加也会使这个问题更加严重。
2、redis监控协调之哨兵sentinel
1)是什么
-
反客为主的自动版,能够后台监控主机是否故障,如果主机故障了根据投票自动将从库转换为主库。
-
上面我们介绍了主从,从库作为一个“傀儡”,可以在需要的时候“顶上来”,”接盘“。我们配置的主从是为了”有备无患“,在主redis挂了之后,可以立马切换到从redis上,可能只需要花几分钟的时间,但是仍然是需要人为操作。假设主redis在晚上23点挂了,10分钟之后你接到电话,老板让你赶紧修复,于是你从被窝爬起来整,岂不是很头疼。假如你关机了,其他人又不知道服务器密码,那系统岂不是要停机一晚上?太可怕了。
-
这个时候redis sentinel 就派上用场了。sentinel 通常翻译成哨兵,就是放哨的,这里它就是用来监控主从节点的健康情况。客户端连接redis主从的时候,先连接 sentinel,sentinel会告诉客户端主redis的地址是多少,然后客户端连接上redis并进行后续的操作。当主节点挂掉的时候,客户端就得不到连接了因而报错了,从接替了主节点之后,客户端重新向sentinel询问主master的地址,然后客户端得到了[新选举出来的主redis],然后又可以愉快的操作了。
-
从上图中可以得出Sentinel其实就是Client和Redis之间的桥梁,所有的客户端都通过Sentinel程序获取Redis的Master服务。首先Sentinel是集群部署的,Client可以链接任何一个Sentinel服务所获的结果都是一致的。其次,所有的Sentinel服务都会对Redis的主从服务进行监控,当监控到Master服务无响应的时候,Sentinel内部进行仲裁,从所有的 Slave选举出一个做为新的Master。并且把其他的slave作为新的Master的Slave。最后通知所有的客户端新的Master服务地址。如果旧的Master服务地址重新启动,这个时候,它将被设置为Slave服务。
-
Sentinel 可以管理master-slave节点,看似Redis的稳定性得到一个比较好的保障。但是如果Sentinel是单节点的话,如果Sentinel宕机了,那master-slave这种模式就不能发挥其作用了。幸好Sentinel也支持集群模式,Sentinel的集群模式主要有以下几个好处:
- 即使有一些sentinel进程宕掉了,依然也可以进行redis集群的主备切换;
- 如果单点sentinel出错,或者是网络堵塞,那么将无法实现redis集群的主备切换(单点问题);
- 如果有多个sentinel,redis的客户端可以随意地连接任意一个sentinel来获得关于redis集群中的信息。
2)怎么玩(使用步骤)
- 1.调整结构,6379带着6380、6381
- 2.新建sentinel.conf文件,名字绝不能错
- 3.配置哨兵,填写内容
- sentinel mymaster(被监控数据库名字) 127.0.0.1 6379 1
- 上面最后一个数字1,表示主机挂掉后salve投票看让谁接替成为主机,得票数多少后成为主机。
- 4.启动哨兵
- redis-sentinel /sentinel.conf(上述目录依照各自的实际情况配置,可能目录不同)
- 5.正常主从演示
- 6.原有的master挂了
- 7.投票新选(主redis没选好之前,程序持续报错,主redis选好了,程序正常运行)
- 8.重新主从继续开工,info replication查查看
启动服务命令:
//启动redis主从服务
redis-server path/to/redis-sentinel/redis01.conf
redis-server path/to/redis-sentinel/redis02.conf
redis-server path/to/redis-sentinel/redis03.conf
//启动哨兵服务
redis-sentinel path/to/redis-sentinel/sentinel.conf //sentinel
3)哨兵有什么功能?
- 哨兵模式:sentinel,哨兵是 redis 集群中非常重要的一个组件,主要有以下功能:
- 集群监控:负责监控 redis master 和 slave 进程是否正常工作。
- 消息通知:如果某个 redis 实例有故障,那么哨兵负责发送消息作为报警通知给管理员。
- 故障转移:如果 master node 挂掉了,会自动转移到 slave node 上。
- 配置中心:如果故障转移发生了,通知 client 客户端新的 master 地址。
4)哨兵的内部工作机制?
- 哨兵用于实现 redis 集群的高可用,本身也是分布式的,作为一个哨兵集群去运行,互相协同工作:
- 故障转移时,判断一个 master node 是否宕机了,需要大部分的哨兵都同意才行,涉及到了分布式选举。
- 即使部分哨兵节点挂掉了,哨兵集群还是能正常工作的。
- 哨兵通常需要 3 个实例,来保证自己的健壮性。
- 哨兵 + redis 主从的部署架构,是不保证数据零丢失的,只能保证 redis 集群的高可用性。
- 对于哨兵 + redis 主从这种复杂的部署架构,尽量在测试环境和生产环境,都进行充足的测试和演练。
5)问题:如果之前挂了的master重启回来,会不会双master冲突?
- 答: 不会,原master,变成slave
3、redis 集群高并发之cluster
1)为什么出现cluster?
出现的主要原因就两点:既解决了并发问题,又解决了扩容问题;
1. 并发问题:
- 上面我们了解了redis主从+ sentinel 哨兵模式,只是保证了数据备份以及高可用,目前为止我们的程序一直都是向1台redis写数据,其他的redis只是备份而已。实际场景中,单个redis节点可能不满足要求,因为:
- 1.单个redis并发有限。
- 2.单个redis接收所有的数据,最终会导致内存太大,内存太大会导致rdb文件过大,从很大的rdb文件中同步和恢复数据会很慢。
2. 扩容问题:
- 熟知的扩容方式有两种:一种是垂直扩容,一种是水平扩容。
- 垂直扩容表示通过加内存方式来增加整个缓存体系的容量比如将缓存大小由2G调整到4G,这种扩容不需要应用程序支持;
- 水平扩容表示表示通过增加节点的方式来增加整个缓存体系的容量比如本来有1个节点变成2个节点,这种扩容方式需要应用程序支持。
- 垂直扩容看似最便捷的扩容,但是受到机器的限制,一个机器的内存是有限的,所以垂直扩容到一定阶段不可避免的要进行水平扩容。
- Redis Sentinel 水平扩容一直都是程序猿心中的痛点,因为水平扩容牵涉到数据的迁移。迁移过程一方面要保证自己的业务是可用的,另方面要保证尽量不丢失数据所以数据能不迁移就尽量不迁移。针对这个问题,Redis Cluster就应运而生了。
2)是什么?
-
Redis-Cluster采用无中心结构,每个节点保存数据和整个集群状态,每个节点都和其他所有节点连接。
-
集群中至少应该有奇数个节点,所以至少有三个节点,每个节点至少有一个备份节点
-
其结构特点:
- 所有的redis节点彼此互联(PING-PONG机制),内部使用二进制协议,优化传输速度和带宽。
- 节点的fail,是通过集群中超过半数的节点检测失效时才生效。
- 客户端与redis节点直连,不需要中间proxy层。客户端不需要连接集群所有节点,连接集群中任何一个可用节点即可。
- redis-cluster把所有的物理节点映射到[0-16383]slot上(不一定是平均分配),cluster 负责维护node<->slot<->value。
- Redis集群预分好16384(2^14)个桶,当需要在 Redis 集群中插入 key-value 时,根据 CRC16(key) mod 16384的值,决定将一个key放到哪个桶中。
3)cluster工作原理
1. redis cluster节点分配
①. 节点间的哈希槽的分配
- 现在我们是三个主节点分别是:A, B, C 三个节点,它们可以是一台机器上的三个端口,也可以是三台不同的服务器。那么,采用哈希槽 (hash slot)的方式来分配16384个slot槽的话,它们三个节点分别承担的slot 区间是:
- 节点A覆盖0-5460;
- 节点B覆盖5461-10922;
- 节点C覆盖10923-16383;
②. 保存和获取数据:
-
- 存入一个值:按照redis cluster哈希槽的算法: CRC16(‘key’) % 16384 = 6782。 那么就会把这个key 的存储分配到 B 上了。
-
- 获取一个值:当我连接(A,B,C)任何一个节点想获取这个key时,也通过这个算法路由到B节点上获取数据。
③. 新增/删除一个主节点:
- 新增一个节点D,redis cluster的这种做法是从其他节点各拿取一部分slot到D上,我会在接下来的实践中实验。大致就会变成这样:
- 节点A覆盖1365-5460
- 节点B覆盖6827-10922
- 节点C覆盖12288-16383
- 节点D覆盖0-1364,5461-6826,10923-12287
- 同样删除一个节点也是类似,移动完成后就可以删除这个节点了。
2. Redis Cluster主从模式
-
1.主从的重要性:redis cluster 为了保证数据的高可用性,引入了主从模式,一个主节点对应一个或多个从节点,主节点提供数据存取,从节点只负责数据备份,当这个主节点挂掉后,就会有这个从节点选取一个来充当主节点,从而保证集群不会挂掉
-
2.不加入从节点的危害:上面那个例子里, 集群有ABC三个主节点, 如果这3个节点都没有加入从节点,如果B挂掉了,我们就无法访问整个集群了。A和C的slot也无法访问。
-
3.举例说明:
- 所以我们在集群建立的时候,一定要为每个主节点都添加了从节点, 比如像这样, 集群包含主节点A、B、C, 以及从节点A1、B1、C1, 那么即使B挂掉系统也可以继续正确工作。
- B1节点替代了B节点,所以Redis集群将会选择B1节点作为新的主节点,集群将会继续运行。 当B重新开启后,它就会变成B1的从节点。
- 不过需要注意,如果节点B和B1同时挂了,Redis集群就无法提供服务了。