1 环境准备

1.1 系统要求

  • 操作系统:Linux (推荐 Ubuntu 20.04+ 或 CentOS 7+)
  • 内存:至少 2GB
  • Redis 版本:6.x 或 7.x

1.2 安装 Redis

Ubuntu/Debian 系统

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
# 更新包管理器
sudo apt update

# 安装 Redis
sudo apt install redis-server -y

# 或者从源码编译最新版本
wget https://download.redis.io/redis-stable.tar.gz
tar -xzf redis-stable.tar.gz
cd redis-stable
make
sudo make install

CentOS/RHEL 系统

1
2
3
4
5
6
7
8
# 安装 EPEL 仓库
sudo yum install epel-release -y

# 安装 Redis
sudo yum install redis -y

# 或使用 dnf (CentOS 8+)
sudo dnf install redis -y

macOS 系统

1
2
3
4
5
# 使用 Homebrew 安装
brew install redis

# 或者使用 MacPorts
sudo port install redis

1.3 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
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
# 创建 Redis 安装检查脚本
cat > ~/redis-practice/check-redis-installation.sh << 'EOF'
#!/bin/bash

echo "=== Redis 安装状态检查 ==="

# 检查 redis-server
if command -v redis-server >/dev/null 2>&1; then
    echo "✅ redis-server 已安装: $(which redis-server)"
    redis-server --version
else
    echo "❌ redis-server 未找到"
    REDIS_MISSING=1
fi

# 检查 redis-cli
if command -v redis-cli >/dev/null 2>&1; then
    echo "✅ redis-cli 已安装: $(which redis-cli)"
else
    echo "❌ redis-cli 未找到"
    REDIS_MISSING=1
fi

# 检查 redis-sentinel
if command -v redis-sentinel >/dev/null 2>&1; then
    echo "✅ redis-sentinel 已安装: $(which redis-sentinel)"
else
    echo "⚠️  redis-sentinel 未找到,将使用 redis-server --sentinel 模式"
    if command -v redis-server >/dev/null 2>&1; then
        echo "✅ 可以使用 redis-server --sentinel 启动哨兵"
    else
        REDIS_MISSING=1
    fi
fi

if [ "$REDIS_MISSING" = "1" ]; then
    echo ""
    echo "❌ Redis 未正确安装,请选择以下安装方式:"
    echo ""
    echo "Ubuntu/Debian:"
    echo "  sudo apt update && sudo apt install redis-server -y"
    echo ""
    echo "CentOS/RHEL:"
    echo "  sudo yum install epel-release -y && sudo yum install redis -y"
    echo ""
    echo "macOS:"
    echo "  brew install redis"
    echo ""
    echo "从源码编译:"
    echo "  wget https://download.redis.io/redis-stable.tar.gz"
    echo "  tar -xzf redis-stable.tar.gz"
    echo "  cd redis-stable && make && sudo make install"
    echo ""
    exit 1
else
    echo ""
    echo "✅ Redis 安装检查完成,可以开始架构搭建实践"
fi
EOF

chmod +x ~/redis-practice/check-redis-installation.sh

# 运行安装检查
~/redis-practice/check-redis-installation.sh

1.4 创建工作目录

1
2
3
mkdir -p ~/redis-practice
cd ~/redis-practice
mkdir -p {master-slave,cluster,sentinel}/{conf,data,logs}

1.5 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
30
# 创建版本兼容性检查脚本
cat > ~/redis-practice/check-redis-version.sh << 'EOF'
#!/bin/bash

echo "=== Redis 版本检查 ==="
REDIS_VERSION=$(redis-server --version | grep -oE "[0-9]+\.[0-9]+" | head -1)
echo "检测到 Redis 版本: $REDIS_VERSION"

MAJOR_VERSION=$(echo $REDIS_VERSION | cut -d. -f1)
MINOR_VERSION=$(echo $REDIS_VERSION | cut -d. -f2)

echo "主版本号: $MAJOR_VERSION, 次版本号: $MINOR_VERSION"

if [ $MAJOR_VERSION -ge 5 ]; then
    echo "✅ Redis 5.0+ 版本,支持 replica-* 指令"
    echo "建议使用: replicaof, replica-serve-stale-data, replica-read-only"
else
    echo "⚠️  Redis 4.x 版本,需要使用 slave-* 指令"
    echo "必须使用: slaveof, slave-serve-stale-data, slave-read-only"
fi

echo ""
echo "当前指南已针对 Redis 4.x 兼容性进行配置"
echo "如果您使用 Redis 5.0+,配置文件仍然有效(向后兼容)"
EOF

chmod +x ~/redis-practice/check-redis-version.sh

# 运行版本检查
~/redis-practice/check-redis-version.sh

2 主从复制架构 (Master-Slave)

2.1 架构说明

  • 1个主节点 (Master):负责写操作
  • 2个从节点 (Slave):负责读操作,从主节点同步数据

2.2 配置文件准备

主节点配置 (redis-master.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
cat > ~/redis-practice/master-slave/conf/redis-master.conf << 'EOF'
# 基本配置
port 6379
bind 0.0.0.0
protected-mode no

# 数据持久化
dir /home/$(whoami)/redis-practice/master-slave/data/master
dbfilename dump-master.rdb
appendonly yes
appendfilename "appendonly-master.aof"

# 日志配置
logfile /home/$(whoami)/redis-practice/master-slave/logs/redis-master.log
loglevel notice

# 主从复制配置
# 允许从节点连接 (Redis 5.0+ 使用 replica-*, 4.0 使用 slave-*)
replica-serve-stale-data yes
replica-read-only yes

# 安全配置
requirepass redis123
masterauth redis123

# 性能优化
maxmemory 256mb
maxmemory-policy allkeys-lru
EOF

从节点1配置 (redis-slave1.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
cat > ~/redis-practice/master-slave/conf/redis-slave1.conf << 'EOF'
# 基本配置
port 6380
bind 0.0.0.0
protected-mode no

# 数据持久化
dir /home/$(whoami)/redis-practice/master-slave/data/slave1
dbfilename dump-slave1.rdb
appendonly yes
appendfilename "appendonly-slave1.aof"

# 日志配置
logfile /home/$(whoami)/redis-practice/master-slave/logs/redis-slave1.log
loglevel notice

# 主从复制配置
replicaof 127.0.0.1 6379
replica-serve-stale-data yes
replica-read-only yes

# 安全配置
requirepass redis123
masterauth redis123

# 性能优化
maxmemory 256mb
maxmemory-policy allkeys-lru
EOF

从节点2配置 (redis-slave2.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
cat > ~/redis-practice/master-slave/conf/redis-slave2.conf << 'EOF'
# 基本配置
port 6381
bind 0.0.0.0
protected-mode no

# 数据持久化
dir /home/$(whoami)/redis-practice/master-slave/data/slave2
dbfilename dump-slave2.rdb
appendonly yes
appendfilename "appendonly-slave2.aof"

# 日志配置
logfile /home/$(whoami)/redis-practice/master-slave/logs/redis-slave2.log
loglevel notice

# 主从复制配置
replicaof 127.0.0.1 6379
replica-serve-stale-data yes
replica-read-only yes

# 安全配置
requirepass redis123
masterauth redis123

# 性能优化
maxmemory 256mb
maxmemory-policy allkeys-lru
EOF

2.3 关键命令详解

在使用脚本之前,让我们先了解主从复制的核心命令:

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
30
31
# 1. 启动 Redis 服务器的基本命令
redis-server [配置文件路径]           # 启动Redis服务器
redis-server --port 6379             # 指定端口启动
redis-server --daemonize yes         # 后台运行模式

# 2. 主从复制配置命令
# 在从节点上执行,建立主从关系
REPLICAOF 127.0.0.1 6379            # Redis 5.0+ 建立主从关系
SLAVEOF 127.0.0.1 6379              # Redis 4.x 建立主从关系
SLAVEOF NO ONE                       # 取消主从关系,提升为主节点

# 3. 认证命令
AUTH redis123                        # 客户端认证
CONFIG SET masterauth redis123       # 设置主节点认证密码
CONFIG SET requirepass redis123      # 设置访问密码

# 4. 复制状态查看命令
INFO replication                     # 查看复制状态信息
INFO server                          # 查看服务器信息
PING                                 # 测试连接

# 5. 数据同步相关
PSYNC <replication_id> <offset>      # 部分重同步命令(内部使用)
FULLRESYNC                          # 全量重同步(内部使用)

# 6. 配置文件中的关键参数
# replicaof <masterip> <masterport>   # 指定主节点
# replica-read-only yes               # 从节点只读
# replica-serve-stale-data yes        # 从节点在连接断开时是否提供旧数据
# repl-diskless-sync no               # 是否使用无盘复制
# repl-diskless-sync-delay 5          # 无盘复制延迟时间

手动建立主从复制示例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# 1. 启动主节点(端口6379)
redis-server --port 6379 --requirepass redis123 --masterauth redis123 \
             --dir /tmp/master --dbfilename master.rdb \
             --logfile /tmp/master.log --daemonize yes

# 2. 启动从节点1(端口6380)
redis-server --port 6380 --requirepass redis123 --masterauth redis123 \
             --dir /tmp/slave1 --dbfilename slave1.rdb \
             --logfile /tmp/slave1.log --daemonize yes

# 3. 在从节点建立主从关系
redis-cli -p 6380 -a redis123 REPLICAOF 127.0.0.1 6379

# 4. 验证主从状态
redis-cli -p 6379 -a redis123 INFO replication  # 查看主节点状态
redis-cli -p 6380 -a redis123 INFO replication  # 查看从节点状态

# 5. 测试数据同步
redis-cli -p 6379 -a redis123 SET test_key "hello world"  # 主节点写入
redis-cli -p 6380 -a redis123 GET test_key                # 从节点读取

# 6. 停止服务
redis-cli -p 6379 -a redis123 SHUTDOWN  # 关闭主节点
redis-cli -p 6380 -a redis123 SHUTDOWN  # 关闭从节点

启动主从架构

 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
# 创建启动脚本
cat > ~/redis-practice/master-slave/start-master-slave.sh << 'EOF'
#!/bin/bash

BASE_DIR=~/redis-practice/master-slave

echo "=== 启动 Redis 主从架构 ==="

# 创建数据目录
echo "创建数据目录..."
mkdir -p $BASE_DIR/data/{master,slave1,slave2}

# 检查配置文件是否存在
for conf in redis-master.conf redis-slave1.conf redis-slave2.conf; do
    if [ ! -f "$BASE_DIR/conf/$conf" ]; then
        echo "错误: 配置文件 $conf 不存在!"
        exit 1
    fi
done

# 启动主节点
echo "启动主节点 (端口 6379)..."
redis-server $BASE_DIR/conf/redis-master.conf &
MASTER_PID=$!

# 等待主节点启动
sleep 3
if ! redis-cli -p 6379 -a redis123 ping >/dev/null 2>&1; then
    echo "错误: 主节点启动失败!"
    exit 1
fi
echo "✅ 主节点启动成功 (PID: $MASTER_PID)"

# 启动从节点1
echo "启动从节点1 (端口 6380)..."
redis-server $BASE_DIR/conf/redis-slave1.conf &
SLAVE1_PID=$!
sleep 2
if ! redis-cli -p 6380 -a redis123 ping >/dev/null 2>&1; then
    echo "错误: 从节点1启动失败!"
    exit 1
fi
echo "✅ 从节点1启动成功 (PID: $SLAVE1_PID)"

# 启动从节点2
echo "启动从节点2 (端口 6381)..."
redis-server $BASE_DIR/conf/redis-slave2.conf &
SLAVE2_PID=$!
sleep 2
if ! redis-cli -p 6381 -a redis123 ping >/dev/null 2>&1; then
    echo "错误: 从节点2启动失败!"
    exit 1
fi
echo "✅ 从节点2启动成功 (PID: $SLAVE2_PID)"

# 等待主从同步
echo "等待主从同步..."
sleep 5

# 验证主从关系
echo "=== 验证主从复制状态 ==="
echo "主节点信息:"
redis-cli -p 6379 -a redis123 info replication | grep -E "role|connected_slaves"

echo "\n从节点1信息:"
redis-cli -p 6380 -a redis123 info replication | grep -E "role|master_host|master_port"

echo "\n从节点2信息:"
redis-cli -p 6381 -a redis123 info replication | grep -E "role|master_host|master_port"

echo "\n=== 主从架构启动完成!==="
echo "主节点: 127.0.0.1:6379"
echo "从节点1: 127.0.0.1:6380"
echo "从节点2: 127.0.0.1:6381"
echo "密码: redis123"

# 保存进程ID
echo "$MASTER_PID $SLAVE1_PID $SLAVE2_PID" > $BASE_DIR/redis-pids.txt
EOF

chmod +x ~/redis-practice/master-slave/start-master-slave.sh

# 运行启动脚本
~/redis-practice/master-slave/start-master-slave.sh

停止主从架构

 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
# 创建停止脚本
cat > ~/redis-practice/master-slave/stop-master-slave.sh << 'EOF'
#!/bin/bash

BASE_DIR=~/redis-practice/master-slave

echo "=== 停止 Redis 主从架构 ==="

# 优雅关闭 Redis 实例
echo "正在停止 Redis 实例..."
for port in 6379 6380 6381; do
    if redis-cli -p $port -a redis123 ping >/dev/null 2>&1; then
        echo "停止端口 $port 上的 Redis 实例"
        redis-cli -p $port -a redis123 shutdown
    else
        echo "端口 $port 上没有运行的 Redis 实例"
    fi
done

# 等待进程结束
sleep 2

# 检查是否还有残留进程
REMAINING=$(ps aux | grep -E "redis-server.*master-slave" | grep -v grep | wc -l)
if [ $REMAINING -gt 0 ]; then
    echo "强制终止残留进程..."
    pkill -f "redis-server.*master-slave"
fi

# 清理 PID 文件
if [ -f "$BASE_DIR/redis-pids.txt" ]; then
    rm $BASE_DIR/redis-pids.txt
fi

echo "✅ 主从架构已停止"
EOF

chmod +x ~/redis-practice/master-slave/stop-master-slave.sh

主从架构管理命令

1
2
3
4
5
6
7
8
# 启动主从架构
~/redis-practice/master-slave/start-master-slave.sh

# 停止主从架构
~/redis-practice/master-slave/stop-master-slave.sh

# 重启主从架构
~/redis-practice/master-slave/stop-master-slave.sh && sleep 2 && ~/redis-practice/master-slave/start-master-slave.sh

2.4 验证主从复制

1
2
3
4
5
6
7
8
9
# 连接主节点并写入数据
redis-cli -p 6379 -a redis123 set test-key "hello from master"

# 在从节点验证数据同步
redis-cli -p 6380 -a redis123 get test-key
redis-cli -p 6381 -a redis123 get test-key

# 查看复制状态
redis-cli -p 6379 -a redis123 info replication

2.5 测试读写分离

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
# 主节点写入测试
redis-cli -p 6379 -a redis123 << 'EOF'
set user:1 "张三"
set user:2 "李四"
hmset product:1 name "iPhone" price 8999
EOF

# 从节点读取测试
echo "从 slave1 读取数据:"
redis-cli -p 6380 -a redis123 get user:1
redis-cli -p 6380 -a redis123 hgetall product:1

echo "从 slave2 读取数据:"
redis-cli -p 6381 -a redis123 get user:2

3 Redis Cluster 集群架构

  • 6个节点:3个主节点 + 3个从节点
  • 每个主节点负责一部分槽位 (0-16383)
  • 自动故障转移和数据分片

3.1 Redis Cluster 核心命令详解

在使用脚本创建集群之前,让我们先了解集群的核心命令:

Cluster 管理命令

 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
# 1. 集群创建命令
# Redis 5.0+ 使用 redis-cli
redis-cli --cluster create 127.0.0.1:7000 127.0.0.1:7001 127.0.0.1:7002 \
                           127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005 \
                           --cluster-replicas 1 -a redis123

# Redis 4.x 使用 redis-trib.rb
redis-trib.rb create --replicas 1 127.0.0.1:7000 127.0.0.1:7001 \
                                  127.0.0.1:7002 127.0.0.1:7003 \
                                  127.0.0.1:7004 127.0.0.1:7005

# 2. 集群状态查看命令
CLUSTER NODES                        # 查看所有节点信息
CLUSTER INFO                         # 查看集群整体状态
CLUSTER SLOTS                        # 查看槽位分配情况
INFO cluster                         # 查看集群相关信息

# 3. 集群节点管理
CLUSTER MEET <ip> <port>             # 添加节点到集群
CLUSTER FORGET <node-id>             # 从集群中移除节点
CLUSTER REPLICATE <node-id>          # 设置当前节点为指定节点的从节点
CLUSTER RESET [HARD|SOFT]            # 重置节点集群状态

# 4. 槽位管理命令
CLUSTER ADDSLOTS <slot> [slot ...]   # 为节点分配槽位
CLUSTER DELSLOTS <slot> [slot ...]   # 删除节点的槽位
CLUSTER SETSLOT <slot> NODE <node-id> # 将槽位分配给指定节点
CLUSTER SETSLOT <slot> MIGRATING <destination-node-id>  # 开始迁移槽位
CLUSTER SETSLOT <slot> IMPORTING <source-node-id>      # 准备接收槽位

# 5. 数据迁移命令
CLUSTER GETKEYSINSLOT <slot> <count> # 获取槽位中的键
MIGRATE <host> <port> <key> <destination-db> <timeout> # 迁移单个键

# 6. 集群配置文件关键参数
# cluster-enabled yes                    # 启用集群模式
# cluster-config-file nodes.conf         # 集群配置文件
# cluster-node-timeout 15000             # 节点超时时间
# cluster-announce-ip 127.0.0.1          # 对外公布的IP
# cluster-announce-port 7000             # 对外公布的端口
# cluster-require-full-coverage no       # 是否要求全部槽位可用

手动创建集群示例

 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
# 1. 启动所有节点(不组成集群)
for port in 7000 7001 7002 7003 7004 7005; do
    redis-server --port $port --cluster-enabled yes \
                 --cluster-config-file nodes-$port.conf \
                 --cluster-node-timeout 5000 \
                 --requirepass redis123 --masterauth redis123 \
                 --daemonize yes --dir /tmp/cluster-$port
done

# 2. 手动组建集群(逐步建立)
# 第一步:让节点相互认识
redis-cli -p 7000 -a redis123 CLUSTER MEET 127.0.0.1 7001
redis-cli -p 7000 -a redis123 CLUSTER MEET 127.0.0.1 7002
redis-cli -p 7000 -a redis123 CLUSTER MEET 127.0.0.1 7003
redis-cli -p 7000 -a redis123 CLUSTER MEET 127.0.0.1 7004
redis-cli -p 7000 -a redis123 CLUSTER MEET 127.0.0.1 7005

# 第二步:分配槽位(共 16384 个槽位,编号 0-16383)
redis-cli -p 7000 -a redis123 CLUSTER ADDSLOTS {0..5461}     # 节点 7000
redis-cli -p 7001 -a redis123 CLUSTER ADDSLOTS {5462..10922} # 节点 7001
redis-cli -p 7002 -a redis123 CLUSTER ADDSLOTS {10923..16383} # 节点 7002

# 第三步:设置主从关系(需要先获取节点 ID)
NODE_7000=$(redis-cli -p 7000 -a redis123 CLUSTER NODES | grep myself | awk '{print $1}')
NODE_7001=$(redis-cli -p 7001 -a redis123 CLUSTER NODES | grep myself | awk '{print $1}')
NODE_7002=$(redis-cli -p 7002 -a redis123 CLUSTER NODES | grep myself | awk '{print $1}')

# 设置 7003 为 7000 的从节点
redis-cli -p 7003 -a redis123 CLUSTER REPLICATE $NODE_7000
# 设置 7004 为 7001 的从节点
redis-cli -p 7004 -a redis123 CLUSTER REPLICATE $NODE_7001
# 设置 7005 为 7002 的从节点
redis-cli -p 7005 -a redis123 CLUSTER REPLICATE $NODE_7002

# 3. 验证集群状态
redis-cli -c -p 7000 -a redis123 CLUSTER NODES
redis-cli -c -p 7000 -a redis123 CLUSTER INFO

# 4. 测试数据分片(使用 -c 参数启用集群模式)
redis-cli -c -p 7000 -a redis123 SET user:1001 "Alice"
redis-cli -c -p 7000 -a redis123 SET user:1002 "Bob"
redis-cli -c -p 7000 -a redis123 GET user:1001
redis-cli -c -p 7000 -a redis123 GET user:1002

# 5. 查看键的槽位分布
redis-cli -c -p 7000 -a redis123 CLUSTER KEYSLOT user:1001
redis-cli -c -p 7000 -a redis123 CLUSTER KEYSLOT user:1002

3.2 集群节点配置

创建集群配置模板

 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
# 创建集群配置生成脚本
cat > ~/redis-practice/cluster/create-cluster-configs.sh << 'EOF'
#!/bin/bash

BASE_DIR=~/redis-practice/cluster
PORTS=(7000 7001 7002 7003 7004 7005)

for port in "${PORTS[@]}"; do
    mkdir -p $BASE_DIR/data/node-$port
    
    cat > $BASE_DIR/conf/redis-$port.conf << CONFIG
# 基本配置
port $port
bind 0.0.0.0
protected-mode no

# 集群配置
cluster-enabled yes
cluster-config-file $BASE_DIR/data/node-$port/nodes-$port.conf
cluster-node-timeout 15000
cluster-announce-ip 127.0.0.1
cluster-announce-port $port

# 数据持久化
dir $BASE_DIR/data/node-$port
dbfilename dump-$port.rdb
appendonly yes
appendfilename "appendonly-$port.aof"

# 日志配置
logfile $BASE_DIR/logs/redis-$port.log
loglevel notice

# 安全配置
requirepass redis123
masterauth redis123

# 性能配置
maxmemory 256mb
maxmemory-policy allkeys-lru
CONFIG
done

echo "集群配置文件生成完成!"
EOF

chmod +x ~/redis-practice/cluster/create-cluster-configs.sh
~/redis-practice/cluster/create-cluster-configs.sh

3.3 启动集群节点

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# 启动所有集群节点
cd ~/redis-practice/cluster
for port in 7000 7001 7002 7003 7004 7005; do
    echo "启动节点 $port"
    redis-server conf/redis-$port.conf &
    sleep 1
done

# 等待所有节点启动
sleep 5
echo "所有节点启动完成"

3.4 创建集群

1
2
3
4
5
6
7
8
9
# 创建集群 (Redis 5.0+ 使用 redis-cli)
redis-cli --cluster create \
    127.0.0.1:7000 127.0.0.1:7001 127.0.0.1:7002 \
    127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005 \
    --cluster-replicas 1 \
    -a redis123

# 如果是 Redis 4.x,使用 redis-trib.rb
# redis-trib.rb create --replicas 1 127.0.0.1:7000 127.0.0.1:7001 ...

3.5 验证集群状态

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
# 查看集群信息
redis-cli -c -p 7000 -a redis123 cluster info
redis-cli -c -p 7000 -a redis123 cluster nodes

# 测试集群数据分片
redis-cli -c -p 7000 -a redis123 << 'EOF'
set name "Redis集群测试"
set age 25
set city "北京"
get name
get age
get city
EOF

3.6 集群管理操作

 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
# 创建集群管理脚本
cat > ~/redis-practice/cluster/cluster-manager.sh << 'EOF'
#!/bin/bash

REDIS_PASSWORD="redis123"

case $1 in
    "status")
        echo "=== 集群状态 ==="
        redis-cli -c -p 7000 -a $REDIS_PASSWORD cluster info
        echo ""
        echo "=== 节点信息 ==="
        redis-cli -c -p 7000 -a $REDIS_PASSWORD cluster nodes
        ;;
    "test")
        echo "=== 测试数据写入 ==="
        for i in {1..10}; do
            redis-cli -c -p 7000 -a $REDIS_PASSWORD set "test:$i" "value-$i"
        done
        
        echo "=== 测试数据读取 ==="
        for i in {1..10}; do
            redis-cli -c -p 7000 -a $REDIS_PASSWORD get "test:$i"
        done
        ;;
    "shutdown")
        echo "=== 关闭集群 ==="
        for port in 7000 7001 7002 7003 7004 7005; do
            redis-cli -p $port -a $REDIS_PASSWORD shutdown
        done
        ;;
    *)
        echo "用法: $0 {status|test|shutdown}"
        ;;
esac
EOF

chmod +x ~/redis-practice/cluster/cluster-manager.sh

# 测试集群
~/redis-practice/cluster/cluster-manager.sh status
~/redis-practice/cluster/cluster-manager.sh test

4 Redis Sentinel 哨兵架构

4.1 Redis Sentinel 核心命令详解

在使用 Sentinel 脚本之前,让我们先了解 Sentinel 的核心命令:

Sentinel 管理命令

 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
# 1. 启动 Sentinel 服务
redis-sentinel sentinel.conf         # 使用配置文件启动
redis-server sentinel.conf --sentinel # 更新的启动方式

# 2. Sentinel 监控命令
SENTINEL MASTERS                     # 查看所有被监控的主节点
SENTINEL MASTER mymaster             # 查看指定主节点的详细信息
SENTINEL SLAVES mymaster             # 查看主节点下的所有从节点
SENTINEL SENTINELS mymaster          # 查看监控同一主节点的其他 Sentinel
SENTINEL GET-MASTER-ADDR-BY-NAME mymaster # 获取主节点地址

# 3. 故障转移命令
SENTINEL FAILOVER mymaster           # 手动触发故障转移
SENTINEL CKQUORUM mymaster           # 检查故障转移条件
SENTINEL FLUSHCONFIG                 # 刷新配置到磁盘

# 4. 动态配置修改
SENTINEL MONITOR mymaster 127.0.0.1 6379 2  # 动态添加监控
SENTINEL REMOVE mymaster                     # 移除监控
SENTINEL SET mymaster down-after-milliseconds 10000  # 修改参数

# 5. 信息查询
SENTINEL PENDING-SCRIPTS             # 查看待执行的脚本
SENTINEL IS-MASTER-DOWN-BY-ADDR 127.0.0.1 6379 # 查询主节点是否下线
INFO sentinel                        # 查看 Sentinel 状态信息

# 6. Sentinel 配置文件关键参数
# sentinel monitor <master-name> <ip> <port> <quorum>
# sentinel auth-pass <master-name> <password>
# sentinel down-after-milliseconds <master-name> <milliseconds>
# sentinel parallel-syncs <master-name> <numreplicas>
# sentinel failover-timeout <master-name> <milliseconds>
# sentinel notification-script <master-name> <script-path>
# sentinel client-reconfig-script <master-name> <script-path>

手动配置 Sentinel 示例

 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
# 1. 准备主从架构(先启动 Redis 主从节点)
redis-server --port 6379 --requirepass redis123 --masterauth redis123 --daemonize yes
redis-server --port 6380 --requirepass redis123 --masterauth redis123 --daemonize yes
redis-cli -p 6380 -a redis123 REPLICAOF 127.0.0.1 6379

# 2. 创建 Sentinel 配置文件
cat > /tmp/sentinel-26379.conf << EOF
port 26379
dir /tmp
sentinel monitor mymaster 127.0.0.1 6379 2
sentinel auth-pass mymaster redis123
sentinel down-after-milliseconds mymaster 5000
sentinel parallel-syncs mymaster 1
sentinel failover-timeout mymaster 10000
requirepass sentinel123
EOF

# 3. 启动 Sentinel
redis-sentinel /tmp/sentinel-26379.conf &

# 4. 连接 Sentinel 并查看状态
redis-cli -p 26379 -a sentinel123
> SENTINEL MASTERS
> SENTINEL SLAVES mymaster

# 5. 模拟主节点故障(关闭主节点)
redis-cli -p 6379 -a redis123 DEBUG SEGFAULT  # 模拟崩溃
# 或者
redis-cli -p 6379 -a redis123 SHUTDOWN         # 正常关闭

# 6. 观察 Sentinel 日志,查看故障转移过程
tail -f /tmp/sentinel-26379.log

# 7. 查看新的主节点
redis-cli -p 26379 -a sentinel123 SENTINEL GET-MASTER-ADDR-BY-NAME mymaster

# 8. 测试新主节点是否可写入
NEW_MASTER_PORT=$(redis-cli -p 26379 -a sentinel123 SENTINEL GET-MASTER-ADDR-BY-NAME mymaster | tail -1)
redis-cli -p $NEW_MASTER_PORT -a redis123 SET failover-test "success"

Sentinel 客户端连接示例

 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
# Python 使用 Sentinel 的示例代码
cat > sentinel_client_example.py << 'EOF'
from redis.sentinel import Sentinel

# 连接 Sentinel
sentinel = Sentinel([('127.0.0.1', 26379), ('127.0.0.1', 26380)], 
                   socket_timeout=0.1,
                   password='sentinel123')

# 发现主节点
master = sentinel.master_for('mymaster', socket_timeout=0.1, password='redis123')

# 发现从节点
slave = sentinel.slave_for('mymaster', socket_timeout=0.1, password='redis123')

# 使用
master.set('foo', 'bar')
print(slave.get('foo'))
EOF

# Java 使用 Sentinel 的示例代码
cat > SentinelExample.java << 'EOF'
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisSentinelPool;
import java.util.HashSet;
import java.util.Set;

public class SentinelExample {
    public static void main(String[] args) {
        Set<String> sentinels = new HashSet<>();
        sentinels.add("127.0.0.1:26379");
        sentinels.add("127.0.0.1:26380");
        
        JedisSentinelPool pool = new JedisSentinelPool("mymaster", sentinels, "redis123");
        
        try (Jedis jedis = pool.getResource()) {
            jedis.set("test", "value");
            System.out.println(jedis.get("test"));
        }
        
        pool.close();
    }
}
EOF

4.2 架构说明

  • 1个主节点 + 2个从节点
  • 3个 Sentinel 哨兵节点监控主从节点
  • 自动故障发现和主从切换

准备 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
30
31
32
# 复用主从架构的配置,但需要修改一些参数
cp ~/redis-practice/master-slave/conf/* ~/redis-practice/sentinel/conf/

# 修改主节点配置以适配 Sentinel
cat > ~/redis-practice/sentinel/conf/redis-master.conf << 'EOF'
port 6379
bind 0.0.0.0
protected-mode no

dir /home/$(whoami)/redis-practice/sentinel/data/master
dbfilename dump-master.rdb
appendonly yes
appendfilename "appendonly-master.aof"

logfile /home/$(whoami)/redis-practice/sentinel/logs/redis-master.log
loglevel notice

# Sentinel 需要的配置
slave-serve-stale-data yes
slave-read-only yes
slave-priority 100

requirepass redis123
masterauth redis123

maxmemory 256mb
maxmemory-policy allkeys-lru
EOF

# 修改从节点配置
sed 's|master-slave|sentinel|g' ~/redis-practice/master-slave/conf/redis-slave1.conf > ~/redis-practice/sentinel/conf/redis-slave1.conf
sed 's|master-slave|sentinel|g' ~/redis-practice/master-slave/conf/redis-slave2.conf > ~/redis-practice/sentinel/conf/redis-slave2.conf

配置 Sentinel 哨兵

 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
# 创建 Sentinel 配置
for i in 1 2 3; do
    port=$((26378 + i))
    cat > ~/redis-practice/sentinel/conf/sentinel-$i.conf << EOF
# Sentinel 基本配置
port $port
bind 0.0.0.0
protected-mode no

# 工作目录
dir /home/$(whoami)/redis-practice/sentinel/data/sentinel-$i

# 日志配置
logfile /home/$(whoami)/redis-practice/sentinel/logs/sentinel-$i.log
loglevel notice

# 监控主节点配置
sentinel monitor mymaster 127.0.0.1 6379 2
sentinel auth-pass mymaster redis123

# 故障检测配置
sentinel down-after-milliseconds mymaster 5000
sentinel parallel-syncs mymaster 1
sentinel failover-timeout mymaster 10000

# Sentinel 认证
requirepass sentinel123

# 通知脚本 (可选)
# sentinel notification-script mymaster /path/to/notify.sh
# sentinel client-reconfig-script mymaster /path/to/reconfig.sh
EOF

    mkdir -p ~/redis-practice/sentinel/data/sentinel-$i
done

4.3 启动 Sentinel 架构

 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
# 创建修复版本的启动脚本
cat > ~/redis-practice/sentinel/start-sentinel-cluster.sh << 'EOF'
#!/bin/bash

BASE_DIR=~/redis-practice/sentinel

echo '=== 检查Redis安装状态 ==='
# 检查Redis是否安装
if ! command -v redis-server >/dev/null 2>&1; then
    echo '错误: redis-server 命令未找到!'
    echo '请先安装Redis:'
    echo '  Ubuntu/Debian: sudo apt install redis-server -y'
    echo '  CentOS/RHEL: sudo yum install redis -y'
    echo '  macOS: brew install redis'
    exit 1
fi

# 检查sentinel启动方式
SENTINEL_CMD=""
if command -v redis-sentinel >/dev/null 2>&1; then
    SENTINEL_CMD='redis-sentinel'
    echo '✅ 使用 redis-sentinel 命令启动哨兵'
else
    SENTINEL_CMD='redis-server --sentinel'
    echo '⚠️  redis-sentinel 命令不存在,使用 redis-server --sentinel 模式'
fi

echo "=== 创建数据目录 ==="
mkdir -p $BASE_DIR/data/{master,slave1,slave2}

echo "=== 启动 Redis 主从节点 ==="
redis-server $BASE_DIR/conf/redis-master.conf &
sleep 2
redis-server $BASE_DIR/conf/redis-slave1.conf &
redis-server $BASE_DIR/conf/redis-slave2.conf &

echo "=== 等待主从同步 ==="
sleep 5

# 验证主从节点启动状态
echo "=== 验证主从节点状态 ==="
for port in 6379 6380 6381; do
    if redis-cli -p $port -a redis123 ping >/dev/null 2>&1; then
        echo "✅ Redis节点 $port 启动成功"
    else
        echo "❌ Redis节点 $port 启动失败"
        exit 1
    fi
done

echo "=== 启动 Sentinel 哨兵 ==="
for i in 1 2 3; do
    port=$((26378 + i))
    echo "启动 Sentinel-$i (端口$port)"
    
    # 首先检查命令是否存在,然后启动
    if command -v redis-sentinel >/dev/null 2>&1; then
        echo "  使用 redis-sentinel 命令启动"
        redis-sentinel $BASE_DIR/conf/sentinel-$i.conf &
    elif command -v redis-server >/dev/null 2>&1; then
        echo "  使用 redis-server --sentinel 模式启动"
        redis-server $BASE_DIR/conf/sentinel-$i.conf --sentinel &
    else
        echo "  错误: 未找到 redis-sentinel 或 redis-server 命令"
        echo "  请检查 Redis 是否正确安装"
        exit 1
    fi
    sleep 2
    
    # 验证启动状态
    if redis-cli -p $port -a sentinel123 ping >/dev/null 2>&1; then
        echo "  ✅ Sentinel-$i 启动成功"
    else
        echo "  ⚠️  Sentinel-$i 可能未完全启动,请稍后检查"
    fi
done

echo "=== Sentinel 集群启动完成 ==="
sleep 3

# 验证Sentinel状态
echo "=== 验证 Sentinel 状态 ==="
for port in 26379 26380 26381; do
    if redis-cli -p $port -a sentinel123 ping >/dev/null 2>&1; then
        echo "✅ Sentinel $port 启动成功"
    else
        echo "⚠️  Sentinel $port 可能未完全启动,请稍等"
    fi
done

sleep 2
echo "=== 查看 Sentinel 状态 ==="
redis-cli -p 26379 -a sentinel123 sentinel masters 2>/dev/null || echo "Sentinel还在初始化中,请稍后手动检查"
EOF

chmod +x ~/redis-practice/sentinel/start-sentinel-cluster.sh

手动启动方案:

 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
# 手动启动方案
cat > ~/redis-practice/sentinel/manual-start-sentinel.sh << 'EOF'
#!/bin/bash

BASE_DIR=~/redis-practice/sentinel

echo "=== 手动启动 Sentinel 架构 ==="

# 步骤1: 启动Redis主从节点
echo "1. 启动Redis主从节点..."
redis-server $BASE_DIR/conf/redis-master.conf &
sleep 2
redis-server $BASE_DIR/conf/redis-slave1.conf &
sleep 2
redis-server $BASE_DIR/conf/redis-slave2.conf &
sleep 3

# 步骤2: 验证主从节点
echo "2. 验证主从节点状态..."
for port in 6379 6380 6381; do
    if redis-cli -p $port -a redis123 ping >/dev/null 2>&1; then
        echo "  ✅ Redis $port: OK"
    else
        echo "  ❌ Redis $port: 失败"
    fi
done

# 步骤3: 尝试不同的Sentinel启动方式
echo "3. 启动Sentinel哨兵..."
for i in 1 2 3; do
    port=$((26378 + i))
    echo "  启动 Sentinel-$i (端口$port)"
    
    # 方式1: 检查并使用redis-sentinel
    if command -v redis-sentinel >/dev/null 2>&1; then
        echo "    📍 检测到 redis-sentinel 命令,正在启动..."
        redis-sentinel $BASE_DIR/conf/sentinel-$i.conf &
        sleep 1
        # 验证启动是否成功
        if redis-cli -p $port -a sentinel123 ping >/dev/null 2>&1; then
            echo "    ✅ 使用 redis-sentinel 启动成功"
        else
            echo "    ❌ redis-sentinel 启动失败"
        fi
    else
        # 方式2: 使用redis-server --sentinel
        echo "    ⚠️  redis-sentinel 命令不存在,尝试 redis-server --sentinel"
        if command -v redis-server >/dev/null 2>&1; then
            redis-server $BASE_DIR/conf/sentinel-$i.conf --sentinel &
            sleep 1
            # 验证启动是否成功
            if redis-cli -p $port -a sentinel123 ping >/dev/null 2>&1; then
                echo "    ✅ 使用 redis-server --sentinel 启动成功"
            else
                echo "    ❌ redis-server --sentinel 启动失败"
            fi
        else
            echo "    ❌ redis-server 命令也不存在,无法启动 Sentinel"
        fi
    fi
    sleep 2
done

sleep 5

# 步骤4: 验证Sentinel状态
echo "4. 验证Sentinel状态..."
for port in 26379 26380 26381; do
    if redis-cli -p $port -a sentinel123 ping >/dev/null 2>&1; then
        echo "  ✅ Sentinel $port: OK"
    else
        echo "  ❌ Sentinel $port: 失败"
    fi
done

echo "=== 启动完成,运行以下命令检查状态 ==="
echo "redis-cli -p 26379 -a sentinel123 sentinel masters"
EOF

chmod +x ~/redis-practice/sentinel/manual-start-sentinel.sh

4.4 验证 Sentinel 功能

 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
# 创建 Sentinel 测试脚本
cat > ~/redis-practice/sentinel/test-sentinel.sh << 'EOF'
#!/bin/bash

SENTINEL_PASSWORD="sentinel123"
REDIS_PASSWORD="redis123"

echo "=== 1. 查看当前主节点 ==="
redis-cli -p 26379 -a $SENTINEL_PASSWORD sentinel get-master-addr-by-name mymaster

echo -e "\n=== 2. 查看所有监控的主节点 ==="
redis-cli -p 26379 -a $SENTINEL_PASSWORD sentinel masters

echo -e "\n=== 3. 查看从节点信息 ==="
redis-cli -p 26379 -a $SENTINEL_PASSWORD sentinel slaves mymaster

echo -e "\n=== 4. 查看其他 Sentinel 节点 ==="
redis-cli -p 26379 -a $SENTINEL_PASSWORD sentinel sentinels mymaster

echo -e "\n=== 5. 测试数据写入主节点 ==="
redis-cli -p 6379 -a $REDIS_PASSWORD set sentinel-test "Hello Sentinel"

echo -e "\n=== 6. 从从节点读取数据 ==="
redis-cli -p 6380 -a $REDIS_PASSWORD get sentinel-test
redis-cli -p 6381 -a $REDIS_PASSWORD get sentinel-test

echo -e "\n=== 7. 模拟主节点故障 ==="
echo "将要关闭主节点 (端口 6379),观察 Sentinel 的故障转移..."
read -p "按 Enter 继续..." 

redis-cli -p 6379 -a $REDIS_PASSWORD debug segfault || redis-cli -p 6379 -a $REDIS_PASSWORD shutdown

echo -e "\n=== 8. 等待故障转移完成 ==="
sleep 10

echo -e "\n=== 9. 查看新的主节点 ==="
redis-cli -p 26379 -a $SENTINEL_PASSWORD sentinel get-master-addr-by-name mymaster

echo -e "\n=== 10. 验证新主节点可写入 ==="
NEW_MASTER=$(redis-cli -p 26379 -a $SENTINEL_PASSWORD sentinel get-master-addr-by-name mymaster | head -1)
NEW_PORT=$(redis-cli -p 26379 -a $SENTINEL_PASSWORD sentinel get-master-addr-by-name mymaster | tail -1)

redis-cli -h $NEW_MASTER -p $NEW_PORT -a $REDIS_PASSWORD set failover-test "Master switched successfully"
redis-cli -h $NEW_MASTER -p $NEW_PORT -a $REDIS_PASSWORD get failover-test
EOF

chmod +x ~/redis-practice/sentinel/test-sentinel.sh
~/redis-practice/sentinel/test-sentinel.sh

5 监控和管理工具

5.1 Redis 核心监控命令详解

在编写监控脚本之前,让我们先了解 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
30
31
32
33
34
35
36
37
38
39
40
# 1. 基本信息查询
INFO                                 # 获取所有服务器信息
INFO server                          # 服务器基本信息
INFO memory                          # 内存使用信息
INFO replication                     # 复制相关信息
INFO persistence                     # 持久化信息
INFO stats                           # 统计信息
INFO clients                         # 客户端连接信息
INFO cpu                             # CPU 使用信息
INFO cluster                         # 集群信息
INFO keyspace                        # 键空间信息

# 2. 性能监控命令
MONITOR                              # 实时监控所有命令
SLOWLOG GET [count]                  # 获取慢查询日志
SLOWLOG LEN                          # 获取慢查询日志长度
SLOWLOG RESET                        # 清空慢查询日志
CLIENT LIST                          # 列出所有客户端连接
CLIENT KILL [ip:port]                # 杀死指定客户端连接

# 3. 内存分析命令
MEMORY USAGE <key>                   # 查看键的内存使用量
MEMORY STATS                         # 内存统计信息
MEMORY DOCTOR                        # 内存诊断建议
DBSIZE                               # 当前数据库键的数量
LASTSAVE                             # 最后一次保存到磁盘的时间

# 4. 配置管理命令
CONFIG GET <parameter>               # 获取配置参数
CONFIG SET <parameter> <value>       # 设置配置参数
CONFIG REWRITE                       # 将配置写入配置文件
CONFIG RESETSTAT                     # 重置统计信息

# 5. 数据库操作命令
SELECT <db>                          # 选择数据库
FLUSHDB                              # 清空当前数据库
FLUSHALL                             # 清空所有数据库
SAVE                                 # 同步保存数据到磁盘
BGSAVE                               # 异步保存数据到磁盘
BGREWRITEAOF                         # 异步重写AOF文件

实用监控脚本示例

 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
# 创建综合监控脚本
cat > ~/redis-practice/redis-health-check.sh << 'EOF'
#!/bin/bash

# 单个Redis实例健康检查函数
check_redis_health() {
    local host=$1
    local port=$2
    local password=$3
    local name=$4
    
    echo "=== $name 健康检查 ==="
    
    # 连接测试
    if ! redis-cli -h $host -p $port -a $password ping >/dev/null 2>&1; then
        echo "❌ 连接失败"
        return 1
    fi
    
    # 获取详细信息
    local info=$(redis-cli -h $host -p $port -a $password info 2>/dev/null)
    
    # 基本信息
    echo "Redis版本: $(echo "$info" | grep redis_version | cut -d: -f2 | tr -d '\r')"
    echo "运行模式: $(echo "$info" | grep redis_mode | cut -d: -f2 | tr -d '\r')"
    echo "进程ID: $(echo "$info" | grep process_id | cut -d: -f2 | tr -d '\r')"
    
    # 运行时间
    local uptime=$(echo "$info" | grep uptime_in_seconds | cut -d: -f2 | tr -d '\r')
    echo "运行时间: $((uptime/3600))小时 $(((uptime%3600)/60))分钟"
    
    # 内存使用
    echo "内存使用: $(echo "$info" | grep used_memory_human | cut -d: -f2 | tr -d '\r')"
    echo "内存峰值: $(echo "$info" | grep used_memory_peak_human | cut -d: -f2 | tr -d '\r')"
    
    # 连接数
    echo "连接客户端: $(echo "$info" | grep connected_clients | cut -d: -f2 | tr -d '\r')"
    
    # 命令统计
    echo "总命令数: $(echo "$info" | grep total_commands_processed | cut -d: -f2 | tr -d '\r')"
    
    # 键空间信息
    local keyspace=$(echo "$info" | grep "^db0:" | cut -d: -f2 | tr -d '\r')
    if [ ! -z "$keyspace" ]; then
        echo "数据库0: $keyspace"
    fi
    
    # 持久化状态
    echo "上次保存: $(date -d @$(echo "$info" | grep rdb_last_save_time | cut -d: -f2 | tr -d '\r'))"
    
    # 复制状态(如果是主从架构)
    local role=$(echo "$info" | grep "role:" | cut -d: -f2 | tr -d '\r')
    echo "节点角色: $role"
    
    if [ "$role" = "master" ]; then
        local slaves=$(echo "$info" | grep connected_slaves | cut -d: -f2 | tr -d '\r')
        echo "连接从节点: $slaves"
    elif [ "$role" = "slave" ]; then
        local master_link=$(echo "$info" | grep master_link_status | cut -d: -f2 | tr -d '\r')
        echo "主节点连接: $master_link"
    fi
    
    # 慢查询检查
    local slow_queries=$(redis-cli -h $host -p $port -a $password slowlog len 2>/dev/null)
    if [ "$slow_queries" -gt 0 ]; then
        echo "⚠️  慢查询: $slow_queries 条"
    fi
    
    echo "✅ 健康检查完成"
    echo ""
EOF

chmod +x ~/redis-practice/redis-health-check.sh

5.2 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
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
cat > ~/redis-practice/redis-monitor.sh << 'EOF'
#!/bin/bash

monitor_redis() {
    local host=$1
    local port=$2
    local password=$3
    local name=$4
    
    echo "=== $name ($host:$port) ==="
    
    # 检查连接
    if redis-cli -h $host -p $port -a $password ping >/dev/null 2>&1; then
        echo "✅ 连接状态: 正常"
        
        # 获取基本信息
        info=$(redis-cli -h $host -p $port -a $password info server,memory,clients 2>/dev/null)
        
        echo "Redis 版本: $(echo "$info" | grep redis_version | cut -d: -f2 | tr -d '\r')"
        echo "运行时间: $(echo "$info" | grep uptime_in_seconds | cut -d: -f2 | tr -d '\r') 秒"
        echo "内存使用: $(echo "$info" | grep used_memory_human | cut -d: -f2 | tr -d '\r')"
        echo "连接客户端: $(echo "$info" | grep connected_clients | cut -d: -f2 | tr -d '\r')"
        
        # 检查角色
        role=$(redis-cli -h $host -p $port -a $password info replication 2>/dev/null | grep "role:" | cut -d: -f2 | tr -d '\r')
        echo "节点角色: $role"
        
    else
        echo "❌ 连接状态: 失败"
    fi
    echo ""
}

echo "Redis 架构监控报告"
echo "===================="
echo "生成时间: $(date)"
echo ""

echo "1. 主从架构监控"
echo "----------------"
monitor_redis 127.0.0.1 6379 redis123 "主节点"
monitor_redis 127.0.0.1 6380 redis123 "从节点1"
monitor_redis 127.0.0.1 6381 redis123 "从节点2"

echo "2. 集群架构监控"
echo "----------------"
for port in 7000 7001 7002 7003 7004 7005; do
    monitor_redis 127.0.0.1 $port redis123 "集群节点-$port"
done

echo "3. Sentinel 监控"
echo "----------------"
for port in 26379 26380 26381; do
    if redis-cli -p $port -a sentinel123 ping >/dev/null 2>&1; then
        echo "✅ Sentinel-$port: 正常运行"
        masters=$(redis-cli -p $port -a sentinel123 sentinel masters 2>/dev/null | grep -c "name")
        echo "   监控主节点数: $masters"
    else
        echo "❌ Sentinel-$port: 连接失败"
    fi
done
EOF

chmod +x ~/redis-practice/redis-monitor.sh

5.3 清理脚本

 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
cat > ~/redis-practice/cleanup.sh << 'EOF'
#!/bin/bash

echo "=== Redis 架构练习清理脚本 ==="

echo "正在停止所有 Redis 进程..."

# 停止 Redis 实例
for port in 6379 6380 6381 7000 7001 7002 7003 7004 7005; do
    redis-cli -p $port -a redis123 shutdown 2>/dev/null || true
done

# 停止 Sentinel 实例
for port in 26379 26380 26381; do
    redis-cli -p $port -a sentinel123 shutdown 2>/dev/null || true
done

# 强制杀死可能残留的进程
pkill -f redis-server 2>/dev/null || true
pkill -f redis-sentinel 2>/dev/null || true

echo "正在清理数据文件..."
rm -rf ~/redis-practice/*/data/*
rm -rf ~/redis-practice/*/logs/*

echo "清理完成!"
echo "如需重新开始,请重新运行相应的启动脚本。"
EOF

chmod +x ~/redis-practice/cleanup.sh

6 性能测试

6.1 Redis 性能测试核心命令

在使用性能测试脚本之前,让我们先了解 redis-benchmark 的核心参数:

redis-benchmark 命令详解

 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
# 1. 基本用法
redis-benchmark [options]            # 基本命令格式

# 2. 连接相关参数
-h <hostname>                        # Redis服务器地址(默认127.0.0.1)
-p <port>                            # Redis服务器端口(默认6379)
-a <password>                        # Redis密码
-s <socket>                          # Unix socket连接

# 3. 测试参数
-c <clients>                         # 并发客户端数量(默认50)
-n <requests>                        # 总请求数(默认10000)
-d <size>                            # 数据大小(字节,默认3)
-t <tests>                           # 指定要测试的命令(用逗号分隔)
-r <keyspacelen>                     # 使用随机键,指定键空间大小

# 4. 输出格式
--csv                                # CSV格式输出
-q                                   # 简化输出
--latency                            # 延迟相关统计
--latency-history                    # 延迟历史记录
--latency-dist                       # 延迟分布统计

# 5. 特殊选项
-i <interval>                        # 间隔时间(秒)
-l                                   # 循环测试
-P <pipeline>                        # 使用管道模式
--cluster                            # 集群模式
-e                                   # 在错误时显示错误信息

# 6. 常用测试命令
SET                                  # 设置键值
GET                                  # 获取键值
INCR                                 # 递增
LPUSH                                # 列表推入
RPUSH                                # 列表推入
LPOP                                 # 列表弹出
RPOP                                 # 列表弹出
SADD                                 # 集合添加
HSET                                 # 哈希设置
SPOP                                 # 集合弹出
ZADD                                 # 有序集合添加
ZREVRANGE                            # 有序集合范围查询
MSET                                 # 批量设置

实用性能测试示例

 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
# 1. 基本性能测试
redis-benchmark -h 127.0.0.1 -p 6379 -a redis123 -c 50 -n 10000

# 2. 指定命令测试
redis-benchmark -h 127.0.0.1 -p 6379 -a redis123 -t set,get -n 100000 -c 100

# 3. 不同数据大小测试
redis-benchmark -h 127.0.0.1 -p 6379 -a redis123 -t set,get -n 10000 -d 1024 -c 50

# 4. 管道模式测试
redis-benchmark -h 127.0.0.1 -p 6379 -a redis123 -t set,get -n 10000 -P 10

# 5. 随机键测试
redis-benchmark -h 127.0.0.1 -p 6379 -a redis123 -t set,get -n 10000 -r 1000

# 6. 集群模式测试
redis-benchmark -h 127.0.0.1 -p 7000 -a redis123 -t set,get -n 10000 --cluster

# 7. 延迟测试
redis-cli -h 127.0.0.1 -p 6379 -a redis123 --latency
redis-cli -h 127.0.0.1 -p 6379 -a redis123 --latency-history -i 1
redis-cli -h 127.0.0.1 -p 6379 -a redis123 --latency-dist

# 8. 内存使用分析
redis-cli -h 127.0.0.1 -p 6379 -a redis123 --bigkeys
redis-cli -h 127.0.0.1 -p 6379 -a redis123 --hotkeys  # 需要开启 maxmemory-policy

# 9. 综合性能分析
redis-benchmark -h 127.0.0.1 -p 6379 -a redis123 -t set,get,incr,lpush,rpush,lpop,rpop,sadd,hset,spop,zadd,zrevrange,mset -n 100000 -c 50 --csv

# 10. 对比测试脚本
cat > ~/redis-practice/performance-compare.sh << 'EOF'
#!/bin/bash

echo "Redis 性能对比测试"
echo "===================="

# 测试参数
TEST_COUNT=50000
CONCURRENCY=50
DATA_SIZE=100
PASSWORD="redis123"

# 测试单机Redis
echo "1. 单机 Redis 性能测试 (6379)"
echo "--------------------------------"
redis-benchmark -h 127.0.0.1 -p 6379 -a $PASSWORD -t set,get -n $TEST_COUNT -c $CONCURRENCY -d $DATA_SIZE -q

# 测试从节点读性能
echo -e "\n2. 从节点读性能测试 (6380)"
echo "--------------------------------"
redis-benchmark -h 127.0.0.1 -p 6380 -a $PASSWORD -t get -n $TEST_COUNT -c $CONCURRENCY -d $DATA_SIZE -q

# 测试集群性能
echo -e "\n3. 集群模式性能测试 (7000)"
echo "--------------------------------"
redis-benchmark -h 127.0.0.1 -p 7000 -a $PASSWORD -t set,get -n $TEST_COUNT -c $CONCURRENCY -d $DATA_SIZE --cluster -q 2>/dev/null

# 管道模式测试
echo -e "\n4. 管道模式性能测试"
echo "--------------------------------"
redis-benchmark -h 127.0.0.1 -p 6379 -a $PASSWORD -t set,get -n $TEST_COUNT -c $CONCURRENCY -d $DATA_SIZE -P 10 -q

echo -e "\n测试完成!"
EOF

chmod +x ~/redis-practice/performance-compare.sh

6.2 基准测试脚本

 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
cat > ~/redis-practice/benchmark.sh << 'EOF'
#!/bin/bash

echo "=== Redis 性能测试 ==="

test_single() {
    local host=$1
    local port=$2
    local password=$3
    local name=$4
    
    echo "测试 $name ($host:$port)"
    echo "------------------------"
    
    redis-benchmark -h $host -p $port -a $password -t set,get -n 10000 -c 50 -d 100 --csv | \
    while IFS=, read test ops_per_sec; do
        echo "$test: $ops_per_sec 操作/秒"
    done
    echo ""
}

test_cluster() {
    echo "测试 Redis 集群"
    echo "----------------"
    redis-benchmark -h 127.0.0.1 -p 7000 -a redis123 -t set,get -n 10000 -c 50 -d 100 --cluster --csv | \
    while IFS=, read test ops_per_sec; do
        echo "$test: $ops_per_sec 操作/秒"
    done
    echo ""
}

echo "1. 单实例性能测试"
test_single 127.0.0.1 6379 redis123 "主节点"

echo "2. 集群性能测试"
test_cluster

echo "3. 延迟测试"
echo "------------"
redis-cli -h 127.0.0.1 -p 6379 -a redis123 --latency -i 1 &
LATENCY_PID=$!
sleep 5
kill $LATENCY_PID
EOF

chmod +x ~/redis-practice/benchmark.sh

7 快速操作命令总结

7.1 核心命令速查表

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
30
31
# 启动和连接
redis-server [config_file]           # 启动Redis服务器
redis-cli -h host -p port -a password # 连接Redis
redis-cli --cluster create ...       # 创建集群
redis-sentinel sentinel.conf         # 启动Sentinel

# 信息查询
INFO [section]                       # 获取服务器信息
PING                                 # 测试连接
DBSIZE                               # 获取键数量
CONFIG GET parameter                 # 获取配置
SLOWLOG GET [count]                  # 获取慢查询日志

# 主从复制
REPLICAOF host port                  # 设置主从关系(Redis 5.0+)
SLAVEOF host port                    # 设置主从关系(Redis 4.x)
SLAVEOF NO ONE                       # 取消主从关系

# 集群管理
CLUSTER NODES                        # 查看集群节点
CLUSTER INFO                         # 查看集群状态
CLUSTER MEET ip port                 # 加入节点到集群
CLUSTER ADDSLOTS slot...             # 分配槽位

# Sentinel 管理
SENTINEL MASTERS                     # 查看监控的主节点
SENTINEL GET-MASTER-ADDR-BY-NAME name # 获取主节点地址
SENTINEL FAILOVER name               # 手动故障转移

# 性能测试
redis-benchmark -h host -p port -a password -t tests -n requests -c clients

7.2 实用命令速查手册

日常运维命令

 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
# 1. 服务状态检查
ps aux | grep redis                  # 查看Redis进程
netstat -tlnp | grep redis           # 查看Redis端口
redis-cli -p 6379 -a password ping  # 测试连接

# 2. 数据备份和恢复
redis-cli -p 6379 -a password SAVE        # 同步备份
redis-cli -p 6379 -a password BGSAVE      # 异步备份
redis-cli -p 6379 -a password BGREWRITEAOF # 重写AOF
cp /path/to/dump.rdb /backup/location     # 备份数据文件

# 3. 内存管理
redis-cli -p 6379 -a password MEMORY USAGE key     # 查看键内存使用
redis-cli -p 6379 -a password --bigkeys            # 查找大键
redis-cli -p 6379 -a password FLUSHDB              # 清空当前数据库
redis-cli -p 6379 -a password FLUSHALL             # 清空所有数据库

# 4. 客户端管理
redis-cli -p 6379 -a password CLIENT LIST          # 列出所有客户端
redis-cli -p 6379 -a password CLIENT KILL ip:port  # 关闭指定客户端
redis-cli -p 6379 -a password MONITOR              # 监控所有命令

# 5. 配置管理
redis-cli -p 6379 -a password CONFIG GET '*'       # 获取所有配置
redis-cli -p 6379 -a password CONFIG SET parameter value  # 设置配置
redis-cli -p 6379 -a password CONFIG REWRITE       # 保存配置到文件

# 6. 性能监控
redis-cli -p 6379 -a password --latency           # 延迟监控
redis-cli -p 6379 -a password --stat              # 实时统计
redis-cli -p 6379 -a password --scan --pattern 'user:*'  # 扫描匹配键

故障排查命令

 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
# 1. 日志分析
tail -f /path/to/redis.log              # 实时查看日志
grep ERROR /path/to/redis.log           # 查找错误日志
grep WARNING /path/to/redis.log         # 查找警告日志

# 2. 连接问题排查
telnet 127.0.0.1 6379                  # 测试TCP连接
redis-cli -h host -p port ping          # 测试Redis连接
nmap -p 6379 host                       # 测试端口开放

# 3. 内存问题排查
redis-cli -p 6379 -a password INFO memory        # 内存使用情况
redis-cli -p 6379 -a password MEMORY DOCTOR      # 内存诊断
redis-cli -p 6379 -a password --bigkeys          # 查找大键

# 4. 性能问题排查
redis-cli -p 6379 -a password SLOWLOG GET 10     # 查看慢查询
redis-cli -p 6379 -a password --latency-history  # 延迟历史
redis-cli -p 6379 -a password INFO stats         # 统计信息

# 5. 主从同步问题
redis-cli -p 6379 -a password INFO replication   # 主节点复制信息
redis-cli -p 6380 -a password INFO replication   # 从节点复制信息
redis-cli -p 6380 -a password REPLICAOF 127.0.0.1 6379  # 重新建立主从关系

# 6. 集群问题排查
redis-cli -c -p 7000 -a password CLUSTER NODES   # 集群节点状态
redis-cli -c -p 7000 -a password CLUSTER INFO    # 集群整体状态
redis-cli --cluster check 127.0.0.1:7000 -a password  # 集群健康检查

8 学习要点和最佳实践

8.1 主从复制架构

  • 优势: 读写分离,提高读性能
  • 劣势: 主节点单点故障,需手动切换
  • 适用场景: 读多写少的应用

8.2 Cluster 集群架构

  • 优势: 水平扩展,自动分片,高可用
  • 劣势: 复杂性高,某些命令限制
  • 适用场景: 大数据量,高并发应用

8.3 Sentinel 哨兵架构

  • 优势: 自动故障转移,监控报警
  • 劣势: 额外的运维复杂性
  • 适用场景: 对可用性要求高的应用

8.4 配置要点

  • 密码认证:生产环境必须配置
  • 持久化:根据业务需求选择 RDB 或 AOF
  • 内存管理:设置合适的最大内存和淘汰策略
  • 网络安全:绑定合适的网络接口

8.5 常见问题解决方案

问题: “Connection refused”

1
2
3
4
5
6
7
8
9
# 检查端口占用
netstat -tlnp | grep :6379

# 检查防火墙
sudo ufw status  # Ubuntu
sudo firewall-cmd --list-ports  # CentOS

# 检查Redis进程
ps aux | grep redis

问题: “NOAUTH Authentication required”

1
2
3
# 检查密码配置
redis-cli -p 6379 -a redis123 ping
redis-cli -p 26379 -a sentinel123 ping

问题: “集群节点无法通信”

1
2
3
4
5
6
7
# 检查集群端口
for port in 7000 7001 7002 7003 7004 7005; do
    redis-cli -p $port -a redis123 ping
done

# 检查集群状态
redis-cli -c -p 7000 -a redis123 cluster nodes

8.6 监控指标

  • 内存使用率
  • 连接数
  • 命令执行延迟
  • 主从同步延迟
  • 集群槽位分布