接手一个Redis实例,第一件事永远是翻配置文件。我见过太多人直接用默认配置跑生产环境,结果内存被打满、数据丢了、主从裂了才回头查资料。Redis的配置文件(redis.conf)是它所有行为的底层逻辑,你不管是做缓存、做分布式锁,还是搭主从集群,最终都要落到这一堆参数上。这篇文章不打算讲空泛的原理,我直接把配置里那些关键项的信息掰开,哪些参数动了会有什么后果,生产环境怎么调,照着抄作业就行。
先说清楚,Redis 6.x以上版本支持用 redis.conf 或命令行参数混合配置,也有 CONFIG SET 这种运行时修改方式。我下面讲的所有内容,以 redis.conf 为主,因为它可维护性最好,改动可追溯,重启也能生效。适合谁看?准备搭Redis但没系统梳理过配置项的,被诡异线上问题坑过的,或者面试前想把Redis底层行为讲清楚的,都适合往下看。
1. 配置文件到底是什么角色
1.1 配置项背后管的四件事
打开redis.conf,几百行配置看着唬人,但归类下来就四块:内存怎么管(上限、淘汰策略)、数据怎么存(持久化RDB/AOF)、网络怎么暴露(端口、绑定、认证)、副本怎么同步(主从复制)。这四个方向基本覆盖了99%的日常问题和故障场景。
举个例子,你启动Redis时看到 warning 提示 overcommit_memory=0,这就是操作系统层面和Redis持久化fork子进程之间的配合问题,也可以归到“数据怎么存”这一类。再比如线上突然查不到key了,排查方向大概率在“内存怎么管”里头的 maxmemory-policy 配置上。也就是说,你不需要背下每行配置,只需要知道每一类配置对应哪类故障,排查路径自然就短了。
1.2 配置文件的加载优先级和生效机制
Redis找配置文件有三种途径:启动命令指定、默认路径、环境变量。最常见的还是启动时显式指定,比如:
redis-server /etc/redis/redis.conf如果启动时不带配置文件,Redis会用内置默认值启动,很多参数和redis.conf里的注解默认值不完全一样。这里有个坑,部分云厂商镜像、Docker容器会把配置文件放在不同路径,如果你不确认就直接跑默认配置,大概率是裸奔状态。
配置文件之外,运行时还能动态调整:
# 运行时查看当前配置 redis-cli CONFIG GET maxmemory # 运行时修改配置(不持久化) redis-cli CONFIG SET maxmemory 2gb # 让运行时配置写入配置文件 redis-cli CONFIG REWRITE注意:CONFIG SET 能解决临时问题,但机器重启后会丢,一定要执行 CONFIG REWRITE 把改动落盘到配置文件。不过这个命令有个限制,它只能重写它认识的参数,如果配置文件里有自定义的include附加文件,重写行为要小心验证。我在生产环境踩过一次,CONFIG REWRITE 把配置文件注释全改了,虽然参数值没错,但diff看起来非常吓人。所以规范做法是:临时调优用CONFIG SET,确认有效后手动改配置文件,别依赖REWRITE。
2. 核心参数拆解:内存、持久化和网络
2.1 内存上限和淘汰策略必须配对看
线上Redis最常见的死法就是内存满了但不淘汰,然后写入报错。配置项里两兄弟必须一起看:maxmemory 和 maxmemory-policy。
# 设置最大内存为4GB maxmemory 4gb # 设置淘汰策略为allkeys-lru maxmemory-policy allkeys-lrumaxmemory-policy 有8个取值,核心就这么记:有volatile开头的只淘汰设置了过期时间的key,有allkeys开头的对所有key动手。剩下的后缀,lru按最近最少使用,lfu按访问频率,random随机,ttl优先淘汰剩余寿命短的。生产环境通用选择:
| 使用场景 | 推荐策略 | 原因 |
|---|---|---|
| 纯缓存,允许丢数据 | allkeys-lru | 整体命中率最均衡 |
| 缓存 + 部分持久数据 | volatile-lru | 只淘汰临时的key不动核心数据 |
| 访问热度差异大的数据 | allkeys-lfu | 防偶发扫描把热点key淘汰 |
| 极端情况防写入失败 | noeviction | 宁可报错也不丢key |
事务和Lua脚本执行期间,Redis的淘汰策略是暂停的,所以如果清理由大key导致耗时过长,会间接阻塞后续命令。这也是为什么一次删除几十个大key会让整个实例卡顿。
实操心得:设置maxmemory时,千万别把机器物理内存用满。Redis做持久化时fork子进程会额外占用内存(写时复制),一般建议Redis内存上限不超过机器物理内存的60%-70%。比如8GB的机器,maxmemory设置5GB左右比较稳,留出来的空间就是为了应对fork瞬间的内存尖峰。
2.2 RDB和AOF怎么配合不丢数据
持久化是Redis配置里最绕不开的话题,毕竟谁都不想重启一下数据没了一半。RDB是定期全量快照,AOF是追加写操作日志。两者可以同时开,Redis默认是RDB开启,AOF默认关闭。
# RDB快照触发条件:900秒内有1次写、300秒内有10次写、60秒内有10000次写 save 900 1 save 300 10 save 60 10000 # AOF开启 appendonly yes # AOF刷盘策略,everysec是性能和安全的平衡 appendfsync everysec # AOF重写触发条件,比初始文件大一倍就重写 auto-aof-rewrite-percentage 100 auto-aof-rewrite-min-size 64mb这里最值得说清楚的是AOF的三种同步策略:
- always:每写一条命令就同步一次磁盘,最安全但性能最差,实测吞吐下降很明显,一般不用。
- everysec:每秒同步一次,最多丢1秒数据,性能和安全的平衡点,生产首选。
- no:完全交给操作系统决定什么时候落盘,数据安全性最差,但性能最好。
有人会问,既然AOF更安全,把appendonly yes,RDB是不是就可以关掉?实际上官方都建议两者共存。RDB恢复速度快,适合做灾备和冷启动;AOF弥补RDB两次快照之间的数据窗口。而且Redis 7.0以后AOF文件由多个文件组成,可以通过redis-check-aof工具单独修复损坏的历史AOF文件。
注意事项:RDB的save参数触发的是主进程fork一个子进程做快照。如果内存很大,fork瞬间会卡顿几十毫秒甚至更长。所以要监控fork耗时和瞬时内存,别把save条件设得太激进。另外,AOF文件如果增长太快,要确认auto-aof-rewrite配置合理,否则磁盘会被撑爆,极端情况下Redis会直接拒绝写入。
2.3 网络层配置和连接数
网络层配置看着简单,但坑不少。默认Redis监听6379,bind参数如果不设置,Redis 3.2以上版本默认只绑本机回环地址,也就是只有本机能连,外部一律连不上。很多人装完Redis发现远程连不上,80%是这个原因。
# 监听所有网卡 bind 0.0.0.0 # 或者绑定指定内网IP bind 192.168.1.100 # 连接空闲300秒自动断开 timeout 300 # TCP keepalive,检测死连接 tcp-keepalive 60 # 最大客户端连接数,默认10000 maxclients 10000生产环境建议bind内网IP,不要bind 0.0.0.0。结合下面的protected-mode保护模式和requirepass密码,否则就是给公网裸奔。
连接数上容易踩的坑是maxclients设置过高但系统文件描述符限制没跟上,Redis启动会报警告。需要同时调整系统limit,比如:
ulimit -n 65535然后在redis.conf里maxclients 50000。如果发现连接数频繁打满,优先排查客户端连接池配置,而不是一味调大Redis侧限制,很多情况是客户端没用连接池,短连接风暴把实例压垮的。
3. 主从复制、持久化联动和分布式锁的配置前提
3.1 主从复制的配置和常见陷阱
主从配置本身很简单,从节点配置文件里写一行:
# 指定主节点IP和端口 replicaof 192.168.1.100 6379但如果主节点开了密码认证,从节点必须配置masterauth,否则同步会一直报MASTER auth failed:
masterauth 你的密码复制方式的参数有两个可以关注:
# 主节点是否开启基于磁盘的复制,no表示尝试无磁盘复制 repl-diskless-sync no # 从节点是否只读 replica-read-only yesreplica-read-only建议保持yes。如果你手滑在从节点上写了数据,会造成主从数据不一致,而且同步恢复时这些多余数据可能直接导致同步失败或数据混乱。我就见过有人为了在从节点临时查数据开了写权限,结果事故现场惨不忍睹。
主从架构下的持久化设置:官方其实允许从节点关闭持久化只做备份,但生产环境别这么干。主节点挂了,从节点是唯一数据源,从节点又没开持久化,重启后可能变成空库。正确做法是主从都开AOF,从节点可以适当放宽RDB频率,但不能两头都关。
3.2 分布式锁要怎么配置才不坑
Redis分布式锁是高频热词,但很多人只关心Redisson代码怎么写,忽略了配置文件层面的配合。分布式锁底层依赖两个核心命令:SETNX和EXPIRE。这两个命令能正常工作,前提是Redis没有运行在会丢数据的危险配置下。
如果你用Redis做分布式锁,至少满足这三点:
- 开启AOF且appendfsync设为everysec或always(防止锁信息丢失)。
- 不要使用allkeys-lru这类可能把锁key淘汰掉的淘汰策略,锁key一般应该用volatile开头或者noeviction。
- 主从模式下要谨慎,因为主节点宕机切换,锁数据可能还没同步到从节点,导致锁失效。严格方案是Redlock,但Redlock需要至少3台独立实例,运维复杂度高,一般业务用主从加AOF已经够用。
# 配合分布式锁的推荐持久化配置 appendonly yes appendfsync everysec maxmemory-policy noeviction这个组合的意思是:锁数据不淘汰,AOF保证重启不丢锁。代价是如果内存真的满了,写入会报错而不是淘汰。所以,锁的key一定要设置合理的TTL,别把锁key当缓存无限期放着。
3.3 哨兵和集群模式与配置文件的联动
Redis Sentinel(哨兵)和Redis Cluster(集群)虽然都有各自的配置文件,但很多参数依然继承自redis.conf。比如:
# 集群模式下,节点间通信端口默认是基础端口+10000 cluster-enabled yes cluster-config-file nodes-6379.conf集群模式推荐关掉RDB的save触发,因为你数据量大了以后,频繁全量快照会让整个集群的带宽和CPU都遭罪。然后AOF的rewrite也要设置得保守一点,毕竟集群本身就做了多副本,单节点数据恢复压力小很多。但关掉RDB不等于不备份,定期用redis-cli --rdb手动导出备份还是很有必要的。
哨兵模式下,sentinel.conf里点名了要监控哪个Redis主节点:
sentinel monitor mymaster 127.0.0.1 6379 2这里的“2”表示需要2个哨兵节点同时判定主节点客观下线,才会触发故障转移。这个数字不能大于哨兵节点数的一半,否则永远无法触发切换。很多人搭哨兵集群的时候在数字上翻车,导致主节点宕机了哨兵光看着不动手。
4. 安全加固和日志配置
4.1 密码认证:别让Redis裸奔
Redis默认无密码,这一点在生产环境是致命的。黑客扫描到6379端口后,可以直接写入定时任务反弹shell。安全配置的核心是这两个:
# 设置密码 requirepass 你足够复杂的密码 # 开启保护模式 protected-mode yesprotected-mode这个参数的含义要理解到位:它只有在没有显式配置bind和requirepass时才生效,一旦你绑定了网卡或者设置了密码,保护模式基本上是退出舞台的。所以你不能“开了protected-mode就高枕无忧”,必须显式设置requirepass。
Redis密码认证相对简单,但要注意:
- 密码不要用弱口令,Redis暴力破解脚本满天飞。
- 密码不要在命令行直接传,会留在history里。用redis-cli的时候,设置环境变量REDISCLI_AUTH更安全:
export REDISCLI_AUTH=你的密码 redis-cli -h 127.0.0.1 -p 6379 ping- requirepass会影响主从复制,从节点用masterauth配置同步密码。改了主节点密码,别忘了同步改所有从节点的masterauth,否则复制全断。
4.2 日志级别和慢日志怎么配置
排查问题离不开日志,Redis的日志配置也要提前做好:
# 日志级别,debug最详细,notice是生产推荐 loglevel notice # 日志文件路径,默认是空(输出到标准输出) logfile "/var/log/redis/redis.log" # 日志是否记录每个写命令,生产不建议开 # 慢日志阈值,单位微秒,超过就记录 slowlog-log-slower-than 10000 slowlog-max-len 128slowlog是一个很容易被忽略但很好用的功能。设置slowlog-log-slower-than为10000微秒(10毫秒),凡是执行超过10毫秒的命令都会被记录下来。通过:
slowlog get 10可以查看最近慢命令。排查Redis性能问题,第一步就是看慢日志,它能直接揪出哪些大key或复杂命令在拖慢整个实例。注意:slowlog不会记录超过阈值的命令参数内容,只记录命令类型、参数个数、耗时和来源,保护隐私也够用。
日志级别生产用notice就够,debug日志量太大,除非临场排查否则别开,否则磁盘很快就满。
5. 实操:从零写一份可落地的生产redis.conf
5.1 一份可以抄的配置模板
根据我前面说的参数,给你一份可复制的完整模板。假设机器8G内存,主要用作业务缓存,同时承担一部分分布式锁,主从架构中的从节点也适用,只需要改replicaof和masterauth。
# 绑定内网IP,不要0.0.0.0 bind 192.168.1.100 port 6379 # 守护进程运行,写pid文件 daemonize yes pidfile /var/run/redis_6379.pid # 日志 loglevel notice logfile "/var/log/redis/redis.log" # 密码 requirepass 你的强密码 # 内存上限,8G机器给5G maxmemory 5gb maxmemory-policy allkeys-lru # RDB快照条件,用于冷备 save 900 1 save 300 10 save 60 10000 rdbcompression yes dbfilename dump.rdb dir /var/lib/redis # AOF持久化 appendonly yes appendfilename "appendonly.aof" appendfsync everysec auto-aof-rewrite-percentage 100 auto-aof-rewrite-min-size 64mb # 网络与连接 tcp-backlog 511 timeout 300 tcp-keepalive 60 maxclients 30000 # 慢日志 slowlog-log-slower-than 10000 slowlog-max-len 128 # 主从复制(从节点取消注释) # replicaof 192.168.1.1 6379 # masterauth 你的强密码 replica-read-only yes5.2 配置完成后验证哪些东西
配置文件写完,启动之前先检查语法,Redis没有专门的config test命令,但可以这样验证:
# 用配置文件方式启动,如果配置有错会直接报错退出 redis-server /etc/redis/redis.conf # 启动后确认基本信息 redis-cli -a 你的密码 INFO server redis-cli -a 你的密码 INFO memory redis-cli -a 你的密码 INFO persistence redis-cli -a 你的密码 INFO replication几个需要重点观测的指标:
- mem_fragmentation_ratio:内存碎片率,在INFO memory里。大于1.5说明碎片严重,小于1说明可能触发了swap。
- rdb_last_bgsave_status:最近一次RDB快照是否成功,ok就正常。
- aof_last_write_status:AOF写入状态,如果报错要立刻处理。
- master_link_status:主从同步状态,up正常,down异常。
别等出事才开始看这些,建议把这几个指标接入监控或者写脚本定时巡检,Redis数据故障很多都是渐进式的,比如磁盘快满、内存碎片率升高,早发现早处理。
5.3 配置变更的发布流程
修改配置也讲究流程。我的习惯是这样:
先在测试环境用CONFIG SET做变更,观察半天到一天,稳定之后再把改动同步到redis.conf。生产环境变更前,一定要先备份配置文件,再用redis-cli CONFIG GET对比新旧差异,搞清每一项变更的影响面,再动手。
如果是主从架构,改配置尽量按“从节点 → 主节点”的顺序滚动,避免主节点一改,从节点复制全断。改密码尤其要按这个顺序,先改从节点的masterauth,重启从节点确认同步正常,再改主节点的requirepass,最后再改应用侧的连接配置。
6. 常见问题与排查技巧实录
6.1 高频故障速查表
| 现象 | 大概率原因 | 排查/处理办法 |
|---|---|---|
| 远程连不上Redis | bind配置只绑了127.0.0.1 | 检查bind和protected-mode |
| 密码错误但确认输入无误 | requirepass被CONFIG SET临时改过 | 执行CONFIG GET requirepass查看实际值 |
| Redis进程还在但所有写入报OOM | 内存满了且maxmemory-policy为noeviction | 扩大maxmemory或调整淘汰策略 |
| 实例重启后数据全没了 | AOF没开且RDB最近没有成功触发 | 确认appendonly yes,检查save条件 |
| 主从同步一直down | 从节点masterauth配置不对 | 在从节点执行INFO replication查看错误 |
| 延迟突然变高 | 有大key被淘汰或fork耗时过长 | 查看slowlog,检查最近RDB触发时间 |
| 日志中有short read或bad file format | AOF文件损坏 | 用redis-check-aof修复或恢复RDB |
6.2 一个典型的排查实录
有一回我接手一个线上Redis,表现为从节点同步断了又自动恢复,周而复始。先看INFO replication,发现master_link_status在up和down之间横跳。查主节点日志,有一条:
MASTER <-> REPLICA sync: Flushing old data然后就看从节点日志,报:
Short read from RDB: 4096 bytes, please check master's RDB file size这种情况一般是RDB快照文件传输中断。最后定位到原因:主节点同时开启了RDB和AOF重写,fork子进程争抢磁盘IO,加上磁盘性能一般,RDB传输超时导致从节点反复断连。处理办法是把repl-timeout调大,同时错开主节点的RDB和AOF重写时间窗口。配置:
repl-timeout 120顺便检查了下主节点磁盘,发现是机械盘,后续升级成SSD才彻底解决。这个例子说明,配置文件里的参数都不是孤立的,repl-timeout、磁盘性能、快照频率是联动的,排查问题要纵向把链路全看一遍,别只盯一个参数。
6.3 关于配置备份和审计的建议
配置文件本身也是资产。我吃过亏:一次误改配置导致内存淘汰策略被改成noeviction,结果业务写入全失败,但这个问题直到晚上流量高峰才爆发。从那以后我做配置变更必留diff记录,也建议你们这样:
# 变更前备份配置 cp /etc/redis/redis.conf /etc/redis/redis.conf.$(date +%F_%H-%M) # 变更后diff检查 diff /etc/redis/redis.conf.$(date +%F_%H-%M) /etc/redis/redis.conf # 用CONFIG GET批量核对运行时配置 redis-cli CONFIG GET maxmemory-policy如果你用了配置管理工具(Ansible、Puppet等),把redis.conf纳入版本管理,每次变更走评审。别小看这步,很多故障其实都是“我记得改过什么但后来忘了”导致的。Redis配置文件虽然就几百行,但它决定了一个实例的生存质量,花半小时逐行弄明白,比出事排查两小时划算得多。
我个人在实际操作中的另一个体会是,不管运维规范多完善,还是要养成看启动日志的习惯。每次Redis启动,日志都会打出它加载了哪个配置文件、用了什么参数。这个信息能帮你快速确认“实例当前到底按哪套配置在跑”,尤其是多个实例共用一台机器时,A实例和B实例往往配置文件路径不同。先确认身份,再谈调优。