采用多台服务器连接的方案,避免单台服务器宕机导致服务不可用问题。
master(主节点):写,收集数据;
slave (从节点):读,提供数据(写数据禁止);
需要解决的问题:数据同步,需要将master中的数据复制到slave中。
1. 建立连接;(slave连接master)
a. 命令行连接
## 在从节点执行,连接主节点
slaveof masterip masterport
b. 配置文件连接
## 在从节点的配置文件中,进行下面的配置
slaveof masterip masterport
2. 数据同步;master同步slave,包括全量复制 + 部分复制两个部分。
全量复制通过 RDB 进行全量复制后同步,部分复制是将 bgsave 过程中存入复制缓冲区的指令同步给从节点。
在从节点连接上主节点后,数据同步过程会自动执行。
注意,当master数据量很大,bgsave 占用时间过长,导致复制缓冲区指令溢出,则最先存入复制缓冲区的指令将会丢失,后续进行部分复制时发现数据丢失,则redis会重新进行全量复制,导致服务器陷入死循环。因此数据同步尽量避开流量高峰期。
复制缓冲区大小设置:
repl-backlog-size 1mb
3. 命令传播
数据同步之后,后续是通过命令传播来保证数据一致性的。命令传播阶段也可能出现全部复制或部分复制,如网络中断导致数据长时间未同步。
master 接收写指令后,会将指令以字节的形式存储在复制缓冲区(FIFO队列)中,复制缓冲区由偏移量(offset) + 字节值组成,通过offset区分不同slave的数据传播差异。master 记录当前缓冲区的 offset,slave 记录自己接收到数据的 offset。
数据同步 + 命令传播 详细版:
心跳机制:
进入命令传播阶段,master 与 slave 需要进行信息交换,使用心跳机制进行维护,实现双方连接保持在线。
master 心跳:ping 指令,用于判断 slave是否在线;
slave 心跳:replconf ack (offset),汇报自己的 offset,并获取最新的同步数据;同时判断 master 是否在线。
频繁的全量复制
缓冲区过小,导致经常进行全量复制,可修改复制缓冲区大小;
频繁的网络中断
a. master CPU过高,或者 slave 频繁下线。
slave 接收到了大量慢查询,如 keys,master 发送心跳时 slave 无响应,导致 master 频繁发送连接请求,CPU占用过高。可设置合理的超时时间(repli-timeout),确认是否释放 slave。
b. slave 与 master 连接断开
master 发送 ping 指令频度较低,master 设置的超时时长过短,ping指令存在丢包等。
数据不一致
多个 slave 数据不同步。可能是网络信息不同步,导致数据发送有延时。
可优化主从间的网络环境,监控主从节点延时(查看offset)。
哨兵是一个分布式系统,用来监控 master 的运行情况,并在 master 宕机以后选择一个 slave 作为 master。哨兵也是一台 redis 服务器,只是不对外提供数据服务。哨兵配置数量为通常为单数,保证投票时不会打平。
创建哨兵的配置文件:
port 26379
dir /tmp
# 表示监控的主节点,2 表示如果有2个哨兵认为主节点宕机则判定为宕机
sentinel monitor mymaster 127.0.0.1 6379 2
# 监控时发现宕机 30s 则被判定为宕机,需要投票选择新的主节点
sentinel down-after-milliseconds mymaster 30000
# 数据同步的线程数
sentinel parallel-syncs mymaster 1
# 超过 180s 算同步超时
sentinel failover-timeout mymaster 180000
分别启动1 个 master、2 个 slave、1 个 sentinel,然后将 master 关闭,日志打印情况如下。可以看到哨兵监测到 master 宕机以后选择了 slave 6381 作为master,并完成了master 与 slave 之间的连接和同步。重新启动 6379 以后,该节点变成了 slave。
master 6379:
slave 6380 :
slave 6381:
sentinel 26379:
重新启动 6379:
监控阶段
哨兵启动后会向 master、slave 获取状态信息,并同步给其他哨兵。
通知阶段
哨兵不断向 master、slave 发送心跳确认节点健康状态,收到正常状态返回后同步给其他哨兵。
故障转移阶段
作用:分散单台服务器的访问及存储压力,并降低宕机带来的业务风险。
方式:将各个 master 相连,对外呈现出单机的效果。
集群的每个master都会被分配一段槽编号,数据存储时通过算法设计,将要存储的 key 计算出一个槽值,再放入对应的 master(类似于数据库分库分表操作)。每台 redis 服务器都会存储自己的槽编号以及其他服务器的槽编号,根据此编号进行数据存储。
配置三套一主一从建立集群,端口分别为主(从)—— 6379(6382)、6380(6383)、6381(6384)。
1. 集群配置
redis-6379.conf 配置文件中添加以下配置,然后复制成6份:
cluster-enabled yes #开启集群模式。标识该节点是集群的一部分
cluster-config-file node-6379.conf #指定配置文件名
cluster-node-timeout 10000 #节点连接超时多久被认为断线
查看启动情况:
2. 集群连接
redis 5.0.0 以上版本使用 redis-cli 进行集群连接(以下版本使用 redis-trib.rb 太难装了)。其中 --cluster-replicas 1 表示集群连接是一拖一模式,即一个主节点带一个从节点,create 后面则是所有要互连的主从节点IP端口,前半部分是主节点,后半部分是从节点:
redis-cli --cluster create 127.0.0.1:6379 127.0.0.1:6380 127.0.0.1:6381 127.0.0.1:6382 127.0.0.1:6383 127.0.0.1:6384 --cluster-replicas 1
执行完以后可以看到 logs 文件夹下已经自动生成了 node-6379.conf 配置文件。集群模式下,主节点下线,从节点将在连接超时后自动晋级为主节点,后续主节点上线后,将重新变成从节点。
集群模式下,需要使用 redis-cli -c 参数,否则,如果key hash 后计算出的槽值不属于当前连接的主节点,将无法set,-c 之后将会自动重定向到对应的主节点:
在 redis 作为数据库缓存的情况下,当 redis 刚启动时,由于 redis 中没有数据,如果此时请求量较大,容易对数据库造成压力。
缓存预热就是将一些高频访问的数据提前加载到 redis 中,避免大量请求同时访问数据库。实际操作过程可以使用脚本导入。
缓存雪崩是指系统在运行过程中短时间内出现大量过期 key,redis 无数据向数据库获取数据,从而对数据库造成压力。数据库无法及时响应,从而 redis 请求堆积,数据库请求激增而崩溃,接着 redis 崩溃,应用服务器崩溃。重启无法解决上述问题,因为雪崩的本质是由于 redis 中无缓存数据可用,必须从数据库获取。
解决方式:
与缓存雪崩不同的是,缓存击穿是指某个时刻单个高热 key 过期,导致大量请求同时访问数据库中的同一数据,从而对数据库造成压力。
解决方式与雪崩类似:
缓存穿透通常是短时间内出现大量未命中 key,而这些数据在数据库中也不存在。由于获取不到值这些 key 访问之后也不会存储在 redis 中,下次请求时还将继续请求数据库,导致数据库崩溃。
解决方式: