redis 集群
redis集群是对redis的水平扩容,即启动N个redis节点,将整个数据分布存储在这个N个节点中,每个节点存储总数据的1/N。
shell
# 示例:由三主三从组成的 redis 集群
客户端
主1 主2 主3 # 每台主承接客户端三分之一请求和写入的数据
从1 从2 从3 # 当主挂掉后,从会自动替代为主,做到高可用解决了什么问题
shell
单台redis容量限制,如何进行扩容?继续加内存、加硬件么?
单台redis并发写量太大有性能瓶颈,如何解决?
redis3.0中提供了集群可以解决这些问题核心概念和特性
shell
# 概念
分片(Sharding):将数据按 **槽(slot)** 拆到多节点,共 **16384** 个槽(编号 **0~16383**),每个主节点负责其中一段。
主从复制:每个 **主节点** 可带 1 个或多个 **副本**;主故障时由集群协议在副本中 **选举提升**,**不依赖独立 Sentinel 进程**(与「主从 + 哨兵」架构不同)。
集群总线:节点间 **Gossip** 与 **PING/PONG** 做故障检测与配置传播。
# 特性
高可用:主节点故障时,从节点自动晋升,无需人工干预。
水平扩展:通过新增节点扩容存储和并发处理能力,支持动态增删节点。
分片存储:数据分散在多个节点,突破单节点内存、磁盘上限。
无中心节点:所有节点平等通信,无需中心协调节点,避免单点故障。集群配置
一个集群至少有3个主节点,因为新master的选举需要大于半数的集群master节点同意才能选举成功,
如果只有两个master节点,当其中一个挂了,是达不到选举新master的条件的。
选项--cluster-replicas 1表示我们希望为集群中的每个主节点创建一个从节点。
分配原则尽量保证每个主库运行在不同的ip,每个主库和从库不在一个ip上,这样才能做到高可用。
- 图解
shell
# 示例:由三主三从组成的 redis 集群
客户端
主1(端口:6379) 主2(端口:6380) 主3(端口:6381) # 每台主承接客户端三分之一请求和写入的数据
从1(端口:6389) 从2(端口:6390) 从3(端口:6391) # 当主挂掉后,从会自动替代主,做到高可用- 步骤
shell
# 创建 /opt/cluster 工作目录
mkdir /opt/cluster
# 创建配置文件
touch /opt/cluster/redis.conf # 内容为 redis.conf 默认配置
# 创建 主1(端口:6379)配置文件,在/opt/cluster目录创建 redis-6379.conf 文件,内容如下:
include /opt/cluster/redis.conf
daemonize yes
bind 192.168.200.129
dir /opt/cluster/
port 6379
dbfilename dump_6379.rdb
pidfile /var/run/redis_6379.pid
logfile "./6379.log"
cluster-enabled yes # 开启集群设置
cluster-config-file node-6379.conf # 设置节点配置文件
cluster-node-timeout 15000 # 设置节点失联时间,超过该时间(毫秒),集群自动进行主从切换
# 创建 主2(端口:6380)配置文件,在/opt/cluster目录创建 redis-6380.conf 文件,内容如下:
include /opt/cluster/redis.conf
daemonize yes
bind 192.168.200.129
dir /opt/cluster/
port 6380
dbfilename dump_6380.rdb
pidfile /var/run/redis_6380.pid
logfile "./6380.log"
cluster-enabled yes # 开启集群设置
cluster-config-file node-6380.conf # 设置节点配置文件
cluster-node-timeout 15000 # 设置节点失联时间,超过该时间(毫秒),集群自动进行主从切换
# 创建 主3(端口:6381)配置文件,在/opt/cluster目录创建 redis-6381.conf 文件,内容如下:
include /opt/cluster/redis.conf
daemonize yes
bind 192.168.200.129
dir /opt/cluster/
port 6381
dbfilename dump_6381.rdb
pidfile /var/run/redis_6381.pid
logfile "./6381.log"
cluster-enabled yes # 开启集群设置
cluster-config-file node-6381.conf # 设置节点配置文件
cluster-node-timeout 15000 # 设置节点失联时间,超过该时间(毫秒),集群自动进行主从切换
# 创建 从1(端口:6389)配置文件,在/opt/cluster目录创建 redis-6389.conf 文件,内容如下:
include /opt/cluster/redis.conf
daemonize yes
bind 192.168.200.129
dir /opt/cluster/
port 6389
dbfilename dump_6389.rdb
pidfile /var/run/redis_6389.pid
logfile "./6389.log"
cluster-enabled yes # 开启集群设置
cluster-config-file node-6389.conf # 设置节点配置文件
cluster-node-timeout 15000 # 设置节点失联时间,超过该时间(毫秒),集群自动进行主从切换
# 创建 从2(端口:6390)配置文件,在/opt/cluster目录创建 redis-6390.conf 文件,内容如下:
include /opt/cluster/redis.conf
daemonize yes
bind 192.168.200.129
dir /opt/cluster/
port 6390
dbfilename dump_6390.rdb
pidfile /var/run/redis_6390.pid
logfile "./6390.log"
cluster-enabled yes # 开启集群设置
cluster-config-file node-6390.conf # 设置节点配置文件
cluster-node-timeout 15000 # 设置节点失联时间,超过该时间(毫秒),集群自动进行主从切换
# 创建 从3(端口:6391)配置文件,在/opt/cluster目录创建 redis-6391.conf 文件,内容如下:
include /opt/cluster/redis.conf
daemonize yes
bind 192.168.200.129
dir /opt/cluster/
port 6391
dbfilename dump_6391.rdb
pidfile /var/run/redis_6391.pid
logfile "./6391.log"
cluster-enabled yes # 开启集群设置
cluster-config-file node-6391.conf # 设置节点配置文件
cluster-node-timeout 15000 # 设置节点失联时间,超过该时间(毫秒),集群自动进行主从切换
# 先关闭所有 redis
ps -ef | grep redis | awk -F" " '{print $2;}' | xargs kill -9
# 再启动 三主三从 redis 数据库
redis-server /opt/cluster/redis-6379.conf
redis-server /opt/cluster/redis-6380.conf
redis-server /opt/cluster/redis-6381.conf
redis-server /opt/cluster/redis-6389.conf
redis-server /opt/cluster/redis-6390.conf
redis-server /opt/cluster/redis-6391.conf
# 查看所有 redis 服务
ps -ef | grep redis
# 查看生成的配置文件
cd /opt/cluster && ll
# 将 6 个节点合成一个集群(--cluster-replicas 1:表示采用最简单的方式配置集群,即每1个主,配1个从,6个节点就形成了3主3从)
/opt/redis-6.2.1/src/redis-cli --cluster create --cluster-replicas 1
192.168.200.129:6379 192.168.200.129:6380 192.168.200.129:6381
192.168.200.129:6389 192.168.200.129:6390 192.168.200.129:6391
# 执行过程中输入 yes
# 连接集群节点,查看集群信息
redis-cli -c # 注意和之前的连接参数有点不同 redis-cli 命令后面多了一个 -c 参数,表示采用集群的方式连接,
cluster nodes # 查看集群信息,可查看到主子节点的关系
# 验证读写操作
redis-cli -c -h 192.168.200.129 -p 6379
set name alias # 明明在 6379 上操作的,但是请求被转发到了6380这个节点去处理了
get alias # 集群信息的读和写一定要是有 -c 参数连接 redis 数据库,否则如果 key 不在一个库上会查不到
# 插槽说明(集群中的数据是如何存储的)
# Redis集群内部划分了16384个slots(插槽),合并的时候,会将每个slots映射到一个master上面
# 数据库中的每个key都属于16384个slots中的其中1个,当通过key读写数据的时候,redis需要先根据
# key计算出key对应的slots,然后根据slots和master的映射关系找到对应的redis节点,key对应的数据就在这个节点上面。
redis主节点 槽位范围
master1(端口:6379) 约 [0-5460](5461 个槽,示意)
master2(端口:6380) 约 [5461-10922](与上一段不重叠,具体以 `cluster nodes` 为准)
master3(端口:6381) 约 [10923-16383]
slave1,slave2,slave3 从节点没有槽位,slave是用来对master做替补的- 故障恢复测试 如果主节点下线,从节点是否能够提升为主节点?注意:要等15秒
shell
# 下线 6379 主节点
redis-cli -c -h 192.168.200.129 -p 6379
shutdown
# 连接 6380 查看集群节点信息,可发现 6389 被提升为主,原 6379 会下线
redis-cli -c -h 192.168.200.129 -p 6380
cluster nodes
# 再启动下线的 6379
redis-server /opt/cluster/redis-6379.conf
redis-cli -c -h 192.168.200.129 -p 6379
cluster nodes # 结果是:6379变成了子节点,挂在了6389下面常见问题
- 如果某一段插槽的主从都宕机了,redis服务是否还能继续?
shell
# 这个时候要看 cluster-require-full-coverage 参数的值了
yes(默认值):整个集群都都无法提供服务了
no:宕机的这部分槽位数据全部不能使用,其他槽位正常