Redis——主从集群搭建及哨兵模式配置(一主两从三哨兵)

Redis介绍

Redis(Remote Dictionary Server)是一款由意大利开发者 antirez(Salvatore Sanfilippo)使用 C 语言编写的高性能内存键值数据库。作为 NoSQL 数据库的代表,它采用 key-value 数据模型,支持多种数据结构,包括 String(字符串)、List(双向链表)、Hash(哈希)、Set(集合)和 Sorted Set(有序集合)。Redis 支持数据持久化,可将内存中的数据保存到磁盘,确保数据安全,同时提供主从复制、哨兵、集群等高可用方案。

1. 业务使用场合

Redis 凭借其丰富的数据结构和优异的性能,在多种业务场景中广泛应用:

  • 排行榜应用(Sorted Set):如微博热门话题、游戏积分榜等需要取 Top N 操作的场景。
  • 最新数据获取(List):获取最新 N 条数据或某个分类的最新数据,如新闻列表、消息流。
  • 计数器应用(String):如网站访问量、点赞数、库存扣减等需要原子性增减的场景。
  • 社交网络(Set):如获取共同好友、共同关注等集合运算。
  • 防攻击系统(Set):基于 IP 的黑白名单过滤,快速判断 IP 是否在名单内。

2. 对比 Memcached

特性 Redis Memcached
数据结构 支持 String、List、Hash、Set、Sorted Set 等多种数据结构 仅支持简单的 key-value
主从复制 支持 master-slave 模式,数据可复制到从节点 不支持
数据持久化 支持 RDB 和 AOF 两种持久化方式,重启可恢复数据 数据仅存于内存,重启即丢失
单 value 大小限制 最大 512 MB 最大 1 MB
多核性能 单核,小数据性能更高 多核,大数据(>100K)性能更优
内存使用率 对于简单 key-value,Memcached 更高;使用 hash 等结构时 Redis 更高 简单 key-value 场景内存使用率更高

结论:Redis 功能更丰富,适合需要复杂数据结构、持久化、高可用的场景;Memcached 更适合纯粹的、大 value 的缓存场景。在实际应用中,两者的每秒请求处理能力通常都不会成为瓶颈,选择时更应关注内存使用率和业务需求。

一、环境准备

角色 IP 地址 说明
Master 192.168.2.123 主节点,可读写
Slave1 192.168.2.124 从节点,只读
Slave2 192.168.2.125 从节点,只读

确保三台机器之间网络互通,可使用 ping 验证:

bash 复制代码
# 在 2.123 上测试
ping 192.168.2.124
ping 192.168.2.125

关闭防火墙和Selinux

bash 复制代码
systemctl stop firewalld

systemctl disable firewalld

setenforce 0

sed -i 's/^SELINUX=.*/SELINUX=disabled/' /etc/selinux/config

配置yum源

bash 复制代码
# aliyun
curl -o /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-7.repo
# Epel
curl -o /etc/yum.repos.d/epel.repo https://mirrors.aliyun.com/repo/epel-7.repo

# 可选
yum install -y http://rpms.remirepo.net/enterprise/remi-release-7.rpm

准备依赖包

https://download.csdn.net/download/qq_44769717/93022090

前置

1.安装前置依赖
bash 复制代码
yum install -y gcc gcc-c++ make wget vim
2.创建运行用户与目录规范
bash 复制代码
useradd -s /sbin/nologin -M redis
mkdir -pv /etc/redis /var/lib/redis/6379 /var/lib/redis/sentinel /var/log/redis /var/run
chown -R redis:redis /etc/redis /var/lib/redis /var/log/redis /var/run
3.配置主机名
复制代码
cat >>/etc/hosts<<'EOF'
192.168.2.123  node1
192.168.2.124  node2
192.168.2.125  node3
EOF
cat /etc/hosts

ping  192.168.2.123  -c2  &> /dev/null ; echo $?
ping  node1 -c2  &> /dev/null ; echo $?
ping  192.168.2.124 -c2  &> /dev/null ; echo $?
ping  node2 -c2  &> /dev/null ; echo $?
ping  192.168.2.125 -c2  &> /dev/null ; echo $?
ping  node3 -c2  &> /dev/null ; echo $?

二、源码编译安装 Redis(三台服务器均执行)

步骤 1:上传并解压软件

bash 复制代码
# 上传 redis-7.0.15.tar.gz 到 /opt 目录后执行
cd /opt
tar -xvzf redis-7.0.15.tar.gz
cd redis-7.0.15

步骤 2:编译安装

bash 复制代码
# 编译安装
make -j$(nproc); echo $?

# 安装到系统路径,全局可用
make install PREFIX=/usr/local/redis;echo $?

# 查看
ln -sv /usr/local/redis/bin/* /usr/local/bin/

# 验证安装:执行 redis-server -v,输出版本号即安装成功。
redis-server -v
redis-cli -v
# 看到以下内容则成功
#Redis server v=7.0.15 sha=00000000:0 malloc=jemalloc-5.2.1 bits=64 build=ca1b32a8ae9fab97
#redis-cli 7.0.15

安装完成后,可执行文件位于 /usr/local/redis/bin

复制代码
/usr/local/redis/bin/redis-server   启动服务端
/usr/local/redis/bin/redis-cli      命令行客户端

三、命令行客户端基础操作

bash 复制代码
cd /usr/local/redis/bin
./redis-cli

进入交互界面后,简单测试:

bash 复制代码
127.0.0.1:6379> set name test
OK
127.0.0.1:6379> get name
"test"
127.0.0.1:6379> info        # 查看系统状态
127.0.0.1:6379> help set    # 查看命令帮助

常用 key 相关操作速查:

命令 作用
exists key 判断 key 是否存在
type key 查看数据类型
keys * 查询所有 key
expire key seconds 设置过期时间
ttl key 查看剩余过期时间
del key 删除 key
select 0-15 切换数据库(默认16个)
dbsize 查看当前库 key 数量
flushdb 清空当前库

案例:

1.创建一个name的key

bash 复制代码
set name lengmoxi

2.exists name --- 判断 key 是否存在

bash 复制代码
exists name

exists name2

#返回 1 表示存在,0 表示不存在。

3.type name --- 查看数据类型

bash 复制代码
type name

4.keys * --- 查询所有 key

bash 复制代码
keys *

#可模糊匹配
keys na*

5.expire name seconds --- 设置过期时间

bash 复制代码
expire name 60

6.ttl name --- 查看剩余过期时间

bash 复制代码
ttl name

7.del name --- 删除 key

bash 复制代码
del name

get name

8.select 0-15 --- 切换数据库

bash 复制代码
set name lmx

select 3

get name
# 切到 3 号库后 [3] 提示符变了,0 号库的 name 在这里拿不到

set name lmx2

get name

select 0

get name
# 两个库互不干扰,各存各的 name。

9.dbsize --- 查看当前库 key 数量

bash 复制代码
dbsize

select 3

dbsize

10.flushdb --- 清空当前库

bash 复制代码
flushdb

keys *

dbsize

四、五种数据类型操作速览

1. String(字符串)

bash 复制代码
set key value           # 设置
get key                 # 获取
mset k1 v1 k2 v2        # 批量设置
mget k1 k2              # 批量获取
incr key / decr key     # 自增/自减 1
incrby key num          # 增加指定值
append key str          # 追加内容
strlen key              # 获取长度

2. List(双向链表)

bash 复制代码
lpush key value         # 左进
rpush key value         # 右进
lpop key                # 左出
rpop key                # 右出
llen key                # 查看长度
lrange key 0 -1         # 查看全部

栈(先进后出):lpush + lpop;队列(先进先出):lpush + rpop

3. Set(无序集合,不重复)

bash 复制代码
sadd key v1 v2          # 添加元素
smembers key            # 查看所有元素
sinter k1 k2            # 交集
sunion k1 k2            # 并集
sdiff k1 k2             # 差集
srem key v1             # 移除元素
sismember key v         # 判断是否存在
smove k1 k2 v           # 移动元素到另一个集合
scard key               # 统计元素数量

4. ZSet(有序集合,按权重排序)

bash 复制代码
zadd key score1 v1 score2 v2    # 添加(带权重)
zrange key 0 -1                 # 从小到大排序
zrevrange key 0 -1              # 从大到小排序
zscore key v                    # 查看某个元素的权重
zincrby key num v               # 增加/减少权重

5. Hash(哈希)

bash 复制代码
hmset key f1 v1 f2 v2          # 批量插入
hget key field                 # 获取单个字段
hmget key f1 f2                # 获取多个字段
hgetall key                    # 获取所有字段和值
hdel key field                 # 删除字段

五、Redis主从配置(一主两从)

1.核心配置说明

所有Redis节点统一设置访问密码,保证安全

所有节点同时配置masterauth:故障转移后原主节点会自动变为从节点,无需手动修改配置

开启RDB+AOF双持久化,保证数据安全

2.主节点(node1)配置

bash 复制代码
# 在node1创建Redis配置文件:
cat > /etc/redis/redis_6379.conf << 'EOF'
# 监听地址,允许内网访问,生产建议替换为具体内网IP
bind 0.0.0.0
port 6379
# 后台守护进程运行
daemonize yes
pidfile /var/run/redis_6379.pid
logfile /var/log/redis/redis_6379.log
# 数据持久化目录
dir /var/lib/redis/6379

# 访问密码,生产环境请修改为复杂密码
requirepass lengmoxi
# 主从同步认证密码,与上面密码完全一致
masterauth lengmoxi

# RDB持久化策略
save 900 1
save 300 10
save 60 10000
rdbcompression yes

# AOF持久化
appendonly yes
appendfilename "appendonly.aof"
appendfsync everysec

# 从节点默认只读
replica-read-only yes
EOF

3.从节点(node2/node3)配置

node2和node3配置与主节点几乎完全一致,仅新增一行指定主节点地址。以node2为例,node3操作完全相同:

bash 复制代码
cat > /etc/redis/redis_6379.conf << 'EOF'
bind 0.0.0.0
port 6379
daemonize yes
pidfile /var/run/redis_6379.pid
logfile /var/log/redis/redis_6379.log
dir /var/lib/redis/6379

requirepass lengmoxi
masterauth lengmoxi

save 900 1
save 300 10
save 60 10000
rdbcompression yes

appendonly yes
appendfilename "appendonly.aof"
appendfsync everysec

replica-read-only yes

# 唯一新增:指定初始主节点的IP和端口

replicaof 192.168.2.123 6379
EOF

注意:将replicaof后的IP替换为你node1的实际IP。

4.配置Systemd服务(所有节点)

配置系统服务,实现开机自启、后台稳定运行:

bash 复制代码
cat > /usr/lib/systemd/system/redis_6379.service << 'EOF'
[Unit]
Description=Redis 6379 Service
After=network.target

[Service]
Type=forking
User=redis
Group=redis
ExecStart=/usr/local/bin/redis-server /etc/redis/redis_6379.conf
ExecStop=/usr/local/bin/redis-cli -a lengmoxi -p 6379 shutdown
Restart=always
RestartSec=5
PrivateTmp=true

[Install]
WantedBy=multi-user.target
EOF

5.启动Redis并验证主从同步

所有节点启动Redis服务

bash 复制代码
systemctl daemon-reload
systemctl start redis_6379
systemctl enable redis_6379
systemctl restart redis_6379

验证主节点状态(node1执行)

bash 复制代码
redis-cli -a lengmoxi info replication

主Msater

从slave

出现master_link_status:up说明主从同步成功,若为down请检查网络、防火墙、密码是否一致。

bash 复制代码
redis-cli -a lengmoxi info replication | grep 'master_link_status'

六、配置哨兵(一主两从三哨兵)

1.所有节点Sentinel配置

三台机器执行完全相同的配置,仅需修改主节点IP为你的node1地址:

bash 复制代码
cat > /etc/redis/sentinel_26379.conf << 'EOF'

# Sentinel端口

port 26379
bind 0.0.0.0
daemonize yes
pidfile /var/run/redis-sentinel_26379.pid
logfile /var/log/redis/sentinel_26379.log

# 工作目录,存放运行时自动更新的配置

dir /var/lib/redis/sentinel

# 监控主节点:名称mymaster + 初始主节点IP端口 + quorum=2

sentinel monitor mymaster 192.168.2.123 6379 2

# 主节点认证密码

sentinel auth-pass mymaster lengmoxi

# 主观下线超时:30秒无响应判定主观下线

sentinel down-after-milliseconds mymaster 30000

# 故障转移后并行同步从节点数

sentinel parallel-syncs mymaster 1

# 故障转移超时时间:3分钟

sentinel failover-timeout mymaster 180000

# 关闭保护模式,允许跨节点通信

protected-mode no
EOF

修改了配置文件,要重启生效(后面设置了systemctl)

bash 复制代码
systemctl restart redis-sentinel_26379

mymaster`不是 node1 的主机名,也不是服务器的主机名/IP,它是 Sentinel 集群给「这一整套被监控的主从集群」起的自定义逻辑名称(集群标识名),和服务器 hostname 没有任何对应关系。

2.配置Sentinel系统服务(所有节点)

bash 复制代码
cat > /usr/lib/systemd/system/redis-sentinel_26379.service << 'EOF'
[Unit]
Description=Redis Sentinel 26379 Service
After=network.target redis_6379.service

[Service]
Type=forking
User=redis
Group=redis
ExecStart=/usr/local/bin/redis-sentinel /etc/redis/sentinel_26379.conf
ExecStop=/usr/local/bin/redis-cli -p 26379 shutdown
Restart=always
RestartSec=5
PrivateTmp=true

[Install]
WantedBy=multi-user.target
EOF

3.修复权限

bash 复制代码
# 1. 修正属主
chown redis:redis /etc/redis/sentinel_26379.conf

# 2. 确保目录也对 redis 可写(避免后面 pid/log )
chown -R redis:redis /var/log/redis
chown -R redis:redis /var/lib/redis/sentinel
# 顺手把 pid 目录也保证存在
mkdir -p /var/lib/redis/sentinel
chown redis:redis /var/lib/redis/sentinel

# 3. 重载并启动(如果之前反复 failed,最好清一次 systemd 状态)
systemctl reset-failed redis-sentinel_26379.service
systemctl daemon-reload
systemctl start redis-sentinel_26379
systemctl restart redis-sentinel_26379
systemctl status redis-sentinel_26379 -l

4.启动Sentinel集群并验证

(1)所有节点启动哨兵服务
bash 复制代码
systemctl daemon-reload
systemctl start redis-sentinel_26379
systemctl enable redis-sentinel_26379
systemctl restart redis-sentinel_26379
systemctl status redis-sentinel_26379 -l

主Master

从salve1

从salve2

(2)验证哨兵集群状态(任意节点执行)
bash 复制代码
redis-cli -p 26379 info sentinel

预期输出核心信息:

master0:name=mymaster,status=ok,address=192.168.2.123:6379,slaves=2,sentinels=3

关键验证点:sentinels=3说明三个哨兵已互相发现并组成集群,slaves=2说明已识别所有从节点。

主Msater:

从salve1

从salve2

查询当前主节点地址

bash 复制代码
redis-cli -p 26379 sentinel get-master-addr-by-name mymaster

正常返回初始主节点的IP和端口6379

正常返回初始主节点的IP和端口6379

七、故障转移

当前环境的路径和密码:

项目
Master 初始 192.168.2.123
Slave 192.168.2.124、192.168.2.125
密码 lengmoxi
Sentinel 端口 26379
配置目录 /etc/redis/
systemd 服务 redis_6379redis-sentinel_26379

前置准备:在 2.125 上开启实时日志监控

bash 复制代码
# 清空旧日志
> /var/log/redis/sentinel_26379.log

# 开启实时监控
tail -f /var/log/redis/sentinel_26379.log

保持这个终端窗口不要关,稍后故障转移的所有日志都会实时滚动出来。

1.确认初始状态(Master = 2.123)

在任意节点执行:

bash 复制代码
redis-cli -p 26379 sentinel get-master-addr-by-name mymaster

预期返回:

复制代码
192.168.2.123
6379

再确认整体集群状态:

bash 复制代码
redis-cli -p 26379 info sentinel | grep master0

预期输出:

复制代码
master0:name=mymaster,status=ok,address=192.168.2.123:6379,slaves=2,sentinels=3

三项关键指标:status=okslaves=2sentinels=3,确认无误后开始测试。

2.模拟 Master 宕机

在 Master 机器(192.168.2.123)上或用 SSH 远程执行:

bash 复制代码
# 方式一:通过 systemd 停服务(推荐,你在用 systemd)
systemctl stop redis_6379

# 方式二:通过 redis-cli 远程关闭
redis-cli -h 192.168.2.123 -a lengmoxi shutdown

验证已停:

bash 复制代码
redis-cli -h 192.168.2.123 -a lengmoxi ping
# 返回 Could not connect 即为已停止

3.观察日志(在 2.125 的 tail 窗口)

10 秒左右,日志中会依次出现以下关键行:

复制代码
+sdown master mymaster 192.168.2.123 6379           ← 主观下线
+odown master mymaster 192.168.2.123 6379 #quorum 3/2  ← 客观下线(≥2票)
+vote-for-leader xxxxx 1                             ← 开始投票
+elected-leader master mymaster 192.168.2.123 6379   ← Leader 选出
+failover-state-select-slave master mymaster ...      ← 选择新 Master
+selected-slave slave 192.168.2.124:6379 ...         ← 选定 124 为新 Master
+switch-master mymaster 192.168.2.123 6379 192.168.2.124 6379  ← 切换完成

4.验证 Sentinel 已切换

bash 复制代码
redis-cli -p 26379 info sentinel | grep master0

现在 address 应该已变为:

复制代码
master0:name=mymaster,status=ok,address=192.168.2.124:6379,slaves=2,sentinels=3

address 从 2.123 变成了 2.124,说明故障转移成功。

命令行快速确认三件套:

bash 复制代码
# 当前 Master 是谁
redis-cli -p 26379 sentinel get-master-addr-by-name mymaster

# 所有 Slave 列表
redis-cli -p 26379 sentinel slaves mymaster

# Master 详细状态(含切换次数)
redis-cli -p 26379 sentinel master mymaster

5.在新 Master(2.124)上验证主从状态

bash 复制代码
redis-cli -h 192.168.2.124 -a lengmoxi info replication

预期看到:

复制代码
role:master
connected_slaves:1
slave0:ip=192.168.2.125,port=6379,state=online,...
  • role:master ✅ 124 已提升为 Master
  • connected_slaves:1 --- 125 已跟随新 Master(123 还没启动,所以是 1)

6.启动原来的 Master(2.123)

bash 复制代码
# 在 192.168.2.123 上
systemctl start redis_6379

验证已启动:

bash 复制代码
redis-cli -h 192.168.2.123 -a lengmoxi ping
# 返回 PONG

7.验证原 Master 已变为 Slave

bash 复制代码
redis-cli -h 192.168.2.123 -a lengmoxi info replication

预期看到:

复制代码
role:slave
master_host:192.168.2.124
master_port:6379
master_link_status:up

这说明 2.123 重新上线后,自动变成了新 Master(2.124)的 Slave

8.最终全局验证

在新 Master 上确认两从已齐:

bash 复制代码
redis-cli -h 192.168.2.124 -a lengmoxi info replication

预期:

复制代码
role:master
connected_slaves:2
slave0:ip=192.168.2.125,port=6379,state=online,...
slave1:ip=192.168.2.123,port=6379,state=online,...

Sentinel 全局确认:

bash 复制代码
redis-cli -p 26379 info sentinel | grep master0

预期:

复制代码
master0:name=mymaster,status=ok,address=192.168.2.124:6379,slaves=2,sentinels=3

故障转移全流程总结

阶段 事件 Master 角色
初始 正常运作 2.123
宕机 systemctl stop redis_6379 ---
10s 内 +sdown → +odown → 选举 → 切换 2.124
启动旧 Master systemctl start redis_6379 2.124(2.123 变 Slave)
恢复后 一主两从正常运行 2.124

注意事项

  • 恢复环境 :如果想重新做一次测试,需要先把 2.123 恢复为 Master。最简单的方式是用 sentinel failover mymaster 手动触发一次转移,让 2.123 重新成为 Master,然后再做上述测试
  • 日志解读 :关键看日志中的 +sdown+odown+switch-master 这五条线,任何一步缺失都说明哨兵集群有问题
  • 密码:所有 Redis 节点和 Sentinel 节点密码必须一致,否则故障转移时会因认证失败而中断