searchusermenu
  • 发布文章
  • 消息中心
点赞
收藏
评论
分享
原创

从入门到上线:Redis 本地部署与生产环境搭建全攻略

2025-10-29 10:31:57
0
0
一、为什么先谈“安装”而不是“使用”
很多工程师习惯把 Redis 当成“apt-get install”就能跑起来的黑盒,结果上线第一天就遇到三大灵魂拷问:
  1. 为什么本地压测只有三万 QPS,到了预发环境突然掉到一万?
  2. 为什么明明给了 8 G 内存,日志却报 “Can’t allocate memory”?
  3. 为什么主从切换后数据回滚了十分钟?
    追根溯源,80% 的诡异现象都能在“安装阶段”埋下的隐患里找到答案。把安装做扎实,等于把后期 2 a.m. 的告警扼杀在摇篮里。本文用 3000 字把“安装”拆成七步:环境、版本、目录、编译、配置、启停、校验,每一步都给出选择逻辑与避坑要点,力求让你下一次装机不再靠“抄博客”,而是“心里有数”。
二、环境:先问操作系统,再问内核
  1. 操作系统
    Linux 是事实标准,但不同发行版的默认参数差异巨大。以文件句柄数为例,Ubuntu 20.04 默认 1024,CentOS 8 默认 65536,直接决定 Redis 能不能扛住 10 万并发连接。
  2. 内核版本
    2.6.32 可以跑,但 3.10+ 才支持 SO_REUSEPORT,能让多实例绑定同端口做负载均衡;5.0+ 才支持 io_uring,对 AOF 重写有 10% 左右的 I/O 提升。如果公司规定必须用老内核,就要提前评估性能折损。
  3. 内存与 Swap
    Redis 是内存数据库,但不是“内存越多越好”。预留 20% 给写时复制、缓冲区和系统页缓存,Swap 必须关,否则一次透明大页压缩就能让延迟飙到秒级。
  4. 磁盘
    磁盘不是“能用就行”。AOF 每秒刷盘一次,如果磁盘写入延迟 5 ms,请求尾延迟就会涨到 5 ms。建议用 nvme 或者至少 SSD,且挂载时加 noatime、nodiratime,减少元数据开销。
  5. 网络
    万兆网卡是标配,但别忘了检查中断亲和性。把网卡队列绑定到不同 CPU,能把 P99 延迟再降 200 µs。
三、版本:稳定≠最新,新特性≠刚需
  1. 主版本号
    6.2 引入 ACL、SSL、多线程 I/O,7.0 引入 Functions、Sharded Pub/Sub。如果业务只用缓存,5.0 足够;需要细粒度权限控制就上 6.2;想尝鲜可插脚本的 Functions 才选 7.0。
  2. 小版本号
    偶数小版本是稳定版,奇数是开发版,这是 Redis 官方 10 年传统。别在生产线程上跑 7.1-rc1,除非你想给社区贡献 Issue。
  3. 回退策略
    升级前一定准备回退包:把旧版本的二进制、配置、RDB 文件打包到 /opt/redis/rollback 目录,并写一行 systemd 的 Conflicts= 确保新旧单元不会同时启动。
四、目录:用“四目录法则”告别文件散落
  1. 二进制目录 /opt/redis/bin
    放可执行文件,权限 755,属主 root,避免开发同学误删。
  2. 配置目录 /etc/redis
    一个实例一个文件,命名规则:端口.conf,例如 6379.conf、6380.conf。
  3. 数据目录 /data/redis/端口
    RDB、AOF、临时文件全放这里,单独挂载一块盘,方便用 df -h 快速看容量。
  4. 日志目录 /var/log/redis
    给 rsyslog 或者 systemd-journald 做统一收集,文件名带端口,方便 ELK 切分。
    这样做的好处:
  • 水平扩容时,只需新建 /data/redis/6381,无需改 puppet/ansible 脚本;
  • 故障排查时,根据端口号就能定位所有文件,减少 30% 的沟通成本。
五、编译:把“-O2” 改成 “-O3” 之前先想清楚
  1. 依赖检查
    gcc、make、tcl 缺一不可,但最容易被忽略的是 jemalloc。系统自带 glibc malloc 在 64 核机器上会出现疯狂锁竞争,把 QPS 砍掉一半。
  2. 编译参数
    MALLOC=jemalloc 是必选项;
    如果 CPU 支持 AVX2,加 CFLAGS=”-mavx2 -O3” 能把 zset 的 score 比较性能提高 8%;
    但 -O3 会让调试符号失真,core dump 时 gdb 看不见局部变量,开发环境建议 -O0 -g。
  3. 静态链接
    生产环境常因为升级 glibc 导致 redis-server 起不来,用 make BUILD_TLS=yes USE_STATIC=1 把 openssl 和 jemalloc 静态编进去,可彻底规避“同版本不同机器”的依赖地狱。
  4. 多实例复用
    编译结果只有 15 M,把 redis-server 复制成 redis-server-6379、redis-server-6380,就能在升级时做灰度:先停 6380,再启动新二进制,滚动重启,用户无感知。
六、配置:别让“网上抄的”毁了你
  1. 内存
    maxmemory 不要等于物理内存,留 20% 给 fork 写时复制;
    淘汰策略用 allkeys-lru 还是 volatile-ttl,取决于业务是否全量设过期时间,选错一次,高峰期就能让 DB 被打穿。
  2. 持久化
    RDB 和 AOF 不是“二选一”,而是“分层保险”:
  • RDB 做冷备,每天一次,恢复速度 1 G/10 s;
  • AOF 做热备,每秒刷盘,最多丢 1 s;
    同时开启时,Redis 7.0 会走 “RDB-AOF mixed” 格式,文件体积降 60%,重启速度翻倍。
  1. 网络
    tcp-backlog 设 511 还是 2048?看 Linux 的 net.core.somaxconn 默认值,如果系统只有 128,Redis 设 2048 也没用。
  2. 安全
    bind 0.0.0.0 一定要配合 requirepass 或者 ACL,否则扫描器 3 秒就能把你的 key 全拉走;
    rename-command 把 CONFIG、FLUSHALL 改名,防止实习生凌晨两点手滑。
  3. 多线程
    io-threads 4 不是“越大越好”,超过 8 线程后内核调度开销会反杀性能;
    建议压测:先用 redis-benchmark -t set -d 256b -c 50 -n 1000000 看 baseline,再逐步加线程,找到拐点。
七、启停:systemd 不是“写完 service 文件就完事”
  1. 通知机制
    Type=notify 能让 Redis 在真正完成端口监听后再通知 systemd,避免监控系统误判“端口起不来”。
  2. 重启策略
    Restart=on-failure 必须配合 RestartSec=5s,否则故障死循环会把机器打挂;
    StartLimitInterval=60s StartLimitBurst=3 能在 1 分钟内最多重启 3 次,超过就放弃,等人干预。
  3. 资源限制
    LimitNOFILE=1000000
    LimitNPROC=8192
    这两个值如果低于 Redis 里的 maxclients,就会在日志里出现 “Too many open files”,但系统又不报任何错,排查平均耗时 30 分钟。
  4. 优雅关闭
    TimeoutStopSec=30
    KillMode=mixed
    Redis 收到 SIGTERM 后会先尝试持久化,如果 30 秒还没完,systemd 会补 SIGKILL。把 TimeoutStopSec 设太短会导致 AOF 末尾截断,重启时触发 redis-check-aof –fix,耗时跟数据量成正比。
八、校验:跑通“三步体检”再上线
  1. 连通性
    redis-cli -p 6379 ping 返回 PONG 只是第一步,再用 telnet 127.0.0.1 6379 看是否立刻断开,判断防火墙是否放行。
  2. 性能基线
    用 redis-benchmark 打本机 loopback,记录 set、get、lpush、sadd、zadd 五类命令的 QPS 和延迟,写成 markdown 存到 docs/performance.md,以后升级硬件或版本,先跑同一条命令,性能掉 10% 以上就回退。
  3. 数据一致性
    写 100 万条 key,格式为 key_(i,value为 UUID;
    执行 BGSAVE,等待 RDB 完成;
    kill -9 redis-server,模拟野蛮断电;
    重启后执行 redis-cli –bigkeys 和 sha1sum 校验,确认条数、SHA1 值一致,才算持久化可信。
九、常见翻车现场 30 秒速查表
  1. 启动时报 “WARNING overcommit_memory is set to 0”
    echo 1 > /proc/sys/vm/overcommit_memory
  2. 日志里 “Can’t save in background: fork: Cannot allocate memory”
    把 vm.overcommit_memory 设为 1 后仍报错,说明物理内存不足,需要降 maxmemory 或加机器。
  3. 客户端偶尔报 “Connection reset by peer”
    检查 tcp-keepalive 60 是否开启,以及 net.ipv4.tcp_keepalive_time 是否小于 60。
  4. 从库持续 “master_link_status:down”
    主库 bind 127.0.0.1,导致从库连不上,把 bind 改成内网地址即可。
  5. 升级后原配置失效
    Redis 7.0 把 “slave” 关键字全面改成 “replica”,老配置里如果写 slaveof 会被忽略,必须全局替换。
十、一条命令都不给,怎么自动化?
  1. 模板引擎
    用 Jinja2 写 redis.conf.j2,变量只有端口号、内存、是否主库三处,其余字段写死,杜绝“复制粘贴改错”。
  2. 配置校验
    写 preflight 脚本,用正则检查 maxmemory < (物理内存 * 0.8),检查 bind 不是 0.0.0.0 就是 127.0.0.1,否则拒绝启动。
  3. 灰度发布
    把 redis-server 二进制放到对象存储,下载后做 sha256 校验,确认无误再 systemd 启动;同时用 consul-template 把实例信息注册到服务发现,让监控自动拉取。
十一、写在最后的 4 句忠告
  1. 安装不是“能跑就行”,而是“给七年后的凌晨留一条活路”。
  2. 每当你想省掉一次校验,就把生产故障的 PPT 想象成自己上台讲解。
  3. 把这篇文章打印出来,贴到工位,下次装机逐条打钩,能减少 90% 的“灵异事件”。
  4. Redis 很轻,轻到 15 M 的二进制就能撑起亿级流量;Redis 也很重,重到一次安装疏忽就能让年终奖归零。愿你从此不再惧怕任何一次版本升级。
0条评论
0 / 1000
c****q
132文章数
0粉丝数
c****q
132 文章 | 0 粉丝
原创

从入门到上线:Redis 本地部署与生产环境搭建全攻略

2025-10-29 10:31:57
0
0
一、为什么先谈“安装”而不是“使用”
很多工程师习惯把 Redis 当成“apt-get install”就能跑起来的黑盒,结果上线第一天就遇到三大灵魂拷问:
  1. 为什么本地压测只有三万 QPS,到了预发环境突然掉到一万?
  2. 为什么明明给了 8 G 内存,日志却报 “Can’t allocate memory”?
  3. 为什么主从切换后数据回滚了十分钟?
    追根溯源,80% 的诡异现象都能在“安装阶段”埋下的隐患里找到答案。把安装做扎实,等于把后期 2 a.m. 的告警扼杀在摇篮里。本文用 3000 字把“安装”拆成七步:环境、版本、目录、编译、配置、启停、校验,每一步都给出选择逻辑与避坑要点,力求让你下一次装机不再靠“抄博客”,而是“心里有数”。
二、环境:先问操作系统,再问内核
  1. 操作系统
    Linux 是事实标准,但不同发行版的默认参数差异巨大。以文件句柄数为例,Ubuntu 20.04 默认 1024,CentOS 8 默认 65536,直接决定 Redis 能不能扛住 10 万并发连接。
  2. 内核版本
    2.6.32 可以跑,但 3.10+ 才支持 SO_REUSEPORT,能让多实例绑定同端口做负载均衡;5.0+ 才支持 io_uring,对 AOF 重写有 10% 左右的 I/O 提升。如果公司规定必须用老内核,就要提前评估性能折损。
  3. 内存与 Swap
    Redis 是内存数据库,但不是“内存越多越好”。预留 20% 给写时复制、缓冲区和系统页缓存,Swap 必须关,否则一次透明大页压缩就能让延迟飙到秒级。
  4. 磁盘
    磁盘不是“能用就行”。AOF 每秒刷盘一次,如果磁盘写入延迟 5 ms,请求尾延迟就会涨到 5 ms。建议用 nvme 或者至少 SSD,且挂载时加 noatime、nodiratime,减少元数据开销。
  5. 网络
    万兆网卡是标配,但别忘了检查中断亲和性。把网卡队列绑定到不同 CPU,能把 P99 延迟再降 200 µs。
三、版本:稳定≠最新,新特性≠刚需
  1. 主版本号
    6.2 引入 ACL、SSL、多线程 I/O,7.0 引入 Functions、Sharded Pub/Sub。如果业务只用缓存,5.0 足够;需要细粒度权限控制就上 6.2;想尝鲜可插脚本的 Functions 才选 7.0。
  2. 小版本号
    偶数小版本是稳定版,奇数是开发版,这是 Redis 官方 10 年传统。别在生产线程上跑 7.1-rc1,除非你想给社区贡献 Issue。
  3. 回退策略
    升级前一定准备回退包:把旧版本的二进制、配置、RDB 文件打包到 /opt/redis/rollback 目录,并写一行 systemd 的 Conflicts= 确保新旧单元不会同时启动。
四、目录:用“四目录法则”告别文件散落
  1. 二进制目录 /opt/redis/bin
    放可执行文件,权限 755,属主 root,避免开发同学误删。
  2. 配置目录 /etc/redis
    一个实例一个文件,命名规则:端口.conf,例如 6379.conf、6380.conf。
  3. 数据目录 /data/redis/端口
    RDB、AOF、临时文件全放这里,单独挂载一块盘,方便用 df -h 快速看容量。
  4. 日志目录 /var/log/redis
    给 rsyslog 或者 systemd-journald 做统一收集,文件名带端口,方便 ELK 切分。
    这样做的好处:
  • 水平扩容时,只需新建 /data/redis/6381,无需改 puppet/ansible 脚本;
  • 故障排查时,根据端口号就能定位所有文件,减少 30% 的沟通成本。
五、编译:把“-O2” 改成 “-O3” 之前先想清楚
  1. 依赖检查
    gcc、make、tcl 缺一不可,但最容易被忽略的是 jemalloc。系统自带 glibc malloc 在 64 核机器上会出现疯狂锁竞争,把 QPS 砍掉一半。
  2. 编译参数
    MALLOC=jemalloc 是必选项;
    如果 CPU 支持 AVX2,加 CFLAGS=”-mavx2 -O3” 能把 zset 的 score 比较性能提高 8%;
    但 -O3 会让调试符号失真,core dump 时 gdb 看不见局部变量,开发环境建议 -O0 -g。
  3. 静态链接
    生产环境常因为升级 glibc 导致 redis-server 起不来,用 make BUILD_TLS=yes USE_STATIC=1 把 openssl 和 jemalloc 静态编进去,可彻底规避“同版本不同机器”的依赖地狱。
  4. 多实例复用
    编译结果只有 15 M,把 redis-server 复制成 redis-server-6379、redis-server-6380,就能在升级时做灰度:先停 6380,再启动新二进制,滚动重启,用户无感知。
六、配置:别让“网上抄的”毁了你
  1. 内存
    maxmemory 不要等于物理内存,留 20% 给 fork 写时复制;
    淘汰策略用 allkeys-lru 还是 volatile-ttl,取决于业务是否全量设过期时间,选错一次,高峰期就能让 DB 被打穿。
  2. 持久化
    RDB 和 AOF 不是“二选一”,而是“分层保险”:
  • RDB 做冷备,每天一次,恢复速度 1 G/10 s;
  • AOF 做热备,每秒刷盘,最多丢 1 s;
    同时开启时,Redis 7.0 会走 “RDB-AOF mixed” 格式,文件体积降 60%,重启速度翻倍。
  1. 网络
    tcp-backlog 设 511 还是 2048?看 Linux 的 net.core.somaxconn 默认值,如果系统只有 128,Redis 设 2048 也没用。
  2. 安全
    bind 0.0.0.0 一定要配合 requirepass 或者 ACL,否则扫描器 3 秒就能把你的 key 全拉走;
    rename-command 把 CONFIG、FLUSHALL 改名,防止实习生凌晨两点手滑。
  3. 多线程
    io-threads 4 不是“越大越好”,超过 8 线程后内核调度开销会反杀性能;
    建议压测:先用 redis-benchmark -t set -d 256b -c 50 -n 1000000 看 baseline,再逐步加线程,找到拐点。
七、启停:systemd 不是“写完 service 文件就完事”
  1. 通知机制
    Type=notify 能让 Redis 在真正完成端口监听后再通知 systemd,避免监控系统误判“端口起不来”。
  2. 重启策略
    Restart=on-failure 必须配合 RestartSec=5s,否则故障死循环会把机器打挂;
    StartLimitInterval=60s StartLimitBurst=3 能在 1 分钟内最多重启 3 次,超过就放弃,等人干预。
  3. 资源限制
    LimitNOFILE=1000000
    LimitNPROC=8192
    这两个值如果低于 Redis 里的 maxclients,就会在日志里出现 “Too many open files”,但系统又不报任何错,排查平均耗时 30 分钟。
  4. 优雅关闭
    TimeoutStopSec=30
    KillMode=mixed
    Redis 收到 SIGTERM 后会先尝试持久化,如果 30 秒还没完,systemd 会补 SIGKILL。把 TimeoutStopSec 设太短会导致 AOF 末尾截断,重启时触发 redis-check-aof –fix,耗时跟数据量成正比。
八、校验:跑通“三步体检”再上线
  1. 连通性
    redis-cli -p 6379 ping 返回 PONG 只是第一步,再用 telnet 127.0.0.1 6379 看是否立刻断开,判断防火墙是否放行。
  2. 性能基线
    用 redis-benchmark 打本机 loopback,记录 set、get、lpush、sadd、zadd 五类命令的 QPS 和延迟,写成 markdown 存到 docs/performance.md,以后升级硬件或版本,先跑同一条命令,性能掉 10% 以上就回退。
  3. 数据一致性
    写 100 万条 key,格式为 key_(i,value为 UUID;
    执行 BGSAVE,等待 RDB 完成;
    kill -9 redis-server,模拟野蛮断电;
    重启后执行 redis-cli –bigkeys 和 sha1sum 校验,确认条数、SHA1 值一致,才算持久化可信。
九、常见翻车现场 30 秒速查表
  1. 启动时报 “WARNING overcommit_memory is set to 0”
    echo 1 > /proc/sys/vm/overcommit_memory
  2. 日志里 “Can’t save in background: fork: Cannot allocate memory”
    把 vm.overcommit_memory 设为 1 后仍报错,说明物理内存不足,需要降 maxmemory 或加机器。
  3. 客户端偶尔报 “Connection reset by peer”
    检查 tcp-keepalive 60 是否开启,以及 net.ipv4.tcp_keepalive_time 是否小于 60。
  4. 从库持续 “master_link_status:down”
    主库 bind 127.0.0.1,导致从库连不上,把 bind 改成内网地址即可。
  5. 升级后原配置失效
    Redis 7.0 把 “slave” 关键字全面改成 “replica”,老配置里如果写 slaveof 会被忽略,必须全局替换。
十、一条命令都不给,怎么自动化?
  1. 模板引擎
    用 Jinja2 写 redis.conf.j2,变量只有端口号、内存、是否主库三处,其余字段写死,杜绝“复制粘贴改错”。
  2. 配置校验
    写 preflight 脚本,用正则检查 maxmemory < (物理内存 * 0.8),检查 bind 不是 0.0.0.0 就是 127.0.0.1,否则拒绝启动。
  3. 灰度发布
    把 redis-server 二进制放到对象存储,下载后做 sha256 校验,确认无误再 systemd 启动;同时用 consul-template 把实例信息注册到服务发现,让监控自动拉取。
十一、写在最后的 4 句忠告
  1. 安装不是“能跑就行”,而是“给七年后的凌晨留一条活路”。
  2. 每当你想省掉一次校验,就把生产故障的 PPT 想象成自己上台讲解。
  3. 把这篇文章打印出来,贴到工位,下次装机逐条打钩,能减少 90% 的“灵异事件”。
  4. Redis 很轻,轻到 15 M 的二进制就能撑起亿级流量;Redis 也很重,重到一次安装疏忽就能让年终奖归零。愿你从此不再惧怕任何一次版本升级。
文章来自个人专栏
文章 | 订阅
0条评论
0 / 1000
请输入你的评论
0
0