Redis 7 + ACL 单节点、主从、哨兵、集群构建方法

摘要

redis安装

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# 下载到指定目录
mkdir -p /usr/local/soft
wget https://download.redis.io/releases/redis-7.4.7.tar.gz -P /usr/local/soft

# 解压
cd /usr/local/soft
tar -zxvf redis-7.4.7.tar.gz

# 编译
sudo yum install gcc gcc-c++ -y
cd redis-7.4.7
# 编译,会将编译好的可执行文件放在src目录下
make
# 编译安装到指定目录,redis相关命令会被安装到 $(pwd)/build_dir/bin目录下
mkdir build_dir
make install PREFIX=$(pwd)/build_dir

# 编辑配置文件,不建议在原有配置文件中修改,可以新建一个配置文件
cp redis.conf redis-6379.conf
vim redis-6379.conf #见下面的配置信息

# 加入环境变量 /etc/bashrc,注意这里要是单引号,否则 $PATH 会被解析
echo 'export PATH=$PATH:/usr/local/soft/redis-7.4.7/build_dir/bin' >> /etc/bashrc
source /etc/bashrc

# 验证
redis-cli --version
# 输出
redis-cli 7.4.7

单节点

  • redis-6379.conf 的主要配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
# 端口,默认 6379
port 6379

# 后台启动,默认 no
daemonize yes

# yes: 当没有 bind / requirepass / ACL 时,只允许本机访问
# no: 允许任意访问
# 这里会启用ACL,所以设置为 yes,默认 yes
protected-mode yes

# 注释掉bind,绑定的是自己机器网卡的ip,如果有多块网卡可以配多个ip,代表允许客户端通过机器的哪些网卡ip去访问,内网一般可以不配置
#bind 127.0.0.1
# 可以配置为,本机IP 内网IP 外网IP
# bind 127.0.0.1 10.250.0.103 18.163.188.20

# 关闭rdb快照,因为会启用混合持久化,所以这里不需要开启rdb快照
# 这里只是关闭了自动快照,如果手动执行了 bgsave 命令,还是会生成一个 dump.rdb 文件
save ""

# 设置dir路径,redis日志、aof和rdb文件都会生成在这个路径下,需要提前创建好这个目录
dir /usr/local/soft/dir-redis7/6379

# 开启aof,实际上只需要开启这个配置,以下aof相关配置默认即可,默认 no
# 开启aof,重启redis时,会主动加载 appendonlydir 下的 相关 aof文件进行数据恢复
# 生成环境必须开启
appendonly yes

# aof文件名称,默认 appendonly.aof
appendfilename "appendonly.aof"
# aof文件保存目录,基于为当前dir路径,默认值就是 appendonlydir
# redis6+会生成3个文件,每个文件都以 appendfilename 配置的文件名称开头,如下:
# appendonly.aof.N.base.rdb:每次触发aof重写时都会生成这个文件,N是当前aof文件序号,base.rdb是当前rdb文件
# appendonly.aof.N.incr.aof:记录每个写操作命令
# appendonly.aof.manifest:记录 base.rdb 和 incr.aof 文件的最新索引(N)
appenddirname "appendonlydir"
# aof将数据fsync到磁盘的策略,默认即可,表示每秒一次,故障时最多会丢失一秒的数据,默认 everysec
appendfsync everysec

# 自动触发aof重写需要满足如下条件,如果需要手动触发aof重写,可以执行 BGREWRITEAOF 命令
# 重写时会删除旧的 appendonly.aof.N.base.rdb(RDB 快照) 文件,生成新的 appendonly.aof.N+1.base.rdb
# 当 AOF 重写完成后,当前的 appendonly.aof.N.incr.aof 会封存,Redis 会新建一个 appendonly.aof.N+1.incr.aof 来继续记录写命令
# 而此时 appendonly.aof.manifest(索引文件) 也会记录最新的 appendonly.aof.N.incr.aof 和 appendonly.aof.N.base.rdb
# aof文件至少要达到64M才会自动重写,文件太小恢复速度本来就很快,重写的意义不大,默认即可,默认 64mb
auto-aof-rewrite-min-size 64mb
# aof文件自上一次重写后文件大小增长了100%则再次触发重写,默认 100
auto-aof-rewrite-percentage 100

# 开启混合持久化,4.0以后版本支持,需要先开启aof,默认 yes
# 开启混合持久化后,appendonly.aof.N.base.rdb 的文件后缀就是 rdb,否则是 aof
aof-use-rdb-preamble yes
# 防止 AOF 意外截断导致 Redis 起不来,默认 yes
aof-load-truncated yes

# pid文件路径,默认 /var/run/redis_6379.pid
pidfile "redis_6379.pid"

# 日志文件名称,默认 ""
logfile "6379.log"

# 指定最大内存,单位bytes,这里设置4G
# 如果不设置最大内存,redis会默认为物理内存,达到上限时会频繁与磁盘发生交换,使redis性能急剧下降
maxmemory 4294967296
# 达到最大内存时的清除策略,推荐 allkeys-lru,淘汰很久没被访问过的数据,基于最近一次的访问时间
# volatile-lru: 只会淘汰「设置了过期时间」的 key
# allkeys-lru: 淘汰最久没有被访问过的数据,最近最久没被访问的
# allkeys-lfu: 淘汰最不经常被访问过的数据,访问次数最少的
# noeviction: 不淘汰,默认
maxmemory-policy allkeys-lru

# 慢查询日志
# 单位微妙,这里表示10毫秒,即超过10毫秒的操作都会记录下来
slowlog-log-slower-than 10000

# 设置慢查询日志记录保存数量,如果数量已满会删除最早的记录
slowlog-max-len 1024

# 性能优化
# Redis 用多少附加线程来处理网络 I/O(不是执行命令),推荐:核心数 / 2,默认为1,超过 8 几乎就没有明显收益了
io-threads 4
# 多线程同时用于 读取 + 写回, no :多线程仅用于 写回客户端
# 推荐>=4核才开启,否则开了反而更慢
io-threads-do-reads yes
# 操作系统 TCP 层的健康检测,默认值300,这里如果 60 秒内没有数据流动,内核会发送探测包,判断连接是否活着
tcp-keepalive 60
# 客户端在 "多少秒不操作" 就强制断开,0:永不超时(推荐),默认 0
# 因为有 tcp-keepalive 60,会每 60 秒检测一下对面还在不在,如果不在,Redis 会主动断开该连接,所以不会导致连接永不释放
timeout 0
# 最大客户端连接数,默认 10000
maxclients 10000

# 禁用危险命令,根据需要自行添加,redis6+ 支持在 acl 文件中为不同的用户禁用危险命令
rename-command FLUSHALL ""
rename-command FLUSHDB ""
# rename-command SHUTDOWN ""
# rename-command CONFIG ""
# rename-command KEYS ""
# rename-command SAVE ""
# rename-command BGSAVE ""
# rename-command DEBUG ""
# rename-command EVAL ""
# rename-command SCRIPT ""

# 开启 ACL 文件
aclfile /usr/local/soft/redis-7.4.7/users.acl
  • Redis 7 支持的淘汰策略

策略 是否只淘汰带 TTL 的 key 淘汰规则 说明
noeviction ❌ 不淘汰 不删任何 key 内存满了直接返回错误(默认)
allkeys-lru ❌ 所有 key 最近最久未使用 ✅ 最常用
allkeys-lfu ❌ 所有 key 访问频率最少 ✅ 热点场景最好
allkeys-random ❌ 所有 key 随机删除 ❌ 很少用
volatile-lru ✅ 只淘汰有 TTL 的 最近最久未使用 你之前用的
volatile-lfu ✅ 只淘汰有 TTL 的 访问频率最少 较少使用
volatile-random ✅ 只淘汰有 TTL 的 随机删除 很少用
volatile-ttl ✅ 只淘汰有 TTL 的 TTL 最小(马上过期的) 特殊场景用
  • users.acl 文件: 该文件不支持添加注释,所以使用时需要去掉如下注释行,关于ACL的详细说明,可以参考 Redis 7 + ACL 简介

1
2
3
4
# 关闭默认用户,禁止匿名访问
user default off
# 超级管理员
user admin on ~* &* +@all >123456
  • redis 服务启动与关闭

1
2
3
4
5
6
7
8
9
10
11
12
# 启动服务
redis-server redis-6379.conf
# 登录服务,本机访问可以省略 -h -p
redis-cli -h 127.0.0.1 -p 6379 --user admin --pass 123456
# 或者
redis-cli -u redis://admin:123456@127.0.0.1:6379

# 关闭服务
# shutdown == shutdown save
redis-cli -u redis://admin:123456@127.0.0.1:6379 shutdown
# 关闭服务,不保存数据,已经开了 AOF(尤其是 everysec) 的场景下,可以
redis-cli -u redis://admin:123456@127.0.0.1:6379 shutdown nosave
场景 推荐命令
正常下线(生产) shutdown nosave
已开 AOF shutdown nosave
数据很大 shutdown nosave
单机调试 shutdown
确定要生成快照 shutdown save
强制杀死(redis卡死) kill -9(极端情况)

单节点优点

  • 单机部署简单方便

单节点缺点

  • 不保证数据的可靠性,不适用于数据可靠性要求高的场景

  • 单点故障导致无法提供服务,或者硬盘损坏导致数据丢失

  • redis单节点最大qps为10w(取决于单核cpu的处理能力),超过这个qps就需要做前端限流

主从

  • 规划

1
2
3
master 10.250.0.235
slave1 10.250.0.58
slave2 10.250.0.36
  • 主从配置时,主节点不需要做任何修改

  • 从节点配置文件增加同步主节点信息,其余配置与主节点相同

1
2
3
4
5
6
7
8
9
# 指定主节点,从节点会从主节点同步数据,这里10.250.0.235 6379是主节点的ip和端口号
replicaof 10.250.0.235 6379

# 配置从节点只读,默认开启,避免数据写入从节点导致主从数据不一致
replica-read-only yes

# 如果主节点开启了ACL认证,则从节点需要设置主节点的认证信息,这里设置为管理员帐号
masteruser admin
masterauth 123456
  • 此时启动从节点redis-server redis-6379.conf,会自动从主节点同步数据,同步前如果从节点已经有数据,则会先清除原有数据再进行同步

  • 主节点接收到从节点的同步请求后,会通过bgsave将内存数据dump到rdb文件中并传递给从节点

  • 主节点生成rdb文件并传递给从节点期间会继续处理客户端的请求,并将这部分数据缓存到内存中,待从节点接收到主节点发过来的rdb文件并完成内存加载后,主节点会将这部分缓存在内存中的数据发送给从节点

  • 从节点相当于主节点的备份,主节点挂了,从节点不能自动切换为主节点,如果需要自动切换,可以使用哨兵或者集群部署方式

  • 此时登录master的redis并执行info replication命令

1
2
3
4
5
6
7
8
9
10
11
12
13
# Replication
role:master # 表示当前是从节点
connected_slaves:1 # 从节点数量
slave0:ip=10.250.0.36,port=6379,state=online,offset=56,lag=1 # 从节点信息
master_failover_state:no-failover # 主节点切换状态,无
master_replid:93e564c18d27418e52fc40254c764d76c1dc3f67 # 主节点的复制ID
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:56 # 主节点复制的偏移量
second_repl_offset:-1
repl_backlog_active:1 # 是否开启复制回放
repl_backlog_size:1048576 # 复制回放缓冲区大小
repl_backlog_first_byte_offset:1 # 复制回放缓冲区第一个字节的偏移量
repl_backlog_histlen:56 # 复制回放缓冲区历史长度
  • 此时登录从节点的redis并执行info replication命令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# Replication
role:slave # 表示当前是从节点
master_host:10.250.0.235 # 主节点的ip
master_port:6379 # 主节点的端口
master_link_status:up # 主从节点连接状态,up 表示已经连接上主节点
master_last_io_seconds_ago:6 # 主从节点最后一次io操作时间
master_sync_in_progress:0 # 主从节点是否正在同步数据,0表示已完成
slave_read_repl_offset:112 # 从节点已经读取的复制偏移量
slave_repl_offset:112 # 从节点已经写入的复制偏移量
slave_priority:100 # 从节点的优先级
slave_read_only:1 # 从节点是否只读
replica_announced:1 # 从节点是否被其他节点所代理
connected_slaves:0 # 从节点所代理的从节点数量
master_failover_state:no-failover # 主节点的故障转移状态,no-failover表示没有进行故障转移
master_replid:93e564c18d27418e52fc40254c764d76c1dc3f67 # 主节点的复制ID
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:112 # 主节点已经写入的复制偏移量 slave_read_repl_offset ≈ master_repl_offset,说明数据已经同步
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:15
repl_backlog_histlen:98
  • 主从数据同步是否完成判断规则,在从节点上执行命令info replication

字段 正常值 说明
role slave 表示当前是从节点
master_link_status up 表示已经连上主库
master_sync_in_progress 0 同步不在进行中 = 已完成
slave_read_repl_offsetmaster_repl_offset 接近 说明数据已追上
  • 参照上面的配置,再添加一个从节点后,在主节点执行命令 info replication

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# Replication
role:master
connected_slaves:2 # 从节点数量
slave0:ip=10.250.0.36,port=6379,state=online,offset=4313,lag=0
slave1:ip=10.250.0.58,port=6379,state=online,offset=4313,lag=0 # 第二个从节点信息
master_failover_state:no-failover
master_replid:93e564c18d27418e52fc40254c764d76c1dc3f67
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:4313
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:4313

主从优点

  • 对请求进行读写分离,提高处理效率

  • 可以提供多个副本,提高数据安全性

主从缺点

  • 不具备自动容错和恢复功能,主节点故障,集群则无法进行工作,可用性比较低,从节点升主节点需要人工手动干预

哨兵

  • 创建三个哨兵,为了方便就在上面主从配置的3台服务器上启动哨兵

  • 规划

1
2
3
4
5
6
master 10.250.0.235
slave1 10.250.0.58
slave2 10.250.0.36
sentinel1 10.250.0.71
sentinel2 10.250.0.131
sentinel3 10.250.0.63
  • 分别编辑各自的 sentinel.conf

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# 端口号
port 26379

# 后台启动
daemonize yes

# dir,需要提前创建好
dir /usr/local/soft/dir-redis7/sentinel

# pid文件路径
pidfile redis-sentinel.pid

# 日志文件名称
logfile "sentinel.log"

# 配置监听的主节点地址和端口,mymaster为自定义的名称,最后的2表示,只要有2个哨兵节点认为主节点挂了就会进行重新选主,一般设置为sentinel总数/2+1
sentinel monitor mymaster 10.250.0.235 6379 2

# 主观下线时间(5秒),默认30秒
sentinel down-after-milliseconds mymaster 5000

# 故障转移超时时间 60秒,默认180秒
sentinel failover-timeout mymaster 60000

# 每次允许多少个slave重新同步,默认就是 1
sentinel parallel-syncs mymaster 1

# acl用户名和密码,这里为了方便也是用的管理员帐号
sentinel auth-user mymaster admin
sentinel auth-pass mymaster 123456
  • 分别启动三个哨兵节点redis-sentinel sentinel.conf,此时登录哨兵节点redis-cli -p 26379,并执行info Sentinel命令,查看其是否正确识别了主从

1
2
3
4
5
6
7
8
# Sentinel
sentinel_masters:1 # 哨兵集群中主从节点的数量
sentinel_tilt:0 # 是否处于 tilt 状态
sentinel_tilt_since_seconds:-1 # tilt 状态的开始时间
sentinel_running_scripts:0 # 正在运行的脚本数量
sentinel_scripts_queue_length:0 # 脚本队列长度
sentinel_simulate_failure_flags:0 # 模拟故障的标志
master0:name=mymaster,status=ok,address=10.250.0.235:6379,slaves=2,sentinels=3 # 主节点的地址,从节点数量和哨兵数量
  • 此时查看sentinel.conf可以在文件最后看到从节点信息和其它的哨兵节点信息(但实测无法感知其它哨兵节点),类似于

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# Generated by CONFIG REWRITE
latency-tracking-info-percentiles 50 99 99.9 # 延迟追踪信息百分比
user default on nopass sanitize-payload ~* &* +@all # 用户信息,当前的哨兵没有开启权限认证,所以缺省为default用户,无密码
sentinel myid 8b9d55a581f2e41b4f8d92f4a9434d9b8a78b3e6 # 本节点的id
sentinel config-epoch mymaster 0
sentinel leader-epoch mymaster 0
sentinel current-epoch 0
# 一个从节点信息
sentinel known-replica mymaster 10.250.0.58 6379
# 另一个从节点信息
sentinel known-replica mymaster 10.250.0.36 6379
# 一个哨兵节点信息
sentinel known-sentinel mymaster 10.250.0.71 26379 b230f6a6076c23eed1923b29027d9ba7b24bee5a
# 另一个哨兵节点信息
sentinel known-sentinel mymaster 10.250.0.63 26379 74ef58ef3616a27cc63d83bcfe422f15e11731b8
  • 此时关闭master节点(10.250.0.235:6379),然后登录哨兵节点查看info Sentinel,就会发现master节点变成了从节点其中的一个了

  • 此时再次开启原master节点,会发现其变成了从节点,相应的配置文件(redis-6379.conf)也发生了变更

1
2
3
4
5
6
# Generated by CONFIG REWRITE
latency-tracking-info-percentiles 50 99 99.9
replicaof 10.250.0.36 6379
save 3600 1
save 300 100
save 60 10000
  • 这里有一点需要注意,就是master节点重启前也需要配置如下认证信息,因为master在哨兵模式下发生故障后重新启动会变成slave

1
2
3
# 如果主节点开启了ACL认证,则从节点需要设置主节点的认证信息,这里设置为管理员帐号
masteruser admin
masterauth 123456
  • 顺便说一下,关闭哨兵服务的命令如下:

1
redis-cli -p 26379 shutdown

哨兵优点

  • 主节点故障,可以自动在从节点中重新选主

哨兵缺点

  • 哨兵单点故障,则集群无法完整自主选举主节点,所以需要对哨兵集群部署,增加服务器成本,但是并没有提升负载

  • 从节点仅作为备份不提供对外服务,只有当master出现故障时其晋升为master后才能提供服务,所以不支持读写分离

集群

  • 搭建6个redis的集群,3主3从

  • 规划

1
2
3
4
5
6
redis1 10.250.0.235
redis2 10.250.0.58
redis3 10.250.0.36
redis4 10.250.0.71
redis5 10.250.0.131
redis6 10.250.0.63
  • 还是基于单节点配置文件,只是将节点配置成集群模式,redis-6379.conf文件增加如下信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# ACL认证,所有节点都要配置
masteruser "admin"
masterauth "123456"

# 启动集群模式
cluster-enabled yes

# 集群节点信息文件,这里最好和port对应上
cluster-config-file nodes-6379.conf

# 集群节点间通信的超时时间,单位毫秒,默认15000,这个时间别设置太短,避免网络抖动等原因干扰
cluster-node-timeout 15000

# 写数据成功最少同步的slave数量,默认数据写入master就返回给client了,加上这个配置,就需要数据同步到指定数量的slave后才能返回,
# 注意这个配置不仅会延长client的等待时间,而且可能会影响集群的可用性,比如这里配置至少同步1个slave,但是如果此时master对应可用的slave不足1个,集群就不能提供服务了,所以建议每个master至少配置了2个以上的slave时才开启这个配置
# 开启这个配置可以预防集群脑裂问题,默认为3
min-replicas-to-write 1

# 如果集群中某个master/slave全部挂掉,整个集群的其它master/slave是否还可以对外提供服务,默认yes,不能
# 如果设置为no,则表示依旧可以提供服务,不过如果有key落在了挂掉的主从上就会失败
cluster-require-full-coverage yes
  • 分别启动6个redis服务

1
redis-server redis-6379.conf
  • 创建集群,3主3从,注意创建集群前所有redis不能有数据,如果有需要先清空(删除dir配置的目录中的所有文件即可),然后在任意一个redis执行

1
redis-cli --user admin --pass 123456 --cluster create --cluster-replicas 1 10.250.0.235:6379 10.250.0.58:6379 10.250.0.36:6379 10.250.0.71:6379 10.250.0.131:6379 10.250.0.63:6379
  • 此时会列出集群内主从和槽位的分配方案,输入yes即可

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
>>> Performing hash slots allocation on 6 nodes...
Master[0] -> Slots 0 - 5460
Master[1] -> Slots 5461 - 10922
Master[2] -> Slots 10923 - 16383
Adding replica 10.250.0.131:6379 to 10.250.0.235:6379
Adding replica 10.250.0.63:6379 to 10.250.0.58:6379
Adding replica 10.250.0.71:6379 to 10.250.0.36:6379
M: afcb754ce8cc79122fe9bcd8c1567bbf13258fce 10.250.0.235:6379
slots:[0-5460] (5461 slots) master
M: 2527142b7cffaf6bb92608550c919a0db0607c39 10.250.0.58:6379
slots:[5461-10922] (5462 slots) master
M: 88762f7d0bbb99bbaf68556ef5fd113cba46d295 10.250.0.36:6379
slots:[10923-16383] (5461 slots) master
S: 547fbd934293ddb5eb770e111b65910f4e604023 10.250.0.71:6379
replicates 88762f7d0bbb99bbaf68556ef5fd113cba46d295
S: 17b33861e6b086b86902fe75f79e5b878bd26f94 10.250.0.131:6379
replicates afcb754ce8cc79122fe9bcd8c1567bbf13258fce
S: 119e5823cccafef506b9b256aad206678eab7d41 10.250.0.63:6379
replicates 2527142b7cffaf6bb92608550c919a0db0607c39
Can I set the above configuration? (type 'yes' to accept): yes
>>> Nodes configuration updated
>>> Assign a different config epoch to each node
>>> Sending CLUSTER MEET messages to join the cluster
Waiting for the cluster to join
.
>>> Performing Cluster Check (using node 10.250.0.235:6379)
M: afcb754ce8cc79122fe9bcd8c1567bbf13258fce 10.250.0.235:6379
slots:[0-5460] (5461 slots) master
1 additional replica(s)
S: 547fbd934293ddb5eb770e111b65910f4e604023 10.250.0.71:6379
slots: (0 slots) slave
replicates 88762f7d0bbb99bbaf68556ef5fd113cba46d295
S: 119e5823cccafef506b9b256aad206678eab7d41 10.250.0.63:6379
slots: (0 slots) slave
replicates 2527142b7cffaf6bb92608550c919a0db0607c39
S: 17b33861e6b086b86902fe75f79e5b878bd26f94 10.250.0.131:6379
slots: (0 slots) slave
replicates afcb754ce8cc79122fe9bcd8c1567bbf13258fce
M: 88762f7d0bbb99bbaf68556ef5fd113cba46d295 10.250.0.36:6379
slots:[10923-16383] (5461 slots) master
1 additional replica(s)
M: 2527142b7cffaf6bb92608550c919a0db0607c39 10.250.0.58:6379
slots:[5461-10922] (5462 slots) master
1 additional replica(s)
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
  • 登录集群并查询集群配置信息

1
2
# -c 表示以集群模式登录,-h 集群内任意ip
redis-cli --user admin --pass 123456 -c -h 10.250.0.235
  • 查看集群信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
10.250.0.235:6379> cluster info
# 输出集群状态
cluster_state:ok # 集群整体状态:ok 表示集群当前可用、健康
cluster_slots_assigned:16384 # 已分配的哈希槽数量(总槽数固定为 16384)
cluster_slots_ok:16384 # 正常工作的槽数量(等于已分配槽,说明全部正常)
cluster_slots_pfail:0 # 处于“疑似失败(pfail)”状态的槽数量
cluster_slots_fail:0 # 被判定为失败(fail)的槽数量
cluster_known_nodes:6 # 当前节点已知的集群节点总数(主节点 + 从节点)
cluster_size:3 # 主节点数量(3 主节点,典型的 3 主 3 从结构)
cluster_current_epoch:6 # 集群当前的全局纪元(用于选举和配置同步)
cluster_my_epoch:1 # 当前这个节点所在的纪元
cluster_stats_messages_ping_sent:159 # 当前节点已发送的 PING 消息数量(心跳)
cluster_stats_messages_pong_sent:156 # 当前节点已发送的 PONG 消息数量(心跳响应)
cluster_stats_messages_sent:315 # 当前节点发送的所有集群消息总数
cluster_stats_messages_ping_received:151 # 当前节点收到的 PING 消息数量
cluster_stats_messages_pong_received:159 # 当前节点收到的 PONG 消息数量
cluster_stats_messages_meet_received:5 # 当前节点收到的 MEET 消息数量(新节点加入发现)
cluster_stats_messages_received:315 # 当前节点收到的所有集群消息总数
total_cluster_links_buffer_limit_exceeded:0 # 因输出缓冲区超限被强制断开的集群连接数(0 = 正常)
  • 查看节点列表

1
2
3
4
5
6
7
8
9
10
11
12
13
10.250.0.235:6379> cluster nodes
# 当前节点(myself),角色为 master,负责槽位 0-5460,是本机所在的主节点
afcb754ce8cc79122fe9bcd8c1567bbf13258fce 10.250.0.235:6379@16379 myself,master - 0 0 1 connected 0-5460
# 从节点(slave),对应的主节点是 10.250.0.36 这个 master(负责槽位 10923-16383)
547fbd934293ddb5eb770e111b65910f4e604023 10.250.0.71:6379@16379 slave 88762f7d0bbb99bbaf68556ef5fd113cba46d295 0 1765033120132 3 connected
# 从节点(slave),对应的主节点是 10.250.0.58 这个 master(负责槽位 5461-10922)
119e5823cccafef506b9b256aad206678eab7d41 10.250.0.63:6379@16379 slave 2527142b7cffaf6bb92608550c919a0db0607c39 0 1765033118000 2 connected
# 从节点(slave),对应的主节点是当前节点 10.250.0.235(负责槽位 0-5460)
17b33861e6b086b86902fe75f79e5b878bd26f94 10.250.0.131:6379@16379 slave afcb754ce8cc79122fe9bcd8c1567bbf13258fce 0 1765033119000 1 connected
# 主节点(master),负责槽位 10923-16383(集群中第三段槽位)
88762f7d0bbb99bbaf68556ef5fd113cba46d295 10.250.0.36:6379@16379 master - 0 1765033117000 3 connected 10923-16383
# 主节点(master),负责槽位 5461-10922(集群中第二段槽位)
2527142b7cffaf6bb92608550c919a0db0607c39 10.250.0.58:6379@16379 master - 0 1765033119126 2 connected 5461-10922
  • 此时查看nodes-6379.conf也会看到和上面一样的节点信息

  • 此时关闭其中一个master节点,比如10.250.0.36,则其对应的slave节点10.250.0.71会切换为新的master节点,此时10.250.0.36的状态最终变为fail

1
2
3
4
5
6
7
8
10.250.0.235:6379> cluster nodes
## 输出
afcb754ce8cc79122fe9bcd8c1567bbf13258fce 10.250.0.235:6379@16379 myself,master - 0 0 1 connected 0-5460
547fbd934293ddb5eb770e111b65910f4e604023 10.250.0.71:6379@16379 master - 0 1765033733534 7 connected 10923-16383
119e5823cccafef506b9b256aad206678eab7d41 10.250.0.63:6379@16379 slave 2527142b7cffaf6bb92608550c919a0db0607c39 0 1765033734542 2 connected
17b33861e6b086b86902fe75f79e5b878bd26f94 10.250.0.131:6379@16379 slave afcb754ce8cc79122fe9bcd8c1567bbf13258fce 0 1765033732526 1 connected
88762f7d0bbb99bbaf68556ef5fd113cba46d295 10.250.0.36:6379@16379 master,fail - 1765033690200 1765033686170 3 connected
2527142b7cffaf6bb92608550c919a0db0607c39 10.250.0.58:6379@16379 master - 0 1765033735550 2 connected 5461-10922
  • 再次启动10.250.0.36,其会变成10.250.0.71的slave节点

1
2
3
4
5
6
7
8
10.250.0.235:6379> cluster nodes
## 输出
afcb754ce8cc79122fe9bcd8c1567bbf13258fce 10.250.0.235:6379@16379 myself,master - 0 0 1 connected 0-5460
547fbd934293ddb5eb770e111b65910f4e604023 10.250.0.71:6379@16379 master - 0 1765033859000 7 connected 10923-16383
119e5823cccafef506b9b256aad206678eab7d41 10.250.0.63:6379@16379 slave 2527142b7cffaf6bb92608550c919a0db0607c39 0 1765033860493 2 connected
17b33861e6b086b86902fe75f79e5b878bd26f94 10.250.0.131:6379@16379 slave afcb754ce8cc79122fe9bcd8c1567bbf13258fce 0 1765033858000 1 connected
88762f7d0bbb99bbaf68556ef5fd113cba46d295 10.250.0.36:6379@16379 slave 547fbd934293ddb5eb770e111b65910f4e604023 0 1765033859488 7 connected
2527142b7cffaf6bb92608550c919a0db0607c39 10.250.0.58:6379@16379 master - 0 1765033859000 2 connected 5461-10922
  • redis集群会将2的14次幂(16384)的slot平均分配到所有master上,然后对key进行hash后计算应该存储到那个slot

1
2
3
4
5
6
7
HASH_SLOT=CRC16(key) mod 16384

# 跳转重定位
10.250.0.235:6379> set name zhangsan
# 输出
-> Redirected to slot [5798] located at 10.250.0.58:6379
OK
  • 关闭集群,6个redis分别关闭

1
redis-cli -c -h 10.250.0.235 -p 6379 --user admin --pass 123456 shutdown
  • 重启集群,6个redis分别启动即可

1
redis-server redis-6379.conf
  • mset/mget要求key都落在同一个slot上,每个key都加上前缀{prefix}

1
2
3
4
5
6
7
8
9
10
10.250.0.235:6379> mset name1 lisi name2 wangwu
(error) CROSSSLOT Keys in request don't hash to the same slot

10.250.0.235:6379> mset {user}:name1 lisi {user}:name2 wangwu
OK

10.250.0.235:6379> mget {user}:name1 {user}:name2
-> Redirected to slot [5474] located at 10.250.0.58:6379
1) "lisi"
2) "wangwu"
  • 集群推举新的master时要求至少一半的master同意,所以一个集群至少需要3个master,官方推荐master节点数为奇数,比如3个和4个master节点,都至多允许一个master节点挂掉时进行选主,但是3个master可以节省资源

  • 集群通过10000+port这个端口号进行集群间通信,所以除了要开放prot这个端口,还要开放10000+port这个端口

  • 有关redis集群及其水平扩展的进一步说明,可以参看Redis集群

集群优点

  • 无中心架构,集群内部自行维护数据的分片和主从的切换

  • 数据分片存储,提供很高的访问效率

  • 高可用性,可实现部分节点不可用时,集群仍可用

  • 高扩展性,可以横向扩展1000个节点后依旧保证访问效率,扩容缩容都支持

集群缺点

  • 数据通过异步复制,不保证数据的强一致性

  • 不支持多数据库空间,单机下的redis可以支持到16个数据库,集群模式下只能使用1个数据库空间,即db 0

  • 不支持跨slot操作,如使用mset、mget目前只支持具有相同slot值的Key执行批量操作

  • Key作为数据分区的最小粒度,不能将一个很大的键值对象如hash、list等映射到不同的节点

  • Key事务操作支持有限,只支持多key在同一节点上的事务操作,当多个Key分布于不同的节点上时无法使用事务功能

  • 不建议使用pipeline和multi-keys操作