拓冰建站拓冰建站
首页 / 资讯中心 / 正文

Redis配置文件redis.conf核心配置详解与避坑指南

Redis配置文件也就是redis.conf是每个用Redis的人都绕不开、但又常常没仔细钻研的文件。很多人第一次接触Redis是apt install redis-server或者Docker一把梭拿到手就能跑默认配置用了一年也没出事。直到某天内存被打满、数据莫名其妙丢了一部分、或者Redis被公网扫描进来写了个定时任务才回过头来研究这个几百行的配置文件。我在帮团队排查线上Redis问题时发现十次事故里至少有七次根因都能追溯到某个配置项没设置对或者是配置改了但没真正生效。这篇文章我就把redis.conf里最常踩坑、最影响业务的核心配置项全部拆开讲一遍从加载机制到内存、持久化、安全、慢查询再到一份可以直接抄作业的配置模板希望能帮你少走半年弯路。1. 配置加载机制你的Redis到底读的是哪一份配置文件1.1 不带任何参数启动时默认配置从哪来很多人有这样一个误区以为Redis启动时一定会去读redis.conf其实不一定。你用redis-server直接启动Redis用的是编译时写死的默认配置根本不会自动找某个配置文件来读。这个默认配置的值是多少可以通过CONFIG GET *查看比如默认maxmemory 0、databases 16、save 3600 1这些都是内置默认值跟磁盘上的任何文件都没有关系。如果你用apt或yum安装的Redis包管理器会在/etc/redis/redis.conf放一份配置文件并且注册为systemd服务。服务启动命令通常会带上配置文件路径比如redis-server /etc/redis/redis.conf。如果你是自己编译安装的Redis默认配置文件就在源码目录下的redis.conf需要你手动复制到/usr/local/etc/或者其他目录再指定加载。Docker方式运行时要特别注意官方镜像里默认是没有redis.conf的如果你不把宿主机上的配置文件挂载进去容器内完全是默认配置启动。判断当前进程到底有没有读配置文件最简单的办法就是看启动命令。执行ps -ef | grep redis如果redis-server后面跟着文件路径说明是通过配置文件启动的如果只看到一个redis-server *:6379那很可能就是默认配置硬跑的。1.2 启动参数、配置文件、CONFIG SET 三者的优先级Redis的配置来源其实有三个层级启动命令行参数、配置文件、运行时CONFIG SET命令。这三者的生效优先级是命令行参数 配置文件 内置默认值而CONFIG SET属于运行时动态修改不重启的话优先级最高一旦重启就丢失回到启动时加载的值。有个非常实用的技巧命令行参数可以临时覆盖配置文件里的值适合快速调试。比如配置文件里设置了port 6379但你临时想用6380跑一个实例不需要改配置文件直接执行redis-server /etc/redis/redis.conf --port 6380启动后端口就会是6380。这时你如果在客户端执行CONFIG GET port看到的结果也是6380但磁盘上的redis.conf并没有被修改。这种机制方便是方便但也很容易坑人你改完配置文件忘了重启或者启动脚本里带了某个--xxx参数重启后跟你预期不一致完全找不到原因。我曾经排查过一台机器上Redis端口到了6380但配置文件里明明是6379的情况最后发现是systemd的ExecStart那行末尾多了个参数。1.3 验证当前生效配置CONFIG GET 的正确用法不管你是通过什么方式改的配置最终以运行进程为准。查真实生效配置的方式是进入redis-cli执行redis-cli CONFIG GET maxmemory CONFIG GET *CONFIG GET *会把当前所有生效配置全打出来大概有两百多项。不要用cat redis.conf来判断实际生效值这个文件只是启动时的输入不能反映运行状态。我在实战中经常碰到同事拿着配置文件跟我说我明明改成2GB了啊结果CONFIG GET maxmemory显示0再一看改的文件跟进程加载的文件压根不是同一个路径。提示排查配置问题时第一步永远是CONFIG GET查看进程内的真实值第二步才是打开配置文件对比不要跳步。2. 内存管理配置maxmemory和淘汰策略决定Redis的下限2.1 maxmemory用默认值等于裸奔Redis在64位系统上maxmemory的默认值是0意思是不限制内存使用。这个默认值设计的初衷是保证Redis能存尽量多的数据但放到生产环境就是一个定时炸弹。Redis是纯内存数据库数据全在内存里如果不设置上限写入量上来之后内存会被吃满操作系统开始使用Swap性能急剧下降甚至触发OOM Killer直接把Redis进程杀掉。更麻烦的是如果部署在同一台机器上的还有别的进程Redis会把整台机器的内存都吃干。设置maxmemory之前先要算清楚机器内存怎么分配。假设机器内存16GBRedis数据占10GBRDB持久化或者AOF重写时会有子进程利用Copy-On-Write机制可能额外占用数据量一定比例的内存通常建议预留数据量的20%到30%。再加上操作系统自身的开销比较稳妥的做法是maxmemory设为物理内存的60%到70%比如16GB机器设maxmemory 10gb。内存压力可以这样检查redis-cli INFO memory重点关注used_memory、used_memory_rss和mem_fragmentation_ratio。used_memory是Redis实际使用的内存used_memory_rss是操作系统视角下进程占用的内存。如果mem_fragmentation_ratio大于1.5说明内存碎片率偏高考虑重启或者开启activedefrag yes。2.2 maxmemory-policy六种策略怎么选内存达到maxmemory之后Redis会根据maxmemory-policy决定怎么处理新写入。这个参数特别重要默认值是noeviction意思是不淘汰任何数据新写入直接报错。对于缓存场景来说默认策略几乎是错误选项缓存不淘汰数据反而让业务写入全部失败。六个策略的适用场景我用实际经验总结如下策略淘汰范围适用场景风险点noeviction不淘汰持久化存储语义的少量数据写满后写入失败allkeys-lru所有key纯缓存所有数据都可牺牲未设置过期时间的key也会被淘汰volatile-lru仅设了过期时间的key缓存持久化混合如果没设过期时间的key多可能淘汰不掉导致写入失败allkeys-lfu所有key按访问频率访问热点分明的缓存冷门key会被很快淘汰volatile-lfu设了过期时间的key按访问频率热点数据设了expire访问频率低但重要的key可能被淘汰volatile-random随机淘汰设了过期时间的key对淘汰谁无所谓只求不报错随机性会导致不可预期最常用的是allkeys-lru和volatile-lru。缓存场景直接用allkeys-lru业务数据中只有一部分key适合过期、其余需要长期保留用volatile-lru。这里有个很多人没注意的细节volatile-lru只会淘汰设了TTL的key如果所有key都没设过期时间内存写满后Redis依然会拒绝写入。所以volatile-*系列策略要求业务方规范地设置过期时间。有人会问allkeys-lru是不是会把原本不该淘汰的key淘汰掉会。如果缓存里混着需要长期保存的数据就别用allkeys-lru。我们线上就曾经出现过一个事故用allkeys-lru做缓存但延迟队列的任务key也被缓存进去了队列积压时这些低温key全部被Redis优先淘汰消费者拉不到数据。所以选策略之前先把自己的数据按可牺牲/不可牺牲分个类。2.3 配合内存配置的实用建议第一个建议缓存场景下给key都要设过期时间让volatile-lru有淘汰的对象。第二个建议修改淘汰策略时不用重启Redis运行中直接CONFIG SET maxmemory-policy allkeys-lru临时应急非常方便。第三个建议监控不能只看used_memory还要关注evicted_keys这个指标如果这个数字持续增长说明淘汰事件很多缓存命中率可能受影响。redis-cli INFO stats | grep evicted_keys如果发现evicted_keys飙升可以适当调大maxmemory或者检查业务是否有一次性大量写入的批量任务把缓存打爆了。数据类型的差异也在这里体现同样存储100万条数据如果都是Short String可能只占100MB如果是Hash且field很多占用会远超预期。评估容量时最好按实际的key结构和数据长度做压测不要拍脑袋估算。3. 持久化配置RDB、AOF和混合持久化的场景化选择3.1 RDBsave参数不是写得越勤越好RDB是Redis默认开启的持久化方式通过快照的形式把内存数据写到磁盘。redis.conf中默认有三条触发规则save 3600 1 save 300 100 save 60 10000意思分别是3600秒内至少有1个key变化就做一次快照300秒内至少有100个key变化就做一次快照60秒内至少有10000个key变化就做一次快照。这三个条件是或的关系谁先满足谁触发。这里的核心思路是变化越频繁快照间隔越短在数据安全性和磁盘IO之间取平衡。但RDB有一个天然缺陷每次快照之间的数据如果丢了是没法恢复的。假设save 3600 1上一小时做了快照这一个小时写入了大量数据Redis突然宕机这一个小时的数据就全没了。所以RDB适合对数据丢失不敏感的场景比如纯缓存或者允许从上游重新拉取数据的场景。save参数不要调得太激进。比如你改成save 60 1看起来数据更安全了但每60秒就fork一个子进程做全量快照大数据量下磁盘IO和内存都会突然飙高。我一个项目就遇到过key有二三十GBsave 300 100本来好好的非要改成save 60 1结果每60秒一次全量快照磁盘被打满主从复制也出现延迟。后来改回默认值才稳定。3.2 AOFappendfsync三种模式如何取舍AOF是追加写日志记录每次写命令恢复时回放日志。它的可靠性取决于appendfsync策略有三种选择参数值行为可靠性性能损耗always每个写命令都fsync到磁盘最高最多丢一个命令最大吞吐量明显下降everysec每秒fsync一次中高最多丢1秒数据小推荐no由操作系统决定何时刷盘最低可能丢较多数据最小绝大多数生产环境选everysec就够了Redis官方文档也推荐这个值。always看起来很安全但实测下吞吐量会下降一个量级尤其是写并发高的场景基本不推荐。no的性能和风险差距都不大也不建议因为崩溃时丢失的数据量不可控。开启AOF的方式是在配置文件里appendonly yes appendfilename appendonly.aof appendfsync everysec这里有个常见的疑问appendonly no时Redis还会生成RDB文件但数据持久化只靠RDB一旦appendonly yesRedis重启时会优先加载AOF文件来恢复数据AOF文件不存在时才加载RDB。3.3 混合持久化和AOF重写条件Redis 4.0之后引入了混合持久化配置文件对应参数是aof-use-rdb-preamble yes。开启后AOF文件的前半部分是RDB格式的二进制快照后半部分是增量命令日志。这样做的收益是重启恢复速度比纯AOF快得多因为直接加载RDB快照再回放少量增量命令即可同时仍然保留AOF的数据安全性。建议新项目全部开启老项目升级时也可以打开。AOF文件会持续增长Redis有自己的重写机制配置文件里控制的是auto-aof-rewrite-percentage 100 auto-aof-rewrite-min-size 64mb含义是当AOF文件体积比上一次重写后的体积增长了100%并且当前文件超过64MB才触发一次自动重写。重写会fork子进程生成一个新的精简AOF文件。如果磁盘空间紧张可以把min-size调小、percentage调低但重写期间IO会有短暂波动这个要根据业务低峰期来权衡。AOF文件如果因为异常崩溃出现半截写入Redis默认会尝试截断尾部不完整的命令并启动。这个行为由aof-load-truncated yes控制保持默认即可。如果Redis启动不了报Bad file format之类的错误先备份原AOF文件再用redis-check-aof --fix修复不要直接删文件能救一点是一点。4. 网络与安全配置bind、protected-mode、requirepass的黄金三角4.1 bind和protected-mode它们究竟在防什么bind和protected-mode这两个参数配合使用决定了谁能连上你的Redis。默认配置是bind 127.0.0.1 -::1 protected-mode yes意思很明确只允许本机的回环地址连接。但很多人拿到Redis第一步就改成bind 0.0.0.0让所有网卡都能访问然后又不设置密码这就等于把Redis裸奔在公网上。Redis本身没有设计鉴权加密层2.8版本之后才有了requirepass但默认是关闭的。protected-mode yes的作用是这样的当没有显式配置bind、也没有设置requirepass时Redis只接受回环地址连接如果检测到你显式配置了bind某个IP就不再保护所有来源都能访问。也就是说你一旦把bind改成0.0.0.0等于告诉Redis我允许所有网卡监听外部连接此时如果没有密码公网扫描到6379端口就能直接登录操作数据。我在安全排查时看到太多这样的案例bind 0.0.0.0加protected-mode yes加无密码Redis被入侵后被人写入SSH公钥或挖矿脚本。安全的做法是明确Redis只对哪些内网IP提供服务然后bind 192.168.1.100 127.0.0.1 protected-mode yes requirepass 你的强密码如果Redis只给本机应用服务最稳妥的配置就是保持bind 127.0.0.1不变不要碰0.0.0.0。4.2 requirepass设密码容易但别用命令行传requirepass是Redis实例级别的访问密码。配置方式requirepass YourStrongPass配置之后客户端连接时要用AUTH YourStrongPass认证否则Redis返回NOAUTH Authentication required。很多人为了方便会用redis-cli -a YourStrongPass来连接但这有个风险命令行的-a参数会被进程列表记录下来任何人都能看到密码。更安全的方式是环境变量REDISCLI_AUTH或者在交互模式下先连接再AUTH。高版本的Redis还有ACL机制可以为不同用户分配不同权限和可访问的key范围。如果团队里有多个人、多个应用共用一套Redis建议用ACL代替一把梭的requirepass控制粒度更细。4.3 Docker部署下的网络配置误区Docker跑Redis踩坑频率最高的就是端口映射和bind冲突。假如你在宿主机上执行docker run -p 6379:6379 redis宿主机外部连接6379时会转发到容器内的6379端口。但容器里Redis默认bind 127.0.0.1这表示它只监听容器内部的回环地址宿主机访问过来时数据包到达的是容器的eth0网卡连接会被拒绝。所以Docker部署时必须显式设置bind 0.0.0.0 protected-mode no requirepass 强密码这里注意Docker的端口映射不是Redis进程主动发起的连接它是网络层的转发所以bind 127.0.0.1会把所有映射过来的请求拒之门外。安全上Docker容器内的Redis本来就不该让公网直连正确做法是用Docker内部网络只让需要访问Redis的容器通过服务名来连接宿主机对外不暴露6379端口。如果你用docker run时加了-v /path/redis.conf:/etc/redis/redis.conf还要确认启动命令是通过redis-server /etc/redis/redis.conf加载的否则挂载进去的文件也不会被读取。很多人挂载了配置文件但Redis启动时压根没指定路径导致怎么改都不生效这个问题我在线下帮人排查过很多次。5. 日志、慢查询与动态调优配置出问题后你靠什么定位5.1 日志级别和日志文件别等出事才想起看日志Redis日志默认输出到标准输出如果daemonize yes后台运行且没有配置logfile日志会被丢弃。正确的配置是daemonize yes pidfile /var/run/redis.pid logfile /var/log/redis/redis.log loglevel noticeloglevel有四种debug、verbose、notice、warning。默认notice会记录启动、关闭、持久化、主从切换等关键事件。排查问题时临时切到debug可以看到每个命令的执行细节代价是日志量极大用完记得改回来。日志里常出现的几个关键信息要能看懂Saving the final RDB snapshot说明RDB快照执行了Background AOF rewrite finished successfully说明AOF重写完成Cant save in background: fork: Cannot allocate memory说明fork子进程时内存不足多半是maxmemory和系统内存设置有问题Accepted 127.0.0.1:xxxx表示新连接接入如果出现大量陌生IP的连接记录就要警惕是不是被扫了。5.2 慢查询日志定位线上延迟的第一把尺子慢查询日志是Redis排查性能问题最高效的入口。配置文件里slowlog-log-slower-than 10000 slowlog-max-len 128slowlog-log-slower-than单位是微秒10000微秒等于10毫秒。意思是执行时间超过10毫秒的命令会记录到慢查询日志。slowlog-max-len是日志最大条数Redis的慢查询日志存在内存里不会写到磁盘重启就清空。查看方式redis-cli SLOWLOG GET 10在实际环境里如果发现大量慢查询是KEYS命令那基本可以断定是业务方误用了KEYS做模糊匹配。KEYS在key数量大时会阻塞Redis单线程阻塞期间所有命令都排队整个实例的延迟指标都会飙升。正确的替代方案是用SCAN命令分批遍历。如果你的慢查询里出现DEL删除大key也很危险Redis删除一个包含几百万元素的集合时会阻塞服务可以考虑用UNLINK异步删除。5.3 CONFIG SET与CONFIG REWRITE运行时改配置的正确姿势Redis最方便的一点是几乎所有的配置都能在运行期动态修改不需要重启。CONFIG SET改的是内存里的值但不会自动写回配置文件。为了让修改在重启后依然生效需要执行redis-cli CONFIG SET maxmemory 2gb redis-cli CONFIG REWRITECONFIG REWRITE会把当前内存中生效的配置跟配置文件比对并自动重写配置文件。这个命令的约束是如果配置文件里某些参数和内存值不一致REWRITE会把内存值写进去。所以调整配置的顺序应该是先CONFIG SET让线上立刻生效观察一段时间确认没问题再CONFIG REWRITE持久化到磁盘。如果先改文件再重启也行但要承担一个风险如果新配置有问题重启后服务可能直接起不来而且在业务高峰期重启Redis是尽量避免的事。注意CONFIG REWRITE要求原配置文件对Redis进程有写权限如果配置文件是root所有且Redis以普通用户运行REWRITE会报错先调整文件权限再执行。6. 一份可以直接抄的redis.conf核心配置模板下面这份配置是我在多个项目中沉淀下来的基础模板不是官方默认值也不是为了跑Demo用的而是综合了安全、性能、可维护性的通用配置。你可以根据实际机器配置调整参数但结构可以直接用。# 网络与访问控制 bind 127.0.0.1 protected-mode yes port 6379 timeout 0 tcp-keepalive 300 # 访问认证强烈建议开启 requirepass your-strong-password # 守护进程与 PID daemonize yes pidfile /var/run/redis.pid supervised no # 日志 loglevel notice logfile /var/log/redis/redis.log # 内存上限与淘汰策略 maxmemory 10gb maxmemory-policy allkeys-lru maxmemory-samples 5 # RDB 持久化 save 3600 1 save 300 100 save 60 10000 dbfilename dump.rdb dir /var/lib/redis # AOF 持久化与混合持久化 appendonly yes appendfilename appendonly.aof appendfsync everysec aof-use-rdb-preamble yes auto-aof-rewrite-percentage 100 auto-aof-rewrite-min-size 64mb aof-load-truncated yes # 慢查询 slowlog-log-slower-than 10000 slowlog-max-len 128 # 客户端连接数 maxclients 10000这份模板有几个细节需要说明一下timeout 0表示连接空闲多久后关闭0表示不关闭。如果业务方经常有闲置连接占着不释放可以设置timeout 300让空闲5分钟以上的连接被Redis切断。但要注意如果客户端有连接池且没做好重连机制服务端主动断开会造成客户端一堆异常需要先确认客户端具备自动重连能力。maxmemory-samples 5是LRU/LFU算法的采样数。Redis的LRU不是全量精确计算而是随机采几个key来决定淘汰谁采样数越大计算结果越精确但也更消耗CPU。默认5是平衡点。maxclients 10000要根据ulimit -n来定如果系统文件描述符上限只有1024Redis最多连接数也到不了10000。修改连接数前先执行ulimit -n查看上限。appendonly yes和混合持久化同时开启后AOF文件会比纯日志模式更小恢复更快。如果redis版本低于4.0aof-use-rdb-preamble这个参数可能不存在需要升级。这份模板我并不是建议你直接照抄所有值而是参考结构和考量方式。比如maxmemory设多少取决于你的机器内存和业务数据量比如缓存和持久化混合业务maxmemory-policy要改成volatile-lru。配置文件的调优本质是Trade-off的决策不存在放之四海皆准的值。我看过很多团队在Redis配置文件上走过同一条弯路默认配置用起来很爽出问题之后一头雾水。实际上redis.conf的每个配置项都可以在官方文档和CONFIG GET的帮助下搞明白真正难的是知道自己业务需要什么数据能不能丢、内存上限多少、哪些客户端需要访问、发生故障时你希望Redis怎么表现。把这些业务决策理清了配置文件怎么填就是顺理成章的事。所以我最后想说的是别把配置文件当成一个改了不报错就行的东西它是你Redis实例的体检报告和遗嘱——现在不重视出问题时它决定的不是Redis的命运而是你的业务。
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门