多彩编程 多彩编程MZPH · CODE BLOG
ARTICLE DETAIL

文章详情

深耕前端与后端开发技术的一线实战笔记与踩坑复盘。

Ubuntu生产环境Redis部署指南:从安装配置到缓存治理与排障实战

Ubuntu生产环境Redis部署指南:从安装配置到缓存治理与排障实战 先把话说在前面网上搜“Ubuntu 安装 Redis”十条里有八条是让你一行命令装完然后跑一个 ping 测试就结束的。真到了生产环境这种“装完即弃”的做法会让后面的缓存失效、连接超时、数据丢失全部变成玄学。我在 Ubuntu 上部署 Redis 的次数不算少从 5.x 到 7.x 都踩过一轮这篇文章不打算只讲安装命令而是把“装完之后怎么配置”“五种数据类型在真实业务里怎么用”“遇到 Redis Command timed out 这类问题怎么排查”串起来讲清楚。适合刚接触 Linux 的开发者照着做也适合已经在用 Redis、但想把缓存治理、分布式锁这些高阶玩法理顺的同学参考。1. 安装方式的全套选择apt、源码编译和 Docker 都各自踩过哪些坑1.1 apt 安装绝大多数场景足够用Ubuntu 的官方软件源里长期维护着 Redis 的稳定版本安装只需要两条命令sudo apt update sudo apt install redis-server -y装完以后Redis 会自动注册成 systemd 服务这也是我推荐新手从 apt 入手的核心原因——服务开机自启、日志交给 journald 管理、卸载也干净完全不需要你自己写守护脚本。苹果的 Homebrew 用户可能更习惯brew install redis但那是 macOS 的玩法。在服务器上apt 装出来的 Redis 配置文件和数据库目录都遵循 Linux 文件系统标准位置在/etc/redis/redis.conf数据默认存到/var/lib/redis/。这个布局对后续做备份、迁移都很友好。当然apt 也不是没有缺点仓库里的版本通常比官方最新版晚一两个大版本。比如 Ubuntu 22.04 默认源里的 Redis 是 6.0.x而官方已经到 7.2 了。如果你只是学习 API、做本地缓存这个版本差异几乎无感但如果你要看 Redis 7 才有的ACL精细化权限控制或者Redis Function功能就得往下看其他安装方式。1.2 源码编译卡在 gcc 和 tcl 上的时间最多不少教程会鼓励你走wget源码包然后make make install的流程觉得这样最“正宗”。我尝试过几次每次都能在编译阶段碰到幺蛾子。最常见的问题集中在两个环节第一缺少构建依赖。Redis 源码编译依赖gcc和make很多精简版 Ubuntu 服务器连 gcc 都没装运行make就报command not found。热搜词里那条“ubuntu安装gcc失败”我怀疑不少人就是在这一步入坑的。正确的办法是先安装一套构建工具sudo apt install build-essential tcl -ytcl不是编译期依赖而是 Redis 源码目录下测试脚本make test需要的解释器。如果你忽略测试只保证make成功那 tcl 缺失倒不影响运行。第二编译完成后二进制文件散落在源码目录里需要你手动make install或者复制到/usr/local/bin。这一步本身不难但很多人忘了复制配置文件结果redis-server跑起来用的是默认配置连密码都没有暴露在网络上就是一场事故。源码编译最大的好处是版本可控想装 7.2 就装 7.2想定制编译参数也行。坏处是后续升级、卸载都需要自己维护对新人来说运维成本远高于那点版本自由度。我的建议是除非你有明确的版本定制需求否则别在源码编译上浪费时间。1.3 Docker 安装环境干净但别忽略数据卷和网络模式docker run redis是另一条常见的路官方镜像更新及时环境隔离度高很适合本地临时起一个 Redis 做测试。但如果你把它当成生产方案有几个细节必须处理好。首先是数据持久化。容器是易失的不挂载数据卷的话docker rm之后数据全没。标准做法是挂载一个目录给 Redis 的 dump 文件和 appendonly 文件docker run -d --name redis \ -p 6379:6379 \ -v /opt/redis/data:/data \ redis:7.2 --appendonly yes其次是配置传递。官方镜像默认不带自定义配置文件你要么在宿主机准备一份 redis.conf 然后挂载到容器内要么通过启动参数传配置。很多人第一次用 Docker 起 Redis光是把配置挂载这件事折腾明白就得来回删容器好几次。最后是网络模式。如果你用默认 bridge 网络宿主机访问容器内的 Redis 需要端口映射其他容器访问它的地址也不是localhost而是容器网络内的 IP。在docker-compose里给 Redis 单独起一个服务其他服务通过 service 名连接这才是比较省心的姿势。Docker 路线我一般用在两类场景一是开发和测试环境方便随时换版本二是生产环境本身就跑在 k8s 或 docker-swarm 上Redis 作为中间件以容器方式纳入编排。如果生产环境是裸机或虚拟机用 apt 装反而更省资源。1.4 我的最终选择逻辑场景推荐方式理由个人学习、虚拟机测试apt 安装命令简单systemd 托管卸载方便生产环境裸机部署官方源安装最新稳定版版本可控性能无容器损耗运维直观集群、编排环境Docker 镜像随服务一起编排版本迭代方便研究最新特性、编译定制源码编译可定制编译参数适合折腾简单说装 Redis 不是越复杂越好而是要根据你的使用场景决定方式。教程喜欢教源码编译是因为它“看起来完整”实际操作中apt 装完再花半小时把配置项吃透收益远大于折腾编译。2. 从零到跑起来安装命令、开机自启与版本验证2.1 三条命令完成安装以 Ubuntu 22.04 LTS 为例打开终端依次执行sudo apt update sudo apt install redis-server -y redis-server --versionredis-server --version会输出类似Redis server v6.0.16的信息。这一步没问题的话说明安装成功。为什么先执行apt update因为 apt 的软件源列表是本地缓存的如果你很久没刷新直接 install 可能装到一个过期版本甚至因为索引缺失而报“无法定位软件包”。装完以后先不用急着改配置Redis 默认就能启动。直接用命令行测试连通性redis-cli ping返回PONG代表服务正常响应。这里多说一句redis-cli ping能通只说明 Redis 进程在监听且你访问的是本机默认端口 6379不能说明其他机器也能连它后面配置章节我会展开讲。2.2 用 systemd 管好 Redis 的生命周期apt 安装的 redis-server 会自动创建 systemd 服务单元所以你应该用systemctl而不是直接执行redis-server命令来控制它sudo systemctl enable redis-server sudo systemctl start redis-server sudo systemctl status redis-serverenable是设置开机自启start是立即启动。注意顺序如果先 start 再 enable服务是起来了但重启机器后不会自动拉起这是很多人踩过的小坑。status查看服务状态时重点看三处信息Active: active (running)说明进程在跑Main PID能确认当前进程号CGroup片段里有没有包含 redis-server 进程。如果看到Active: failed大概率是配置文件写错了用下面命令看详细日志journalctl -u redis-server -n 50 --no-pager日志会直接告诉你是 bind 地址写错、端口冲突还是权限不对。如果你启动过多个 Redis 实例redis-server命令方式下常见的“Address already in use”问题在 journald 日志里也会体现得清清楚楚。2.3 默认安装后的关键目录结构apt 安装的 Redis 目录结构是有讲究的了解清楚以后做备份、排错会快很多/etc/redis/redis.conf主配置文件几乎所有的运行参数都在这里/var/lib/redis/RDB 快照和 AOF 文件的默认存放目录/var/log/redis/Redis 日志文件目录/usr/bin/redis-server和/usr/bin/redis-cli服务和客户端二进制记住这些路径最大的意义在于当你需要迁移数据时直接打包/var/lib/redis就行当你想看运行日志时不用满世界找日志文件就在/var/log/redis。很多面试题里问“Redis 数据文件在哪”本质上考的就是你对默认目录结构的熟悉程度。2.4 当 apt 版本太旧时怎么办如果你需要 Redis 7.x 的 ACL 功能或者想体验新版数据结构的优化但 apt 源里的版本不够新最简单的办法是启用 Redis 官方提供的 PPA 软件源sudo add-apt-repository ppa:redis-server/redis-server sudo apt update sudo apt install redis-server -y升级前把redis-cli --version和redis-server --version都记下来升级完以后第一时间跑redis-cli ping和INFO server确认版本。这里要提醒一句跨大版本升级 Redis 时RDB 文件一般都能兼容但如果你从 5.x 直接跳到 7.x最好先做一次全量备份再用redis-check-rdb检查一下 dump.rdb 文件完整性避免老节点止写、新节点起不来的尴尬局面。3. 配置文件里决定生死的几个参数密码、绑定和持久化3.1 bind 与 protected-mode为什么默认连不上外部机器刚装好的 Redis 默认只监听本机地址127.0.0.1所以你在服务器上跑redis-cli能连上换一台机器用 IP 连大概率是Connection refused。这不是故障这是安全设计。Redis 出于安全考虑默认开启了 protected-mode。当它发现你以默认配置运行没有设置密码且监听地址包含非本机地址时会直接拒绝外部连接并提示需要修改配置。这样的设计是为了避免“裸奔的 Redis 被全网扫到然后写入了恶意数据”的经典事故。如果你确实需要让其他机器访问 Redis最小改动是这样bind 0.0.0.0 protected-mode yes requirepass 你的强密码bind 0.0.0.0表示监听所有网卡此时 protected-mode 默认会拒绝外部无密码连接所以必须配合requirepass一起用。如果你只想让内网某几台机器访问千万别图省事写0.0.0.0最好写成具体 IP比如bind 192.168.1.100 127.0.0.1把监听白名单做小一点。3.2 requirepass 与 ACL密码不是设置完就万事大吉设置密码的方式很简单在配置文件里加一行requirepass yourpassword重启后redis-cli直接发命令会被提示NOAUTH Authentication required。你要么每次在客户端手动执行AUTH yourpassword要么连接时直接带密码redis-cli -h 192.168.1.100 -p 6379 -a yourpassword这里有个安全隐患-a参数指定密码后密码会出现在 shell 的历史记录里如果服务器被别人登录过密码就泄露了。更安全的做法是用环境变量REDISCLI_AUTHyourpassword redis-cli -h 192.168.1.100Redis 6.0 以上还支持 ACL 用户权限给不同的业务分配不同权限的命令比如某个业务只允许读写某个 key 前缀。实际生产环境我没见过多少团队把 ACL 用得很彻底大多数是“一个 requirepass 走天下”。但如果你接手了一个多租户的 Redis 集群ACL 绝对是值得研究的治理手段。3.3 持久化选型RDB、AOF 还是混合Redis 默认是内存数据库数据不在磁盘上落盘。一旦进程重启或机器断电内存数据全部丢失。但在绝大多数缓存场景里丢失是可以容忍的因为缓存可以从数据库重新回填。不过如果你想拿 Redis 存一些不能丢的业务数据就必须开启持久化。RDB快照是默认开启的它会在满足触发条件时把内存数据打一个快照存到dump.rdb。默认配置是save 900 1、save 300 10、save 60 10000意思是 900 秒内发生 1 次写操作就存盘300 秒内发生 10 次写操作就存盘60 秒内发生 10000 次写操作就存盘。RDB 文件恢复速度快适合做备份和灾难恢复但快照存在间隔如果 59 秒内发生了写入但还没到触发点突然宕机这 59 秒的数据就丢了。AOF追加日志模式是把每次写命令追加到appendonly.aof文件里重启时通过回放命令来恢复数据。它比 RDB 更安全但文件一般更大、恢复速度也更慢。生产环境里我最常用的搭配是appendonly yes appendfsync everyseceverysec表示每秒同步一次 AOF 缓冲区到磁盘兼顾性能和数据安全。三个可选项分别是always每次写都同步最安全但最慢、everysec每秒钟同步一次折中、no交给操作系统决定性能最好但不安全。我一般推荐everysecRedis 官方也是这个建议。如果你不想纠结直接同时开启 RDB 和 AOF 也行。Redis 启动时会优先用 AOF 文件恢复数据因为它的数据更新的频率更高。文件格式和恢复顺序是面试题里常出现的考点理解了这层逻辑就不会把 RDB 和 AOF 的关系搞混。3.4 maxmemory 和淘汰策略不设内存上限等于埋雷内存是 Redis 最贵的资源。默认情况下 Redis 对内存使用没有上限如果你把大量 key 写进去又不清理内存迟早被打爆。设置上限的配置是maxmemory 4gb maxmemory-policy allkeys-lrumaxmemory可以写字节数也可以写 gh 这种简写4gb 表示 4GB。关键在maxmemory-policy的选择noeviction达到上限后不再接受写请求直接返回错误这种策略保证数据完整性但会触发线上报警allkeys-lru按照 LRU最近最少使用算法淘汰所有 key这是缓存场景最常用的策略volatile-lru只对设置了过期时间的 key 进行 LRU 淘汰适合有些 key 不能丢的场景allkeys-random随机淘汰任意 key适合缓存数据均匀分布的场景我之前在项目里踩过一个坑某业务缓存的数据量超出预期但配置的是noeviction结果达到上限后 Redis 拒绝写入整个业务链路都在报错。后来我把策略改成allkeys-lru并且对缓存 key 都设置了合理过期时间问题立刻缓解。缓存治理的第一课就是搞清楚内存上限和淘汰策略。3.5 一份可落地的推荐配置模板给你一份我参考过的、可以直接抄的配置模板主要适用于生产环境单机 Redisbind 127.0.0.1 protected-mode yes port 6379 tcp-backlog 511 timeout 0 tcp-keepalive 300 daemonize no supervised systemd pidfile /var/run/redis/redis-server.pid loglevel notice logfile /var/log/redis/redis-server.log databases 16 always-show-logo no requirepass yourpassword maxmemory 4gb maxmemory-policy allkeys-lru save 900 1 save 300 10 save 60 10000 stop-writes-on-bgsave-error yes rdbcompression yes rdbchecksum yes dbfilename dump.rdb dir /var/lib/redis appendonly yes appendfilename appendonly.aof appendfsync everysec auto-aof-rewrite-percentage 100 auto-aof-rewrite-min-size 64mb这里daemonize no和supervised systemd是配套的让 Redis 以 systemd 托管的方式运行日志交给 journald 也照样能看到。4. 命令行与五种数据类型的实战语法不用背也能熟练掌握4.1 先学会看状态再谈操作不管你是用redis-cli还是图形工具连接 Redis 以后第一件事不是急着写 key而是确认实例的基本状态redis-cli INFO server INFO memory DBSIZEINFO server会显示 Redis 版本、运行模式、端口这些基本信息INFO memory会展示used_memory_human、peak_memory_human等内存情况这是判断是否需要调maxmemory的依据DBSIZE返回当前库里的 key 总数能直接看出来数据规模。还有一个容易被忽略的指令是FLUSHALL它会把整个实例的数据全清空。在测试环境随便用没事生产环境要是按错一下数据直接人间蒸发。我见过不止一次有人在生产上把FLUSHALL当成FLUSHDB用清完还一脸懵。所以操作前一定要确认自己连接的到底是不是生产的实例。4.2 String 类型缓存、计数器、限流都靠它String 是最基础的类型业务里的缓存值、商品库存、接口调用次数基本都是用它。 SET user:1001:name zhangsan GET user:1001:name INCR page:view EXPIRE user:1001:name 3600 TTL user:1001:nameSET和GET是成对出现的INCR是自增操作可以把一个字符串按数字处理并自增 1适合做计数器。很多人会问“为什么不用数据库来计数”因为 Redis 是单线程模型INCR是原子操作不会出现并发写入导致计数丢失的问题。EXPIRE设置过期时间TTL查询剩余存活时间这两个命令是缓存治理的标配。线上的缓存 key 一定要设置过期时间不然数据变成“永久垃圾”内存会被吃光。这个道理和冰箱里不能只放不拿是一个逻辑只进不出迟早塞满。4.3 List最简单的任务队列List 是一个双向链表可以从头部或尾部插入、弹出元素天然的队列结构 RPUSH task:email user1example.com RPUSH task:email user2example.com LPOP task:email LRANGE task:email 0 -1RPUSH往队列尾部放任务LPOP从头部取任务这样就实现了一个 FIFO 队列。结合阻塞命令BLPOP消费者可以在没有任务时阻塞等待而不是轮询空转消耗 CPU BLPOP task:email 5如果 5 秒内队列为空命令返回 nil如果队列有数据立即返回头部元素。这是 Redis 作为简单消息中间件的一种玩法适合任务量不大、不想额外引入 Kafka 等消息队列的轻量场景。4.4 Hash把业务对象存成一张“迷你表”Hash 适合存储对象比如用户信息、商品详情 HSET user:1002 name lisi age 18 HGETALL user:1002 HGET user:1002 name HINCRBY user:1002 age 1一个 Hash 键下可以挂多个字段HGETALL能一次性取出全部字段但字段很多时有性能风险——它一次性返回全部内容字段越多网络开销越大。所以对象字段多的时候尽量用HMGET只取需要的字段。Hash 的另一个典型场景是购物车商品 ID 是字段商品数量是值HINCRBY可以方便地增减数量。4.5 Set 和 ZSet去重、好友关系、排行榜Set 是无序不重复集合适合做去重和集合运算 SADD user:1001:tags java redis SADD user:1002:tags python redis SINTER user:1001:tags user:1002:tags SCARD user:1001:tagsSINTER求交集能算出两个人共同的技术标签“SCARD” 返回集合大小可以做在线人数统计。ZSet 在 Set 的基础上给每个元素加了一个 score 分数按分数排序这是排行榜的标准姿势 ZADD ranking 100 user:1 ZADD ranking 90 user:2 ZRANGE ranking 0 -1 WITHSCORES ZREVRANGE ranking 0 -1 WITHSCORESZREVRANGE按分数从高到低取排行直播送礼榜、积分榜都是这个套路。Redis 面试题里必考的五种数据结构其实就是这五种类型理解它们的用途比背命令更重要。4.6 图形化工具与连接注意事项命令行够用但日常排查时图形工具效率更高。网上常见的 Redis 连接工具有不少比如 Redis Desktop Manager 家族下的衍生工具、Another Redis Desktop Manager以及 TablePlus 这类通用数据库客户端对 Redis 也有支持。选择一个自己顺手的即可——工具只是外壳要理解里面的数据模型。使用图形工具时需要特别留意连接地址要填对端口默认 6379设置了密码要填密码。很多人第一次用图形工具连不上不是因为 Redis 配置有问题而是安全组/防火墙没有放行 6379 端口。后面排查章节我会给一个完整链路。5. 缓存治理与分布式锁Redis 的进阶玩法5.1 穿透、击穿、雪崩缓存没治理好数据库跟着遭殃把 Redis 当缓存用最经典的三个问题是缓存穿透、缓存击穿和缓存雪崩。它们是面试题里的常客更是生产事故里的常客。缓存穿透查询一个不存在的 key缓存和数据库里都没有请求每次都打到数据库。解决办法是“空值缓存”或者“布隆过滤器”。空值缓存的意思是数据库查不到也把 null 写入缓存并设置短过期时间避免下一次相同请求穿透到数据库。缓存击穿某个热点 key 过期瞬间大量请求同时涌入数据库。解决办法是“互斥锁/分布式锁”或者“逻辑过期”。互斥锁保证只有一个请求去数据库重建缓存其他请求等待逻辑过期是不设置真实的过期时间而是在 value 里记录过期时间后台异步刷新。缓存雪崩大量 key 同时过期导致数据库压力突增。解决办法最简单——过期时间加一个随机因子比如 3600 秒基础上随机 0~300 秒让过期时间错开。我在生产上就是这么做的效果立竿见影。5.2 SET NX EX 分布式锁的正确用法与主从丢锁问题分布式锁是 Redis 高频使用场景。核心命令是SET key value NX EX 秒数意思是只有 key 不存在时才设置成功并且同时设置过期时间。这样能保证同一时刻只有一个客户端拿到锁 SET lock:order:1001 client-1 NX EX 10第一个客户端执行成功返回 OK拿到锁第二个客户端执行返回 nil拿不到锁。业务处理完再执行DEL lock:order:1001释放锁。这里有个关键点加锁和设置过期时间必须在一个命令里完成。早期版本的写法是先SETNX再单独EXPIRE中间如果客户端崩溃锁就永远不会过期形成死锁。现在官方的SET key value NX EX是原子操作不再有这个问题。还有更复杂的情况如果你用 Redis 主从架构主节点挂了以后从节点顶上锁信息可能还没同步到从节点就会造成“两个客户端同时拿到锁”的严重问题。Redis 官方为此推出了 Redlock 算法要求在多个独立节点上加锁但 Redlock 本身也有争议工程上实现成本不小。我的建议是如果你的团队还没到“分布式锁一旦失效就会造成资损”的量级用单节点 Redis 加SET NX EX足够别过度设计。5.3 序列化选择StringRedisTemplate 还是 GenericJackson2JsonRedisSerializer如果你是 Java 后端一定会遇到 RedisTemplate 序列化的问题。热搜词里“redis序列化”被搜了很多次可见这件事困扰了不少人。Spring Data Redis 默认的 JdkSerializationRedisSerializer 会序列化成二进制key 和 value 在客户端看起来是一堆乱码而且体积大、有反序列化漏洞风险。我强烈建议改成 JSON 序列化RedisTemplateString, Object template new RedisTemplate(); StringRedisSerializer stringSerializer new StringRedisSerializer(); GenericJackson2JsonRedisSerializer jsonSerializer new GenericJackson2JsonRedisSerializer(); template.setKeySerializer(stringSerializer); template.setHashKeySerializer(stringSerializer); template.setValueSerializer(jsonSerializer); template.setHashValueSerializer(jsonSerializer);如果你存的对象结构非常简单甚至可以直接用StringRedisTemplate把对象手动转成 JSON 字符串再存。字符串序列化最大的好处是肉眼可读、调试方便、兼容性好排错时redis-cli GET一下就能看到内容。5.4 Redis 做中间件发布订阅与更轻量的消息通道热搜词里有一条“redis做中间件”其实指的是 Redis 除了缓存、存储之外还能承担消息发布订阅的角色。PUBLISH channel message和SUBSCRIBE channel可以实现一个非常轻量级的广播消息系统 SUBSCRIBE news PUBLISH news hello但PUBLISH/SUBSCRIBE模式有几个硬伤消息不持久化订阅者不在线就收不到没有消息确认机制消费者挂了消息就丢了。所以在需要可靠投递的场景Redis 官方更推荐 Stream 类型它支持消费组、消息持久化和 ACK 确认某种程度上可以替代很基础的消息队列。如果你的业务消息量不大不想引入额外的中间件组件用 Redis Stream 做一个轻量消息通道是完全可行的。但消息量到了一定规模或者你需要更复杂的重试、死信队列能力还是让专业的消息队列来处理比较好。6. 踩坑实录我在 Ubuntu 上折腾 Redis 遇到的五个典型问题6.1 daemonize 与 systemd 的冲突apt 装完 Redis 后用systemctl start redis-server发现服务状态一直是degraded或者直接失败但手动执行redis-server又能跑起来。这个问题通常出在配置文件的daemonize参数上。apt 默认的配置文件已经设置了daemonize no和supervised systemd。如果你习惯了网上手写配置的风格把daemonize yes写进去Redis 会自己 fork 一个后台进程但 systemd 发现主进程退出就认为服务停了状态就成了失败。排查方式很简单打开/etc/redis/redis.conf确认daemonize no然后sudo systemctl restart redis-server再观察。6.2 Redis Command timed out 的完整排查链路热搜词里“Redis command timed out; nested exception is io.lettuce.core.RedisCommandTimeoutException”这套报错非常典型尤其在 Spring Boot 项目里用 Lettuce 连接池时。看到这个异常第一步不要慌按下面的链路排查确认 Redis 网络是否可达在应用服务器上执行redis-cli -h redis-ip ping。确认 Redis 是否过载INFO cpu和INFO commandstats看命令耗时。如果used_cpu_sys很高说明 Redis 本身处理不过来。检查应用侧连接池参数Lettuce 默认没有设置最大连接数高并发下可能把 Redis 的连接打满。确认是否有慢命令阻塞执行SLOWLOG GET 10看看有没有执行时间异常长的命令。比如大量使用KEYS *在线上做全量扫描就会造成阻塞。我当时遇到的根因是两个一是连接池参数太小maxTotal只有 8并发一上来就超时二是代码里有几个定时任务用KEYS扫描全库直接把 Redis 拖慢。把慢查询换成SCAN增量迭代再把连接池调大问题就消停了。6.3 AOF 文件膨胀与自动重写只开启 AOF 持久化后文件会随着写入增长重放日志的时间也会越来越长。Redis 提供了 AOF 重写机制它会把内存中的当前数据重新写一个更精简的 AOF 文件而不是简单地追加命令。相关配置是auto-aof-rewrite-percentage 100 auto-aof-rewrite-min-size 64mb意思是当前 AOF 文件比上次重写时增长超过 100%且文件大于 64MB就触发自动重写。这套默认配置在生产环境基本够用。如果磁盘空间很紧张可以调低auto-aof-rewrite-percentage到 80让重写更频繁如果对恢复时间敏感也可以手动执行BGREWRITEAOF。AOF 重写是后台 fork 子进程执行的不会阻塞主线程但如果机器内存很紧张fork 时可能会有延迟这也是突然出现命令超时的原因之一。6.4 服务起来了但外部连接失败Redis 明明已经运行本地 redis-cli ping正常但其他机器连不上。这个问题按以下顺序排查基本能就地解决检查监听地址ss -lntp | grep 6379看监听的是127.0.0.1还是0.0.0.0还是具体内网 IP。检查防火墙Ubuntu 上常见的是 ufw执行sudo ufw status查看 6379 端口是否放行。检查云安全组如果你用的是云服务器安全组只放行了 22 端口那 Redis 端口肯定不通这跟服务器本身配置没关系。这串排查思路同样适用于 MySQL、PostgreSQL 等其他端口服务熟了以后可以举一反三。6.5 升级 Redis 后数据文件不兼容大版本升级之前最简单的保险措施就是先备份/var/lib/redis目录或者用redis-cli BGSAVE手动触发一次快照。升级后启动失败先别急着删数据文件用 Redis 自带的工具检查redis-check-rdb /var/lib/redis/dump.rdb redis-check-aof /var/lib/redis/appendonly.aof这两个工具能告诉你 RDB/AOF 文件是否损坏、是否存在版本不兼容。如果确实不兼容可以根据备份做恢复而不是盲目地FLUSHALL。我见过有人在升级失败后直接删除 dump.rdb 重启Redis 是起来了但历史数据全没了。Redis 启动时如果发现 RDB 文件损坏有一个选项是在配置里设置rdbchecksum no临时忽略然后尽快手动备份。这个操作只能救急不能长期开启否则数据完整性就没有保障了。最后再分享一个小技巧我在实际使用中发现INFO stats里有个字段叫keyspace_hits和keyspace_misses对应缓存命中率和未命中率。线上排查缓存是否有效不用靠猜直接看这两个数字的比值就行。如果 miss 率持续偏高说明缓存的过期时间设置不合理、key 设计有问题或者某些请求压根没走缓存这个指标比任何监控面板都直观。你先把 Redis 装好、配置理顺再把这个命中率盯上缓存治理就算真正入门了。
返回列表