← 返回最佳实践列表

*Redis 生产环境部署与配置最佳实践:从单机到集群的完整运维指南

本文基于 Redis 7.x 版本,系统总结从单机开发环境到大规模生产集群的部署、配置、安全和高可用最佳实践,帮助运维团队构建稳定、高效、可扩展的 Redis 基础设施。


*目录


*一、概述:为什么生产环境部署不能"开箱即用"

Redis 以"简单、快速"著称,单机版 make && make install 后启动即可使用。但在生产环境中,这种"开箱即用"的方式会带来严重的稳定性风险:

  • 内存失控:默认配置不限制内存,数据持续增长可能导致 OOM 被系统 Kill
  • 持久化缺失:默认关闭 AOF,RDB 快照策略也很宽松,故障后数据大量丢失
  • 安全裸奔:无密码、无 ACL、绑定所有网卡,任何客户端均可访问
  • 单点故障:单机故障 = 服务完全不可用,没有自动切换机制
  • 性能瓶颈:默认配置未针对高并发优化,连接数、缓冲区、内核参数都可能成为瓶颈

本文从硬件选型 → 单机配置 → 主从架构 → Sentinel 高可用 → Cluster 集群 → 安全加固 → 监控告警的全链路出发,提供可直接落地的生产部署方案。

适用版本:Redis 7.0+(部分功能如 ACL、多线程 I/O 需要 6.0+)


*二、硬件与系统环境准备

*2.1 服务器选型建议

组件 最低配置 推荐配置 说明
CPU 4 核 8 核+ Redis 单线程命令执行,但 6.0+ 多线程 I/O 和后台任务需要更多核心
内存 8GB 32GB+ 留 50% 余量给系统、副本、缓冲区;建议 maxmemory 设置为物理内存的 70%
磁盘 SSD 100GB NVMe SSD 500GB+ AOF 和 RDB 对磁盘 I/O 敏感,禁止机械盘
网卡 千兆 万兆 主从复制和 Cluster 节点间通信需要高带宽

*2.2 操作系统调优

# 1. 关闭透明大页(THP)—— Redis 强烈建议关闭
echo never > /sys/kernel/mm/transparent_hugepage/enabled
echo never > /sys/kernel/mm/transparent_hugepage/defrag

# 永久关闭(写入 /etc/rc.local 或 systemd 服务)
cat >> /etc/rc.local << 'EOF'
if test -f /sys/kernel/mm/transparent_hugepage/enabled; then
    echo never > /sys/kernel/mm/transparent_hugepage/enabled
fi
EOF

# 2. 调整内核参数——内存和网络优化
# 增大 TCP 连接队列
echo 'net.core.somaxconn = 65535' >> /etc/sysctl.conf
# 增大端口范围和 TCP 回收
echo 'net.ipv4.ip_local_port_range = 1024 65535' >> /etc/sysctl.conf
echo 'net.ipv4.tcp_max_syn_backlog = 65535' >> /etc/sysctl.conf
# 内存分配策略
echo 'vm.overcommit_memory = 1' >> /etc/sysctl.conf
# 禁用交换(Redis 内存数据不应该被换出)
echo 'vm.swappiness = 0' >> /etc/sysctl.conf

sysctl -p

# 3. 文件描述符限制
# Redis 默认最多 10000 客户端,系统限制要足够高
cat >> /etc/security/limits.conf << 'EOF'
redis soft nofile 65535
redis hard nofile 65535
EOF

# 4. 文件系统选择——XFS 优先于 ext4
# XFS 在大文件和并发 I/O 上性能更好,适合 AOF 和 RDB 场景
mkfs.xfs -f /dev/sdb1
mount /dev/sdb1 /var/lib/redis

*2.3 目录规划

# 建议目录结构
/opt/redis/7.0.12/          # 安装目录
├── bin/redis-server        # 二进制文件
├── bin/redis-cli
├── etc/redis.conf          # 主配置文件
├── data/                   # 数据目录(RDB/AOF)
├── logs/                   # 日志目录
└── scripts/                # 运维脚本

# 权限设置
chown -R redis:redis /opt/redis/
chmod 750 /opt/redis/data

*三、单机部署最佳实践

*3.1 最小生产配置(redis.conf)

# =====================================
# Redis 7.0 生产环境最小安全配置
# =====================================

# ---- 网络绑定 ----
bind 127.0.0.1 10.0.0.10           # 绑定内网 IP,禁止外网访问
port 6379
protected-mode yes                   # 保护模式:无密码时仅允许本地访问
tcp-backlog 65535                    # 与系统 somaxconn 一致

# ---- 安全认证 ----
requirepass "YourStrongPassword123!" # 强密码,至少 16 位混合字符
# 禁用危险命令
rename-command FLUSHALL ""           # 彻底禁用
rename-command FLUSHDB  ""           # 彻底禁用
rename-command CONFIG  "config_9a8b7c6d"  # 重命名,保留运维使用
rename-command DEBUG   "debug_1a2b3c4d"   # 重命名
rename-command SHUTDOWN ""           # 禁用 SHUTDOWN,通过 systemd 管理

# ---- 内存管理 ----
maxmemory 22gb                       # 32GB 物理内存,设置为 70%
maxmemory-policy allkeys-lru         # 内存满时淘汰最近最少使用的 Key
# 避免写入失败,volatile 策略在 Key 无过期时间会拒绝写入

# ---- 持久化配置 ----
# RDB 配置(灾难恢复,快速重启)
save 900 1                           # 15 分钟内有 1 次修改则触发
save 300 10                          # 5 分钟内有 10 次修改则触发
save 60 10000                        # 1 分钟内有 10000 次修改则触发
stop-writes-on-bgsave-error yes      # RDB 失败时停止写入,保护数据一致性
rdbcompression yes                   # 启用压缩
rdbchecksum yes                      # 启用 CRC64 校验
dbfilename dump.rdb

# AOF 配置(数据安全,故障丢失 < 1 秒)
appendonly yes
appendfilename "appendonly.aof"
appendfsync everysec                 # 每秒刷盘,平衡性能与安全
no-appendfsync-on-rewrite yes        # 重写期间不强制刷盘,减少阻塞
auto-aof-rewrite-percentage 100      # AOF 增长 100% 时触发重写
auto-aof-rewrite-min-size 64mb       # 最小重写体积
aof-load-truncated yes               # 启动时允许截断损坏的 AOF

# ---- 慢查询日志 ----
slowlog-log-slower-than 10000         # 10ms 以上为慢查询
slowlog-max-len 1000                 # 保留 1000 条慢查询记录

# ---- 客户端连接 ----
maxclients 10000                     # 最大连接数
client-output-buffer-limit normal 0 0 0   # 普通客户端不限制
client-output-buffer-limit replica 256mb 64mb 60  # 从节点缓冲区
client-output-buffer-limit pubsub 32mb 8mb 60   # 发布订阅缓冲区

# ---- 高级配置 ----
# 后台删除(Redis 4.0+ 必须开启)
lazyfree-lazy-eviction yes
lazyfree-lazy-expire yes
lazyfree-lazy-server-del yes
lazyfree-lazy-user-del yes

# 多线程 I/O(Redis 6.0+,CPU 多核时启用)
io-threads-do-reads yes
io-threads 4                         # 不超过 CPU 核心数

# 日志配置
loglevel notice
logfile "/opt/redis/7.0.12/logs/redis-server.log"

*3.2 启动与验证

# 启动 Redis(使用 systemd 管理)
systemctl start redis-server
systemctl enable redis-server

# 验证配置
redis-cli -h 10.0.0.10 -a "YourStrongPassword123!" INFO SERVER
# 检查版本、启动时间、配置加载状态

redis-cli -h 10.0.0.10 -a "YourStrongPassword123!" CONFIG GET maxmemory
# 确认配置生效

# 验证持久化
redis-cli -h 10.0.0.10 -a "YourStrongPassword123!" BGSAVE
# 检查日志:Background saving started by pid xxx
# 检查 /opt/redis/7.0.12/data/dump.rdb 生成

# 压测验证(可选)
redis-benchmark -h 10.0.0.10 -a "YourStrongPassword123!" -t set,get -n 100000 -c 50

*四、主从复制架构部署

*4.1 架构说明

主从复制架构是 Redis 高可用的基础。一个主节点负责读写,多个从节点复制数据并分担读流量。当主节点故障时,需要手动或借助 Sentinel 将从节点提升为主节点。

*4.2 主节点配置(在单机配置基础上补充)

# 主节点额外配置
# 启用密码验证从节点(双向认证)
masterauth "YourStrongPassword123!"

# 复制相关配置
repl-diskless-sync yes               # 无磁盘复制,减少磁盘 I/O
repl-diskless-sync-delay 5           # 延迟 5 秒,等待更多从节点连接
repl-ping-replica-period 10          # 心跳检测周期
repl-timeout 60                      # 复制超时时间
disable-thp yes                      # 禁用透明大页(已做系统级配置)

*4.3 从节点配置

# 从节点完整配置(基于主节点配置修改)
# 绑定从节点 IP
bind 127.0.0.1 10.0.0.11

# 主从复制配置
replicaof 10.0.0.10 6379             # 指向主节点
masterauth "YourStrongPassword123!"  # 主节点密码

# 从节点只读(默认 yes,必须保持)
replica-read-only yes

# 复制缓冲区大小(根据网络带宽调整)
repl-backlog-size 100mb              # 复制积压缓冲区,用于部分重同步
repl-backlog-ttl 3600                # 缓冲区保留 1 小时

# 从节点数据一致性配置
replica-serve-stale-data yes         # 同步期间仍然响应旧数据
replica-priority 100               # 故障转移优先级(数字小优先)

*4.4 启动与验证

# 从节点启动
redis-server /opt/redis/7.0.12/etc/redis-slave.conf

# 验证复制状态
redis-cli -h 10.0.0.10 -a "YourStrongPassword123!" INFO REPLICATION
# 输出示例:
# role:master
# connected_slaves:2
# slave0:ip=10.0.0.11,port=6379,state=online,offset=123456,lag=0
# slave1:ip=10.0.0.12,port=6379,state=online,offset=123456,lag=0

redis-cli -h 10.0.0.11 -a "YourStrongPassword123!" INFO REPLICATION
# 输出示例:
# role:slave
# master_host:10.0.0.10
# master_port:6379
# master_link_status:up
# master_last_io_seconds_ago:0
# master_sync_in_progress:0

*4.5 应用层读写分离(Java Jedis)

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

public class ReadWriteSplit {
    private JedisPool masterPool;
    private JedisPool slavePool;

    public ReadWriteSplit() {
        JedisPoolConfig config = new JedisPoolConfig();
        config.setMaxTotal(100);
        config.setMaxIdle(20);

        // 主节点连接池(写操作)
        masterPool = new JedisPool(config, "10.0.0.10", 6379, 2000, "YourStrongPassword123!");

        // 从节点连接池(读操作)—— 生产环境使用连接池或负载均衡
        slavePool = new JedisPool(config, "10.0.0.11", 6379, 2000, "YourStrongPassword123!");
    }

    public String get(String key) {
        try (Jedis slave = slavePool.getResource()) {
            return slave.get(key);
        }
    }

    public void set(String key, String value) {
        try (Jedis master = masterPool.getResource()) {
            master.set(key, value);
        }
    }

    public void close() {
        masterPool.close();
        slavePool.close();
    }

    public static void main(String[] args) {
        ReadWriteSplit client = new ReadWriteSplit();
        client.set("test:rw", "hello");
        System.out.println(client.get("test:rw"));
        client.close();
    }
}

*五、Redis Sentinel 高可用部署

*5.1 架构说明

Redis Sentinel 提供自动故障检测、自动故障转移和配置通知。最少需要 3 个 Sentinel 节点,避免单点判定问题(类似 ZooKeeper 的半数机制)。

*5.2 Sentinel 配置(sentinel.conf)

# =====================================
# Sentinel 配置(3 节点相同配置,仅修改 IP)
# =====================================

port 26379
bind 10.0.0.20 127.0.0.1           # 根据节点 IP 修改

# 监控主节点(2 表示至少 2 个 Sentinel 同意才判定故障)
sentinel monitor mymaster 10.0.0.10 6379 2

# 主节点认证
sentinel auth-pass mymaster YourStrongPassword123!

# 故障判定时间(5 秒未响应则判定主观下线)
sentinel down-after-milliseconds mymaster 5000

# 故障转移超时
sentinel failover-timeout mymaster 60000

# 并行同步从节点数(1 表示每次只同步 1 个从节点,减少压力)
sentinel parallel-syncs mymaster 1

# 通知脚本(可选,接入企业告警)
sentinel notification-script mymaster /opt/redis/scripts/notify.sh

# 故障转移后脚本(可选,更新 DNS/配置中心)
sentinel client-reconfig-script mymaster /opt/redis/scripts/reconfig.sh

# 日志配置
loglevel notice
logfile "/opt/redis/7.0.12/logs/sentinel.log"

*5.3 启动与验证

# 启动 Sentinel(3 个节点分别执行)
redis-sentinel /opt/redis/7.0.12/etc/sentinel.conf

# 或者使用 redis-server --sentinel 模式
redis-server /opt/redis/7.0.12/etc/sentinel.conf --sentinel

# 验证 Sentinel 状态
redis-cli -h 10.0.0.20 -p 26379 SENTINEL master mymaster
# 输出主节点信息:IP、端口、状态、从节点数等

redis-cli -h 10.0.0.20 -p 26379 SENTINEL slaves mymaster
# 输出从节点列表和状态

redis-cli -h 10.0.0.20 -p 26379 SENTINEL get-master-addr-by-name mymaster
# 输出当前主节点地址:10.0.0.10 6379

# 查看 Sentinel 集群信息
redis-cli -h 10.0.0.20 -p 26379 SENTINEL sentinels mymaster
# 输出其他 Sentinel 节点信息

*5.4 应用层连接(Jedis Sentinel)

import redis.clients.jedis.JedisSentinelPool;
import redis.clients.jedis.Jedis;
import java.util.HashSet;
import java.util.Set;

public class SentinelClient {
    private JedisSentinelPool sentinelPool;

    public SentinelClient() {
        Set<String> sentinels = new HashSet<>();
        sentinels.add("10.0.0.20:26379");
        sentinels.add("10.0.0.21:26379");
        sentinels.add("10.0.0.22:26379");

        // 连接池会自动从 Sentinel 获取当前主节点
        sentinelPool = new JedisSentinelPool("mymaster", sentinels, "YourStrongPassword123!");
    }

    public String get(String key) {
        try (Jedis jedis = sentinelPool.getResource()) {
            return jedis.get(key);
        }
    }

    public void set(String key, String value) {
        try (Jedis jedis = sentinelPool.getResource()) {
            jedis.set(key, value);
        }
    }

    public void close() {
        sentinelPool.close();
    }

    public static void main(String[] args) {
        SentinelClient client = new SentinelClient();
        client.set("sentinel:test", "auto-failover-ready");
        System.out.println(client.get("sentinel:test"));
        client.close();
    }
}

*5.5 手动故障转移测试

# 1. 模拟主节点宕机
redis-cli -h 10.0.0.10 -a "YourStrongPassword123!" DEBUG SEGFAULT
# 或 systemctl stop redis-server

# 2. 观察 Sentinel 日志(10 秒内)
tail -f /opt/redis/7.0.12/logs/sentinel.log
# +sdown master mymaster 10.0.0.10 6379
# +odown master mymaster #quorum 2/2
# +failover-begin master mymaster
# +selected-slave slave 10.0.0.11:6379
# +promoted-slave slave 10.0.0.11:6379 -> master
# +failover-end master mymaster

# 3. 验证新主节点
redis-cli -h 10.0.0.11 -a "YourStrongPassword123!" INFO REPLICATION
# role:master
# connected_slaves:1
# slave0:ip=10.0.0.12,port=6379,...

# 4. 应用层自动切换(Jedis Sentinel 会自动重连新主节点)
redis-cli -h 10.0.0.20 -p 26379 SENTINEL get-master-addr-by-name mymaster
# 10.0.0.11
# 6379

*六、Redis Cluster 集群部署

*6.1 架构说明(6 主 6 从)

Redis Cluster 采用无中心架构,数据分布在 16384 个 Slot 上,每个主节点负责一部分 Slot。每个主节点至少有一个从节点,实现自动故障转移。

*6.2 节点配置模板(redis-cluster.conf)

# =====================================
# Redis Cluster 节点配置(每节点修改 IP 和端口)
# =====================================

# 基础配置(同单机配置)
bind 127.0.0.1 10.0.0.10           # 根据节点修改 IP
port 6379
requirepass "YourStrongPassword123!"

# Cluster 核心配置
cluster-enabled yes
cluster-config-file nodes-6379.conf  # 集群状态自动保存
cluster-node-timeout 5000            # 节点通信超时 5 秒
cluster-require-full-coverage no     # 部分 Slot 不可用时仍然响应可用 Slot
cluster-slave-validity-factor 10     # 从节点数据延迟 10 倍 timeout 内才允许故障转移
cluster-migration-barrier 1          # 主节点至少保留 1 个从节点
cluster-allow-reads-when-down no     # 集群不完整时禁止读取(强一致性)

# 数据迁移配置(Rebalance 时使用)
cluster-replica-no-failover no       # 允许从节点自动故障转移

# 内存和持久化(同单机配置)
maxmemory 22gb
maxmemory-policy allkeys-lru
appendonly yes
appendfsync everysec

# 其他配置略(复制单机配置)

*6.3 创建集群

# 1. 启动所有 12 个节点
# 每个节点执行:
redis-server /opt/redis/7.0.12/etc/redis-cluster.conf

# 2. 使用 redis-cli 创建集群(在任意一个节点上执行)
redis-cli --cluster create \
  10.0.0.10:6379 10.0.0.12:6379 10.0.0.14:6379 \
  10.0.0.16:6379 10.0.0.18:6379 10.0.0.20:6379 \
  --cluster-replicas 1 \
  -a "YourStrongPassword123!"

# 参数说明:
# --cluster-replicas 1:每个主节点分配 1 个从节点
# 前 6 个是主节点,后 6 个是从节点(按顺序分配)

# 3. 确认集群创建成功
redis-cli -h 10.0.0.10 -a "YourStrongPassword123!" -c CLUSTER INFO
# cluster_state:ok
# cluster_slots_assigned:16384
# cluster_slots_ok:16384
# cluster_known_nodes:12
# cluster_size:6

# 4. 查看节点分配
redis-cli -h 10.0.0.10 -a "YourStrongPassword123!" -c CLUSTER NODES
# 输出 12 个节点信息,包括主从关系、Slot 分配、状态

*6.4 Python 连接 Cluster(redis-py-cluster)

from rediscluster import RedisCluster

# 集群客户端配置
startup_nodes = [
    {"host": "10.0.0.10", "port": "6379"},
    {"host": "10.0.0.12", "port": "6379"},
    {"host": "10.0.0.14", "port": "6379"}
]

rc = RedisCluster(
    startup_nodes=startup_nodes,
    password="YourStrongPassword123!",
    decode_responses=True,
    skip_full_coverage_check=True,      # 允许部分 Slot 不可用
    max_connections_per_node=100
)

# 自动路由到正确节点
rc.set("user:1000", "Alice")
value = rc.get("user:1000")
print(f"Value: {value}")

# 批量操作(Pipeline 自动处理跨节点)
pipe = rc.pipeline()
for i in range(100):
    pipe.set(f"key:{i}", f"value:{i}")
pipe.execute()

rc.close()

*6.5 集群维护命令

# 查看 Slot 分布
redis-cli --cluster check 10.0.0.10:6379 -a "YourStrongPassword123!"

# 重新分配 Slot(扩容/缩容)
redis-cli --cluster reshard 10.0.0.10:6379 -a "YourStrongPassword123!"
# 交互式输入:目标节点 ID、迁移 Slot 数量、源节点

# 添加新节点
redis-cli --cluster add-node 10.0.0.22:6379 10.0.0.10:6379 -a "YourStrongPassword123!"
# 新节点作为空主节点加入,需要后续 reshard 分配 Slot

# 删除节点
redis-cli --cluster del-node 10.0.0.10:6379 <node_id> -a "YourStrongPassword123!"
# 先迁移该节点的 Slot,再删除

# 故障转移(手动)
redis-cli -h 10.0.0.11 -a "YourStrongPassword123!" CLUSTER FAILOVER
# 强制从节点提升为主节点(原主节点仍然在线时)

*七、安全加固实践

*7.1 ACL 精细化权限控制(Redis 6.0+)

# 创建应用用户(只能读写业务 Key)
redis-cli -h 10.0.0.10 -a "YourStrongPassword123!" ACL SETUSER app_user \
  on >AppPassword456 \
  ~app:* \
  +get +set +del +hmget +hmset +hget +hset +lpush +rpop +zadd +zrange \
  -@admin -@dangerous

# 创建监控用户(只读 + INFO)
redis-cli -h 10.0.0.10 -a "YourStrongPassword123!" ACL SETUSER monitor_user \
  on >MonitorPass789 \
  ~* \
  +info +ping +readonly +client \
  -@write -@admin -@dangerous

# 创建管理员(保留所有权限)
redis-cli -h 10.0.0.10 -a "YourStrongPassword123!" ACL SETUSER admin \
  on >AdminSecure123 \
  ~* +@all

# 删除默认用户(禁止无密码访问)
redis-cli -h 10.0.0.10 -a "YourStrongPassword123!" ACL SETUSER default off

# 验证 ACL
redis-cli -h 10.0.0.10 -a "AppPassword456" GET app:test
redis-cli -h 10.0.0.10 -a "AppPassword456" FLUSHALL
# (error) NOPERM this user has no permissions to run the 'flushall' command

# 保存 ACL 到文件(redis.conf 中配置 aclfile)
redis-cli -h 10.0.0.10 -a "YourStrongPassword123!" ACL SAVE

*7.2 网络安全

# 防火墙规则(iptables / firewalld)
# 仅允许应用服务器和 Sentinel 节点访问 Redis 端口

# iptables 示例
iptables -A INPUT -p tcp --dport 6379 -s 10.0.0.0/24 -j ACCEPT
iptables -A INPUT -p tcp --dport 6379 -j DROP
iptables -A INPUT -p tcp --dport 26379 -s 10.0.0.0/24 -j ACCEPT
iptables -A INPUT -p tcp --dport 26379 -j DROP

# 云服务安全组
# 6379:仅允许应用服务器内网 IP
# 26379:仅允许 Sentinel 节点内网 IP
# 16379(Cluster 总线):仅允许 Cluster 节点内网 IP

*7.3 审计日志

# 开启命令审计(Redis 6.0+)
redis-cli -h 10.0.0.10 -a "YourStrongPassword123!" CONFIG SET acllog-max-len 10000

# 查看审计日志
redis-cli -h 10.0.0.10 -a "YourStrongPassword123!" ACL LOG
# 输出最近被 ACL 拒绝或命中的命令记录

*八、性能优化与监控配置

*8.1 关键监控指标

指标 告警阈值 说明
used_memory / maxmemory > 80% 内存使用率
mem_fragmentation_ratio > 1.5 或 < 0.9 内存碎片率
connected_clients / maxclients > 80% 连接数使用率
instantaneous_ops_per_sec 基线 + 50% 每秒操作数
keyspace_hits / (keyspace_hits + keyspace_misses) < 80% 缓存命中率
master_repl_offset - slave_repl_offset > 10MB 主从复制延迟
rdb_last_bgsave_status != ok 上次 RDB 状态
aof_last_write_status != ok 上次 AOF 写入状态
slowlog > 10ms 且 > 100 次/分钟 慢查询
cluster_state != ok 集群状态(Cluster 模式)

*8.2 监控脚本(Shell + Prometheus 风格)

#!/bin/bash
# redis_exporter.sh - Redis 指标采集脚本

HOST="127.0.0.1"
PORT="6379"
PASSWORD="YourStrongPassword123!"
OUTPUT="/var/lib/node_exporter/textfile/redis.prom"

# 获取 INFO 信息
INFO=$(redis-cli -h $HOST -p $PORT -a $PASSWORD INFO 2>/dev/null)
MEMORY=$(echo "$INFO" | grep -E "^used_memory:|^maxmemory:|^mem_fragmentation_ratio:")
STATS=$(echo "$INFO" | grep -E "^connected_clients:|^maxclients:|^instantaneous_ops_per_sec:")

# 解析指标
used_memory=$(echo "$MEMORY" | grep "used_memory:" | cut -d: -f2)
maxmemory=$(echo "$MEMORY" | grep "maxmemory:" | cut -d: -f2)
frag_ratio=$(echo "$MEMORY" | grep "mem_fragmentation_ratio:" | cut -d: -f2)
clients=$(echo "$STATS" | grep "connected_clients:" | cut -d: -f2)
max_clients=$(echo "$STATS" | grep "maxclients:" | cut -d: -f2)
iops=$(echo "$STATS" | grep "instantaneous_ops_per_sec:" | cut -d: -f2)

# 计算内存使用率
if [ "$maxmemory" != "0" ] && [ -n "$maxmemory" ]; then
    memory_usage=$(echo "scale=2; $used_memory / $maxmemory * 100" | bc)
else
    memory_usage=0
fi

# 输出 Prometheus 格式
cat > $OUTPUT <<EOF
# HELP redis_memory_usage_percent Memory usage percentage
# TYPE redis_memory_usage_percent gauge
redis_memory_usage_percent $memory_usage

# HELP redis_memory_fragmentation_ratio Memory fragmentation ratio
# TYPE redis_memory_fragmentation_ratio gauge
redis_memory_fragmentation_ratio $frag_ratio

# HELP redis_connected_clients Connected clients
# TYPE redis_connected_clients gauge
redis_connected_clients $clients

# HELP redis_instantaneous_ops_per_sec Instantaneous operations per second
# TYPE redis_instantaneous_ops_per_sec gauge
redis_instantaneous_ops_per_sec $iops
EOF

echo "Metrics exported to $OUTPUT"

*8.3 慢查询自动巡检

#!/bin/bash
# slowlog_checker.sh - 慢查询巡检脚本

HOST="127.0.0.1"
PORT="6379"
PASSWORD="YourStrongPassword123!"
THRESHOLD=100  # 超过 100 条慢查询则告警

# 获取慢查询数量
SLOWLOG_COUNT=$(redis-cli -h $HOST -p $PORT -a $PASSWORD SLOWLOG LEN 2>/dev/null)

if [ "$SLOWLOG_COUNT" -gt "$THRESHOLD" ]; then
    echo "[ALERT] $(date) Slowlog count: $SLOWLOG_COUNT (threshold: $THRESHOLD)"

    # 获取最新的 10 条慢查询详情
    redis-cli -h $HOST -p $PORT -a $PASSWORD SLOWLOG GET 10 2>/dev/null

    # 接入企业告警通道
    # curl -X POST https://alert.company.com/dingtalk ...

    # 清空慢查询日志(或保留)
    redis-cli -h $HOST -p $PORT -a $PASSWORD SLOWLOG RESET 2>/dev/null
fi

*九、实战案例:电商平台 Redis 集群部署实录

*9.1 背景与需求

某电商平台日均订单 100 万,峰值 QPS 5 万,Redis 主要用于:

  • 商品缓存(String / Hash)
  • 购物车数据(Hash)
  • 库存扣减(String + Lua)
  • 订单状态流转(List + ZSet)
  • 用户 Session(String + EX)
  • 排行榜 / 热销榜单(ZSet)

需求

  • 可用性 99.99%(全年停机 < 52 分钟)
  • 数据零丢失(RDB + AOF 双持久化)
  • 支持水平扩展(未来 10 倍流量增长)
  • 读写分离(读流量是写流量的 5 倍)
  • 安全合规(ACL 权限控制、审计日志)
  • 监控告警(实时性能指标 + 自动巡检)

*9.2 架构设计

组件 配置 说明
Redis Cluster 6 主 6 从,32GB 内存 每个主节点负责 2730 个 Slot,从节点交叉复制
服务器 12 台,每台 16 核 64GB NVMe SSD 2 个 Redis 实例/台(主+从),资源隔离
网络 万兆内网,独立 VLAN Cluster 总线与应用流量隔离
持久化 RDB 15min + AOF everysec 双保险,数据丢失 < 1 秒
安全 ACL + iptables + 禁用危险命令 三层防护
监控 Prometheus + Grafana + 自研巡检 10 秒粒度采集

*9.3 部署实施步骤

Step 1:硬件与系统准备(2 天)

  • 12 台服务器上架,安装 Ubuntu 22.04 LTS
  • 内核参数调优(THP 关闭、TCP 优化、文件描述符限制)
  • 磁盘分区:XFS 文件系统,独立数据盘挂载 /var/lib/redis
  • 网络配置:万兆内网,Cluster 总线(16379)与应用端口(6379)分 VLAN

Step 2:Redis 编译安装(1 天)

# 所有 12 台服务器执行
wget https://download.redis.io/releases/redis-7.0.12.tar.gz
tar xzf redis-7.0.12.tar.gz
cd redis-7.0.12
make -j$(nproc)
make PREFIX=/opt/redis/7.0.12 install

# 创建用户和目录
useradd -r -s /bin/false redis
mkdir -p /opt/redis/7.0.12/{etc,data,logs,scripts}
chown -R redis:redis /opt/redis/7.0.12/
chmod 750 /opt/redis/7.0.12/data

Step 3:配置文件生成(1 天)

使用自动化脚本生成每台服务器的配置:

#!/bin/bash
# generate_configs.sh - 批量生成 Cluster 配置

for i in {1..12}; do
    IP="10.0.0.$((9 + i))"
    cat > /opt/redis/7.0.12/etc/redis-${IP}.conf <<EOF
bind 127.0.0.1 ${IP}
port 6379
requirepass "EcomRedis2024!@#"
masterauth "EcomRedis2024!@#"

cluster-enabled yes
cluster-config-file nodes-${IP}.conf
cluster-node-timeout 5000
cluster-require-full-coverage no

maxmemory 28gb
maxmemory-policy allkeys-lru

appendonly yes
appendfsync everysec
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb

save 900 1
save 300 10
save 60 10000

lazyfree-lazy-eviction yes
lazyfree-lazy-expire yes
lazyfree-lazy-user-del yes

io-threads-do-reads yes
io-threads 4

slowlog-log-slower-than 10000
slowlog-max-len 1000

maxclients 10000

client-output-buffer-limit normal 0 0 0
client-output-buffer-limit replica 256mb 64mb 60
client-output-buffer-limit pubsub 32mb 8mb 60

loglevel notice
logfile "/opt/redis/7.0.12/logs/redis-${IP}.log"

# ACL 配置
aclfile /opt/redis/7.0.12/etc/users.acl
EOF
    chown redis:redis /opt/redis/7.0.12/etc/redis-${IP}.conf
done

Step 4:ACL 配置(0.5 天)

# /opt/redis/7.0.12/etc/users.acl
# 应用用户:只能读写商品、购物车、订单相关的 Key
user app_ecommerce on >EcomApp456! ~product:* ~cart:* ~order:* ~user:* ~rank:* +@all -@admin -@dangerous

# 库存用户:只能读写库存 Key,支持 Lua 脚本(原子扣减)
user app_inventory on >InvApp789! ~stock:* +get +set +del +incr +decr +eval +evalsha -@admin -@dangerous

# 监控用户:只读 + INFO
user monitor on >MonPass2024! ~* +info +ping +readonly +client +slowlog -@write -@admin -@dangerous

# 管理员:完整权限
user admin on >AdminEcom2024! ~* +@all

# 禁用默认用户
user default off

Step 5:systemd 服务配置(0.5 天)

# /etc/systemd/system/redis-cluster.service
[Unit]
Description=Redis Cluster Node
After=network.target

[Service]
Type=notify
User=redis
Group=redis
ExecStart=/opt/redis/7.0.12/bin/redis-server /opt/redis/7.0.12/etc/redis-%i.conf --supervised systemd
ExecStop=/opt/redis/7.0.12/bin/redis-cli -h %i -a "EcomRedis2024!@#" shutdown
Restart=always
RestartSec=5
LimitNOFILE=65535

[Install]
WantedBy=multi-user.target

Step 6:启动集群(0.5 天)

# 12 台服务器分别启动
systemctl enable redis-cluster@10.0.0.10
systemctl start redis-cluster@10.0.0.10

# ... 其他 11 台类似

# 创建 Cluster(在任意一台执行)
redis-cli --cluster create \
  10.0.0.10:6379 10.0.0.11:6379 10.0.0.12:6379 \
  10.0.0.13:6379 10.0.0.14:6379 10.0.0.15:6379 \
  10.0.0.16:6379 10.0.0.17:6379 10.0.0.18:6379 \
  10.0.0.19:6379 10.0.0.20:6379 10.0.0.21:6379 \
  --cluster-replicas 1 \
  -a "EcomRedis2024!@#"

Step 7:应用层改造(3 天)

  • 商品服务:使用 redis-py-cluster 连接 Cluster,Key 前缀 product:
  • 购物车服务:使用 Jedis Cluster 连接,Key 前缀 cart:,Hash 存储
  • 库存服务:使用 Lua 脚本实现原子扣减,Key 前缀 stock:
  • 订单服务:使用 List + ZSet 实现状态流转,Key 前缀 order:
  • 用户服务:使用 String + EX 存储 Session,Key 前缀 user:
  • 排行榜服务:使用 ZSet,Key 前缀 rank:

Step 8:监控与告警接入(2 天)

  • Prometheus 采集:每 10 秒采集 INFO、SLOWLOG、内存使用率
  • Grafana 看板:内存、QPS、命中率、延迟、主从延迟、节点负载均衡度
  • 告警规则:
    • 内存使用率 > 80%:钉钉告警
    • 慢查询 > 10ms/分钟 > 100 次:钉钉告警 + 自动转工单
    • 节点宕机 > 30 秒:电话告警 + 自动触发故障转移
    • 主从延迟 > 10MB:钉钉告警
    • Cluster 状态 != ok:电话告警

Step 9:压测与优化(2 天)

# 使用 redis-benchmark 压测
redis-benchmark -h 10.0.0.10 -a "EcomRedis2024!@#" -c 100 -n 1000000 -d 1024 -t set,get,hset,hget,lpush,lrange,zadd,zrange

# 模拟故障:随机 Kill 1 个主节点,观察自动故障转移时间
# 目标:故障转移 < 10 秒,数据丢失 < 1 秒

# 模拟扩容:添加 2 台新服务器,执行 reshard,观察数据迁移
# 目标:迁移期间 QPS 下降 < 20%

*9.4 上线后数据

指标 目标 实际 说明
可用性 99.99% 99.995% 全年停机 26 分钟(1 次计划维护)
峰值 QPS 5 万 6.2 万 618 大促峰值
平均延迟 < 2ms 0.8ms P99 < 5ms
数据丢失 0 0 RDB + AOF 双持久化
故障转移 < 30s 8s 自动故障转移
扩容时间 < 2h 1.5h 添加 2 主 2 从,reshard 完成
内存使用率 < 70% 65% 预留 35% 缓冲
缓存命中率 > 80% 92% 商品缓存命中率

*十、故障排查与应急手册

*10.1 常见故障速查表

故障现象 根因 紧急处理 根治方案
内存使用率 100% 大 Key / 内存泄漏 / 未设过期 立即扩容内存或紧急淘汰 设置 maxmemory + allkeys-lru,治理大 Key
主从同步中断 网络抖动 / 大 Key / 缓冲区溢出 检查网络,重启从节点同步 增大 repl-backlog-size,拆分大 Key
Cluster 状态 fail 节点宕机 / 网络分区 定位宕机节点,启动或替换 检查节点状态,修复网络
应用超时激增 热 Key / 慢查询 / 节点宕机 本地缓存兜底,限流 热 Key 治理,慢查询优化
CPU 100% 热 Key / 复杂命令 / 大 Key 定位热点,降级读从节点 哈希打散,禁用危险命令
持久化失败 磁盘满 / 磁盘故障 / 权限 清理磁盘,检查权限 监控磁盘使用率,独立数据盘
连接数耗尽 连接泄漏 / 未使用连接池 重启应用释放连接 使用连接池,设置超时回收

*10.2 紧急止血命令

# 1. 查看内存占用前 10 的 Key
redis-cli -h <host> -a <pass> --bigkeys

# 2. 查看当前慢查询
redis-cli -h <host> -a <pass> SLOWLOG GET 10

# 3. 查看连接数最高的客户端
redis-cli -h <host> -a <pass> CLIENT LIST | awk -F'=' '{print $2}' | sort | uniq -c | sort -nr | head

# 4. 查看热 Key(Redis 4.0+)
redis-cli -h <host> -a <pass> --hotkeys

# 5. 手动触发故障转移(Cluster)
redis-cli -h <slave_host> -a <pass> CLUSTER FAILOVER

# 6. 手动切换主节点(Sentinel)
redis-cli -h <sentinel_host> -p 26379 SENTINEL failover mymaster

# 7. 紧急清理内存(危险!)
redis-cli -h <host> -a <pass> DEBUG OBJECT <big_key>  # 确认大小
redis-cli -h <host> -a <pass> UNLINK <big_key>         # 异步删除

# 8. 查看 Cluster 节点状态
redis-cli -h <host> -a <pass> -c CLUSTER NODES
redis-cli -h <host> -a <pass> -c CLUSTER INFO

# 9. 紧急禁用写入(保留读取)
redis-cli -h <host> -a <pass> CLIENT PAUSE 30000 WRITE  # 暂停写入 30 秒

# 10. 查看复制延迟
redis-cli -h <slave_host> -a <pass> INFO REPLICATION | grep master_repl_offset
redis-cli -h <master_host> -a <pass> INFO REPLICATION | grep master_repl_offset

*10.3 数据恢复流程

场景:主节点宕机,AOF 损坏,需要从 RDB 恢复

1. 停止 Redis 服务
   systemctl stop redis-cluster@<ip>

2. 备份损坏的 AOF 和 RDB(以防万一)
   cp /opt/redis/7.0.12/data/appendonly.aof /opt/redis/7.0.12/data/appendonly.aof.bak.$(date +%Y%m%d%H%M%S)
   cp /opt/redis/7.0.12/data/dump.rdb /opt/redis/7.0.12/data/dump.rdb.bak.$(date +%Y%m%d%H%M%S)

3. 检查 RDB 完整性
   redis-check-rdb /opt/redis/7.0.12/data/dump.rdb

4. 如果 RDB 完整,删除损坏的 AOF,从 RDB 启动
   rm /opt/redis/7.0.12/data/appendonly.aof
   # 修改配置:appendonly no(临时)
   # 启动 Redis,数据从 RDB 加载

5. 重新开启 AOF(数据恢复后)
   redis-cli -h <host> -a <pass> CONFIG SET appendonly yes
   # 或修改配置后重启

6. 验证数据完整性
   redis-cli -h <host> -a <pass> DBSIZE
   redis-cli -h <host> -a <pass> INFO KEYSPACE

*十一、FAQ

Q1:Redis 生产环境必须用 Cluster 吗?

不一定。选择架构取决于数据规模和可用性要求:

  • 数据 < 10GB,QPS < 1 万:单机 + 主从 + Sentinel 足够
  • 数据 > 10GB 或 QPS > 5 万:必须使用 Cluster 水平扩展
  • 需要 99.99% 可用性:Cluster + 跨机房部署(但延迟增加)

Q2:RDB 和 AOF 都开启会不会性能很差?

Redis 7.0 的 AOF 采用多文件机制(AOF + RDB preamble),性能损耗 < 10%。建议生产环境双开:

  • RDB 用于快速全量恢复(分钟级)
  • AOF 用于精确增量恢复(秒级数据丢失)
  • 如果磁盘 I/O 是瓶颈,可以只开 AOF + RDB 关闭(save ""),但恢复时间变长

Q3:为什么 maxmemory 要设置为物理内存的 70%?

预留 30% 给:

  • 系统进程和内核缓冲区(约 10%)
  • AOF 重写期间的临时内存(约 10%)
  • 复制缓冲区(约 5%)
  • 碎片和突发增长缓冲(约 5%)

如果设置 100%,AOF 重写或突发写入会触发 OOM。

Q4:Sentinel 和 Cluster 的故障转移有什么区别?

特性 Sentinel Cluster
架构 主从复制 + 独立 Sentinel 无中心分片集群
故障检测 Sentinel 投票 节点间 Gossip
故障转移 Sentinel 选举主节点 从节点自动提升
数据迁移 不支持 支持在线 Reshard
扩展性 垂直扩展(主节点容量) 水平扩展(添加节点)
适用场景 数据量小、高可用 数据量大、高并发

Q5:Redis 7.0 的多线程 I/O 应该开多少线程?

建议:线程数 = CPU 核心数 - 1(留 1 个核心给命令执行和后台任务)。例如 8 核 CPU 开 7 个线程。但实测表明:

  • 纯内存操作、低并发:多线程无收益甚至负收益
  • 高并发、大 Value(> 10KB)、网络瓶颈:多线程收益明显(QPS 提升 20-50%)

建议通过 redis-benchmark 压测对比后决定。

Q6:如何安全地升级 Redis 版本?

  1. 小版本升级(7.0.10 → 7.0.12):

    • 直接替换二进制,滚动重启(先重启从节点,再主节点)
    • 利用 Sentinel 或 Cluster 的故障转移实现零停机
  2. 大版本升级(6.x → 7.x):

    • 先升级从节点,验证兼容性
    • 手动故障转移到新版本从节点
    • 观察 24 小时无异常后,升级剩余节点
    • 注意:7.0 的 AOF 格式与 6.x 不同,首次启动会自动转换

Q7:Redis 数据如何备份到异地?

  • RDB 冷备:定时 BGSAVE,将 dump.rdb 同步到异地对象存储(S3/OSS)
  • AOF 实时同步:使用 redis-shake 或自研工具实时解析 AOF,同步到异地 Redis
  • CDC 方案:Redis 6.0+ 的 KEYSPACE 通知 + 应用层双写

Q8:Cluster 模式下批量操作(MGET、Pipeline)有什么限制?

Cluster 模式下,批量操作的所有 Key 必须在同一 Slot。解决方案:

  • 使用 Hash Tag:{user:1000}:profile{user:1000}:settings 保证同一 Slot
  • 使用 redis-py-cluster 的 Pipeline:自动拆分跨节点请求,但无法保证原子性
  • 应用层拆分:先按 Slot 分组,再分别发送 Pipeline

*十二、总结

Redis 生产环境部署是一项系统工程,涉及硬件选型、系统调优、配置管理、架构设计、安全加固、监控告警和应急响应等多个环节。本文提供了一套从单机到 Cluster 的完整部署方案,核心要点总结如下:

  1. 系统层:关闭 THP、优化内核参数、使用 XFS 文件系统、预留足够文件描述符
  2. 配置层:绑定内网 IP、强密码、禁用危险命令、maxmemory 70%、RDB + AOF 双持久化、lazyfree 全部开启
  3. 架构层:小规模用 Sentinel,大规模用 Cluster;读写分离降低主节点压力;交叉复制避免机架故障
  4. 安全层:ACL 最小权限、网络隔离(iptables/安全组)、审计日志、定期轮换密码
  5. 监控层:10 项核心指标 + 慢查询巡检 + 自动告警 + 可视化看板
  6. 应急层:10 个紧急止血命令 + 数据恢复流程 + 故障演练

遵循以上最佳实践,可以构建一个可用性达 99.99%、数据零丢失、可水平扩展的 Redis 生产环境。建议每季度进行一次故障演练(随机 Kill 节点、模拟网络分区),验证架构的可靠性和团队的应急响应能力。

相关阅读