
服务器这东西一旦上了生产环境你总会遇到一个绕不开的名字Redis。不管是扛高并发读多写少的缓存、做分布式锁、还是临时计数器和排行榜Redis几乎是后端服务器里最常见的“基础设施”之一。这篇博文我就结合自己多年摆弄服务器和Redis的经验把从安装配置、数据类型、缓存治理、分布式锁到主从集群和常见报错排查的思路完整捋一遍。既给新手一份可以照着做的实操清单也希望能给已经上路的朋友一点排查问题的方向。我默认你手头有一台能登录的Linux服务器或者一台能开Docker的机器。东西不复杂但坑不少咱们一个坑一个坑地过。1. 服务器架构里的Redis到底在扛什么1.1 它解决了服务器的三个核心痛点很多初学者容易把Redis理解成“一个能存数据的缓存”这话没错但太浅。站在服务器的角度Redis真正解决的是三个问题第一是数据库压力。你的业务一旦有大量读请求全部打到MySQL或者PostgreSQL上数据库连接池和磁盘IO根本扛不住尤其是类似热点新闻、商品详情这种读多写少的场景。Redis把热数据放在内存里读请求直接命中内存数据库QPS压力能下降一个数量级。第二是接口响应时间。磁盘随机读取和网络来回的延迟通常在几十毫秒甚至上百毫秒而在内网环境下Redis的读写往往是亚毫秒级别。这意味着你如果之前查一次详情要80ms现在Redis命中只要1ms用户体验的提升是非常直观的。第三是分布式环境下的协同。单机程序用锁很简单但上了服务器集群多台机器要抢同一个资源就需要一个大家都能访问的协调者。Redis的原生SET NX、INCR、发布订阅等能力让它很适合做分布式锁、分布式计数器、接口幂等控制这类“中间件”角色。1.2 为什么选Redis而不是别的我碰到过很多人在选型时纠结既然服务器内存有限为什么不直接用本地缓存用Memcached不行吗甚至直接放数据库不行吗我把选型逻辑拆开讲。本地缓存比如Guava Cache、Caffeine速度确实快因为根本不走网络但问题是每台服务器各存一份数据不一致而且没法做跨实例的失效通知。Memcached也能做分布式缓存但数据结构只有字符串一种类型太简单你想做个排行榜都费劲。数据库虽然安稳但扛不住高频读。Redis强在两点一是数据的结构丰富String、Hash、List、Set、ZSet五大数据类型基本覆盖了缓存、计数、队列、去重、排行榜等常见场景二是生态成熟客户端多、运维工具多、主从和集群方案现成从单机到集群的迁移路径很平滑。注意Redis虽然带个“数据库”的名字但它不是万能存储。没有事务回滚、没有强一致的多表关联把它当MySQL用的大坑后面我会细说。1.3 红线场景什么情况下别硬上Redis说了这么多优点也得讲讲哪些场景不要用Redis这是我踩过坑之后才明白的。第一核心业务数据不要只放Redis。比如订单金额、库存扣减最终记录你可以用Redis做前置校验和防抖但最终必须以数据库落盘为准。因为Redis的持久化机制RDB和AOF在生产实践中可能会丢极少量的数据不适合当唯一存储。第二别拿Redis当重型消息队列。它虽然有List、Stream能实现简单的任务队列但缺少消息确认、重试、死信这些成熟消息队列该有的能力。如果业务量上来你会陷入自己造轮子的泥潭。第三不要存大字符串和大集合。Redis是单线程处理命令的一个几千KB的value写一次和读一次都要占据事件循环很久。如果某个key特别大它可能会把整个Redis服务拖慢这就是后面要聊的“大key”问题。2. 安装部署换一台新服务器我会怎么装2.1 三种安装方式的取舍在服务器上装Redis主流有三种方式包管理器安装、源码编译安装、Docker容器安装。我根据不同环境切换着用各有取舍。包管理器安装apt install redis-server 或 yum install redis适合快速搭一套测试环境。优点是快缺点是版本往往偏旧而且配置文件位置和默认参数因发行版而异。源码编译安装从Redis官网下载稳定版源码make编译。优点是版本最新、参数可控。缺点是你要自己处理依赖和systemd服务文件。Docker安装docker run redis一条命令搞定而且主从集群用compose编排非常方便。前提是你已经接受容器化运维。我自己在生产环境倾向于用官方源码编译指定版本然后配合systemd管理。原因很简单生产环境不能接受莫名其妙的版本差异和默认配置陷阱你用什么参数启动、装在哪心里要门清。测试环境则直接Docker坏了就删重建也快。2.2 配置文件里这七个参数必须理解Redis默认配置可以直接跑但直接跑的结果就是裸奔。装好后第一件事打开redis.conf逐个调整下面这些参数。# 绑定地址0.0.0.0表示所有网卡可访问建议按实际环境限制 bind 0.0.0.0 # 保护模式不配置密码时必须开启 protected-mode yes # 端口 port 6379 # 后台运行如果用systemd管理则建议设为no由systemd托管 daemonize no # 访问密码生产环境必须设置 requirepass 你的强密码 # 最大内存根据服务器内存和业务合理分配 maxmemory 2gb # 内存淘汰策略见下方说明 maxmemory-policy allkeys-lru # 开启AOF持久化 appendonly yes appendfsync everysec这里最容易忽视的是maxmemory和maxmemory-policy的组合。你如果不设上限Redis会一直吃内存直到把服务器内存吃光触发系统OOM Killer到时候整个服务直接挂。设了上限之后还需要回答“内存满了怎么办”这个由淘汰策略决定。volatile-lru只对设置了过期时间的key做LRU淘汰适合缓存场景。allkeys-lru对所有key做LRU淘汰适合你能接受任意key消失的场景。noeviction内存满直接报错不写适合不能丢数据的场景。我用得最多的是 allkeys-lru毕竟Redis主要做缓存冷了的数据应该被淘汰。注意maxmemory不要设置为服务器物理内存的100%要留出给操作系统、fork子进程以及AOF重写时的内存开销。比如一台16G内存的服务器我一般分给Redis 10G剩下的给系统和业务本身。2.3 用systemd把Redis管起来很多从源码编译安装的朋友都会卡在这一步redis-server /path/to/redis.conf 能启动但重启服务器后Redis没了也没法用systemctl status查看状态。解决方法是写一个标准的systemd unit文件。[Unit] DescriptionRedis Server Afternetwork.target [Service] Typesimple Userredis Groupredis ExecStart/usr/local/bin/redis-server /etc/redis/redis.conf ExecReload/bin/kill -USR2 $MAINPID Restarton-failure RestartSec5s LimitNOFILE65535 [Install] WantedBymulti-user.target把这个文件放到 /etc/systemd/system/redis.service然后执行systemctl daemon-reload systemctl enable redis systemctl start redis systemctl status redis这里有个服务器运维中特别容易踩的细节如果Redis进程是root启动的出于安全考虑我强烈建议单独建一个redis用户来运行。你可以用 useradd -r -s /sbin/nologin redis 创建然后把 /var/lib/redis 和 /etc/redis 的属主改成 redis。这样做的好处是即使Redis被利用攻击者拿到的也不是root权限服务器不会被一锅端。2.4 装完先跑一次体检装好之后先别急着接业务在命令行敲几个命令确认状态。# 登录并验证密码 redis-cli -a 你的密码 # 看基本信息 info server # 看内存情况 info memory # 看客户端连接数 info clients # 跑一遍读写验证 set hello world get hello这些命令不是让你看一眼就算了。info output里的 used_memory、connected_clients、uptime_in_days 这些指标建议心里有个数后续监控告警都是从这里取值。如果配置了密码redis-cli 会提示 warning加 --no-auth-warning 可以关掉提示脚本里尤其需要这个参数否则 cron 日志会被刷屏。3. 数据类型实战别把Redis用成高级Map3.1 五大数据类型和它们的战场很多新手觉得Redis就是 set/get 字符串完全忽略另外四种类型。等你真正做排行榜、做关注列表、做去重的时候就会知道用错数据类型的代价有多大。类型底层实现最适合的场景典型命令String动态字符串缓存、计数、验证码、分布式锁SET、GET、INCR、SETNXHash哈希表对象存储如用户信息、商品详情HSET、HGETALL、HINCRBYList双向链表消息队列、时间线、最近列表LPUSH、RPOP、LRANGESet哈希表/整数集合去重、共同好友、抽奖SADD、SISMEMBER、SINTERZSet跳表哈希表排行榜、延迟队列、限流窗口ZADD、ZRANGE、ZSCORE举个例子。你要存用户信息假设用户有昵称、头像、年龄三个字段。如果你用String就会搞出 user:1001:name、user:1001:avatar、user:1001:age 三个key浪费内存还难管理。用Hash的话一条 HSET user:1001 name 张三 avatar /a.jpg age 25 就搞定了后续只查某个字段还能节省带宽命令也会优雅很多。再比如排行榜如果用数据库做 ORDER BY 然后再算出名次数据量一大准卡。而ZSet天生就是干这个的score就是分数ZREVRANGE 取Top10是毫秒级操作。3.2 key设计和序列化的隐形坑我接手过不少服务器Redis里存了一堆乱七八糟的key最大的问题不是数据乱了而是你根本不知道这个key是干什么的。服务器出了问题想排查连个线索都没有。好的key命名一定要有规则推荐这么设计业务名:对象名:唯一标识。比如 order:detail:20240101。冒号分割在Redis Desktop Manager里会天然形成目录结构一眼就知道归属。千万别用没有规则的随机串也别用下划线糊成一大段。再说序列化。这也是热词里很多人踩过的“redis序列化”问题。Java业务里最常见、最糟糕的做法是直接把对象用JDK默认序列化塞进Redis。问题有三个一是体积大JDK序列化出来的字节数组比JSON大好几倍浪费内存和带宽二是二进制不可读你在命令行里 get key 看到一堆乱码根本没法排查三是协议耦合万一以后换语言Java序列化的数据其他语言根本读不了。我的实践是数据入库Redis之前统一用JSON序列化特别是Jackson或Fastjson节省内存且可读性强。如果追求更极致的空间可以考虑protobuf这类但牺牲可读性换空间调试成本会增加看你的业务取舍。3.3 大key和热key服务器上最容易翻车的两个问题先说“大key”。我定义的大key是单个key的value超过几百KB或者是Hash/Set/ZSet里的元素数量超过一万。危害在于读写大key会产生很大的网络包占用带宽删除大key时会阻塞Redis主线程导致服务在几百毫秒甚至几秒内无法处理其他命令。排查大key的方法很简单Redis自带了--bigkeys扫描参数redis-cli --bigkeys -a 你的密码 --no-auth-warning它会扫描整个实例输出每种数据类型里最大的几个key。扫出来之后如果是Hash/Set这种大集合用 HSCAN 分批迭代然后用 HDEL 或 SREM 分批删千万不要直接 DEL否则就是一次线上事故。字符串类型的大value拆分成多个小key或者用压缩算法先把内容压一压。再说“热key”。如果某个key被超高并发读取比如双十一的秒杀库存Redis本身单线程处理虽然快但网络和CPU也会达到瓶颈。简单的雪崩应对方案是给key随机加后缀比如把 hotkey 变成 hotkey1 到 hotkey10这样流量就分散到多个key上了。更彻底的办法是在业务机器上加一层本地缓存或者用Redis Cluster把热点分散到不同节点。3.4 缓存治理TTL、淘汰策略、定期扫描热词里有“redis缓存治理”这是个很实际的运维主题。缓存治理的核心就三件事设TTL、定策略、定期盘。我在实际中遇到过最经典的事故一个同事插入Redis的缓存key全部没有设置过期时间三个月后服务器的内存被吃满OOM直接把Redis进程杀了。治理方案分三步代码review保证每条缓存业务都设置TTL通常是几分钟到一小时的业务时延。配置 maxmemory-policy防止内存满时Redis写不进新的key。每周在低峰期跑一遍 redis-cli --scan --pattern 业务前缀* 检查key数量增长或者用 info keyspace 看有没有缓存key只增不减。这里提一下Redis的过期删除策略它其实不是定时把所有过期key瞬间删掉而是懒性删除配合周期删除。所谓懒性删除就是每次get时如果发现key过期就删除再返回空周期删除就是Redis每隔一段时间主动扫一部分过期key。理解这个机制很重要如果大量key设置了同一秒过期那这一秒Redis会疯狂执行删除操作可能造成瞬间卡顿。所以缓存TTL我一般会加一个随机扰动比如基础时间600秒再随机加0到60秒就是为了避免这种“缓存雪崩”的变体。4. 生产级玩法分布式锁和缓存治理细节4.1 分布式锁的正确姿势别再踩两个坑热词里“redis分布式锁”赫然在列这也确实是服务器集群场景下最常被问到的Redis用法。但网上很多文章的写法过时了甚至有bug。我先演示错误写法。第一个坑是两步操作先用 SETNX 命令抢锁成功后再 EXPIRE 设过期时间。问题在于如果 SETNX 之后、EXPIRE 之前进程崩溃了锁永远不会过期其他请求就永远拿不到锁。第二个坑是只判断 SETNX 返回值忘记在释放锁时校验持有者。假设A拿到锁执行时间超过了锁的过期时间锁已经自动失效B拿到锁开始执行。这时候A执行完直接 DEL 把B的锁删了就出大事了。正确的写法是Redis官方推荐的原子操作# 获取锁value用唯一标识比如UUID SET lock:order:1001 uuid_value NX EX 30 # 释放锁先校验是持有者再删除 if redis.call(get, KEYS[1]) ARGV[1] then return redis.call(del, KEYS[1]) else return 0 end上面用Lua脚本保证“判断删除”的原子性。如果你用的是Java的Redisson客户端它已经把看门狗机制封装好了获取锁时默认30秒过期但是只要业务一直执行后台线程会一直给锁续期直到业务执行完释放锁。这比手动设一个死长的过期时间要安全得多。至于RedLock那种多实例加锁方案我个人的看法是绝大多数业务根本用不到。实现复杂而且学术界对它也有争议。只要你的Redis不是单点比如主从加哨兵普通的SET NX EX加Redisson就足够应对绝大部分场景了。4.2 缓存三大坑穿透、击穿、雪崩这三个词是所有面试题和真实事故里的常客也是“Redis做中间件”绕不开的话题。缓存穿透请求的key在缓存里不存在数据库里也不存在于是每次请求都直接打到数据库。攻击者可以构造一堆不存在的ID来打库。解决思路有三个一是缓存空值并设置短TTL二是用布隆过滤器先把不存在的key过滤掉三是对无法修正的恶意请求做接口限流。缓存击穿某个热点key在缓存过期的那一瞬间大量并发请求同时查询数据库。解决思路一是热点key不设TTL二是用互斥锁让只有一个请求去刷新缓存其他请求先等一下再读三是上面说的逻辑过期方案。缓存雪崩大量key同一时间过期导致一大批请求打到数据库。解决思路TTL加随机扰动让过期时间分散开多级缓存本地加Redis两层提前压测评估数据库能否扛住冲击。这里给一个快速对比表问题原因核心解法穿透查不存在的数据缓存空值、布隆过滤器、接口限流击穿热点key过期并发不设TTL、互斥锁、逻辑过期雪崩大量key同时过期TTL随机化、多级缓存、服务降级4.3 缓存与数据库的一致性怎么保证这个问题的标准答案是大多数业务场景只需要做到最终一致性别追求强一致否则性能和复杂度都不划算。我实践下来最稳妥的套路是“Cache Aside”旁路缓存加“延迟双删”。流程是读请求先读缓存没命中就读数据库然后回填缓存写请求先更新数据库然后删除缓存。为什么要删除缓存而不是更新缓存因为更新缓存存在并发问题两个请求同时写数据库后写的数据库是最终值但如果先更新的线程后完成缓存更新缓存里就存了一个旧值。删除缓存就简单了下次读的时候会从数据库拿最新数据回填。“延迟双删”处理的是更极端的并发场景线程A更新数据库删缓存线程B这时读了一个旧值回填了缓存A等了一小段时间后再次删除缓存。这个延迟一般几百毫秒主要看业务容忍度。强一致性场景怎么办我的建议是别缓存。库存、余额这种涉及钱的强一致数据老老实实走数据库事务Redis顶多做前置的预检和限流。5. 高可用与集群单机Redis注定撑不了太久5.1 用Docker快速搭一套主从复制单机Redis一旦服务器宕机整个业务缓存全部丢失。生产环境至少要做主从。主从复制的作用有两个一是数据冗余二是主节点挂了可以从节点顶上实现读写分离。热词里“docker安装redis主从”是很多人搜过的确实用Compose搭建最省事。我写一个可以直接用的docker-compose.ymlversion: 3 services: redis-master: image: redis:7.0 container_name: redis-master command: redis-server --requirepass masterpass --appendonly yes ports: - 6379:6379 volumes: - ./master-data:/data redis-slave: image: redis:7.0 container_name: redis-slave command: redis-server --slaveof redis-master 6379 --masterauth masterpass --requirepass slavepass --appendonly yes depends_on: - redis-master ports: - 6380:6379 volumes: - ./slave-data:/data执行 docker compose up -d然后进从节点执行 INFO replication 看 role 是否为 slave。主从复制原理不复杂主节点启动一个后台进程把当前数据生成RDB快照发给从节点从节点加载完快照后主节点再把后续的写命令增量传给从节点。这个流程是异步的所以主从之间天然有极小的数据延迟。注意从节点默认是只读的你在从节点上执行 SET 会报错。这是保护机制防止主从数据不一致。想开启写操作就得改 replica-read-only no但我劝你别这么干会让数据彻底失控。5.2 哨兵自动故障切换的守护者主从解决了数据备份但主节点宕机时业务怎么自动把写请求切到从节点这就需要Sentinel哨兵出场。哨兵本身也是一个Redis进程它的职责是监控主从节点发现主节点挂了之后在从节点里选举一个提升为新主节点并把消息推给客户端。部署哨兵最少三个节点这是个典型问题。三个节点互相投票才能避免“脑裂”——也就是两个节点各自认为自己是主节点从而产生数据分裂。哨兵配置文件里关键参数是sentinel monitor mymaster 127.0.0.1 6379 2 sentinel auth-pass mymaster masterpass sentinel down-after-milliseconds mymaster 5000 sentinel failover-timeout mymaster 10000其中数字2表示至少需要2个哨兵同意才能判定主节点客观下线。哨兵模式整体的复杂点在于客户端接入客户端不能直接写死主节点IP而要通过哨兵接口来获取当前主节点地址。如果你的客户端不原生支持哨兵那就得在客户端代码里加一层地址发现逻辑。这也是我建议中小业务直接上云托管Redis的原因之一省掉这些运维复杂度。5.3 集群真正解决容量和写入瓶颈主从加哨兵解决了高可用但没有解决容量上限。单台服务器内存总是有限的假设业务数据量超过单台机器的内存就要考虑Redis Cluster。Redis Cluster采用分片策略整个集群有16384个哈希槽每个key通过CRC16算法算出一个哈希值映射到其中某个槽位每个主节点负责一部分槽位。比如三主三从的集群三个主节点各负责大约5461个槽位。这样数据分散到了多台服务器自然突破了单机内存限制。部署集群用官方工具最方便。拿到源码后redis-cli --cluster create \ 192.168.1.10:7000 192.168.1.11:7000 192.168.1.12:7000 \ 192.168.1.13:7001 192.168.1.14:7001 192.168.1.15:7001 \ --cluster-replicas 1后面的 --cluster-replicas 1 表示给每个主节点配一个从节点。集群模式下有一个约束要特别记住单个命令涉及多个key时如果key不在同一个哈希槽里就会报错。所以设计key时要有意识地让相关数据挂在相同前缀比如 user:1001:info 和 user:1001:score 会落在同一个槽位而 user:1001 和 order:1001 大概率不在一个槽。5.4 监控和日志不能省生产环境的Redis我每天晚上会例行看几样东西连接数、内存使用率、慢查询日志、持久化失败告警。连接数突然飙高大概率是你的应用连接池配置有问题没释放连接。内存涨得快要么是缓存没有TTL要么是某个业务把大对象塞进去了。慢查询的命令用下面两个方式查# 查看当前慢查询阈值单位微秒默认10000微秒即10ms CONFIG GET slowlog-log-slower-than # 查看最近10条慢命令 SLOWLOG GET 10如果发现慢命令频繁出现且都是一些 HGETALL、LRANGE 大范围命令那就该回去查大key问题了。日志也是一样。Redis默认日志不太多但出问题时日志会给出明显提示比如主从断连、RDB持久化失败、OOM内存超过限制等。日志级别建议设置为 notice生产环境别开debug否则日志量能把你磁盘写满。日志文件位置一般在 /var/log/redis/redis.log自己部署的话在redis.conf里用 logfile 指定。服务器虚拟化环境还有个值得注意的点如果Redis运行在虚拟机里时钟跳跃可能导致过期时间计算异常进而影响缓存TTL和分布式锁的过期策略。有条件的话用同步时间服务保证时钟一致性或者直接用容器化部署让时钟问题暴露得更直观、更好排查。6. 连接工具和客户端选择运维效率的关键6.1 从Redis Desktop Manager到Another Redis Desktop Manager对于不习惯命令行操作的朋友可视化工具几乎是必需品。老牌的Redis Desktop ManagerRDM相信大家都听过界面成熟但它早期版本对免费用户限制严格且部分版本需要付费授权。热词里“redis desktop manager”和“another redis desktop manager”同时出现说明大家确实在找替代品。我目前主力用的是Another Redis Desktop Manager简称ARDM。它免费开源跨平台功能上甚至比老牌RDM更顺手。几个我常用的功能支持Redis Cluster和哨兵模式的连接管理。支持SSH隧道连接服务器Redis不暴露公网端口时通过跳板机连过去很方便。支持命令行面板可以直接敲redis命令调试Lua脚本。可以按key前缀过滤扫描大key在GUI里能一眼看出来。在配置连接时如果你用密码认证填密码就行。但如果Redis部署在Docker或者K8s里端口映射和网络模式需要注意GUI连不上很多时候不是密码问题而是bind地址和容器端口映射没弄对。工具免费集群支持跨平台我的评价Redis Desktop Manager部分限制好是老牌但付费限制烦人Another Redis Desktop Manager是好是首选免费且功能强命令行 redis-cli是需插件是必会服务器上最可靠6.2 命令行下的几个高能技巧就算有了GUI我也建议任何时候都掌握几个比较好用的命令行技巧。特别是服务器上排查问题时可视化工具不一定装得上命令行是最后一道防线。# 实时查看命令统计观察哪些命令被大量执行 redis-cli --stat # 重新启动就报错Address already in use # 大概率是旧的redis进程没退出 ss -lntp | grep 6379 ps -ef | grep redis # 批量删除某个前缀的所有key用SCAN而不是KEYS redis-cli --scan --pattern user:* | xargs -r -n 100 redis-cli DEL务必记住生产环境别用 KEYS *。这个命令会遍历所有key数据量大时直接阻塞Redis主线程几秒钟线上立马连锁反应。想遍历就用SCAN它是游标式分批返回不阻塞。7. 常见问题与Redis面试真题实战7.1 redis command timed out怎么排查热词里有一条非常具体“redis command timed out; nested exception is io.lettuce.core.rediscommandtimeout”。这是Java项目里使用Spring Data Redis底层是Lettuce客户端时非常经典的报错。字面意思就是Redis命令执行超时了。常见的诱因有这么几个按排查优先级排序大key阻塞Redis主线程在做一个耗时操作比如删一个大key或者执行了一次全量KEYS扫描所有命令都排队超时。网络问题Redis部署在另一台服务器服务器之间网络抖动、防火墙限制或者跨机房访问延迟过高。连接池耗尽Lettuce使用共享连接线程一多请求在客户端本地排队也会表现为命令超时。Redis自身负载CPU达到瓶颈文件系统IO有问题AOF每秒钟同步磁盘都可能卡住。排查路径是先看 Redis 服务端慢日志SLOWLOG GET确认是不是有大命令拖慢了服务再看 Redis 的 info clients 和连接数确认连接没有堆积最后 ping 一下确认网络延迟。如果Redis完全正常那就是客户端配置问题Spring里调高 lettuce 的超时配置只能是权宜之计治本还是要扫大key。7.2 从日志和内存里读出问题排查问题的经验告诉我先看日志再看内存别瞎猜。Redis日志里如果出现 Disk is full 或者写AOF失败基本就是磁盘空间干满了。出现 Cannot allocate memory就是服务器内存不足Redis无法分配内存。出现 Misbehaving client可能是客户端发了一堆畸形命令。内存方面info memory有三个关键指标used_memory当前实际占用的内存。used_memory_rssRedis进程占用的物理内存。mem_fragmentation_ratioRSS与used_memory的比值正常在1左右如果超过1.5说明存在内存碎片可以考虑重启或开启自动整理。当 mem_fragmentation_ratio 长期很高时可考虑设置activedefrag yes让Redis在空闲时自动整理碎片。7.3 面试里常问的几个点这么答热词里出现了“redis面试题”也顺便把这部分讲了。我的经验是面试官问Redis主要考察三个方面底层原理、场景应用、踩坑经验。常见问题回答要点Redis为什么快纯内存操作、单线程避免上下文切换和锁竞争、IO多路复用单线程为什么还能扛并发Redis瓶颈不在CPU而在内存和网络单线程简化了线程安全持久化选RDB还是AOFRDB恢复快但可能丢数据AOF数据更安全但文件大恢复慢生产建议两者结合缓存一致性怎么解决Cache Aside 延迟双删最终一致性强一致就不缓存分布式锁怎么做SET NX EX原子操作Lua释放Redisson看门狗续期内存满了会怎样按maxmemory-policy淘汰noeviction会直接写失败主从和集群选哪个数据量大用Cluster只做高可用用主从哨兵面试不是背书关键是能把每个方案背后的为什么讲清楚。比如Redis为什么快往深处说还要提到 Redis 6.0之后支持的IO多线程以及单线程模型下删除大key的代价这一层深度是很多人没准备到的。7.4 扩展思路Redis做中间件还能玩什么除了缓存和锁我在实际项目中还用Redis做过几类“中间件”角色简单分享两个思路。一个是接口幂等用 SETNX 做一个幂等键同一个请求号在几十秒内只能成功一次配合数据库唯一索引做双重保障。另一个是滑动窗口限流用ZSet记录请求时间戳统计固定时间窗口内的请求数超过阈值就拒绝服务。这两个方案在生产中都很实用代码量也不大。我觉得在这些场景里Redis最大的价值不是性能而是原子操作和数据结构本身。它让分布式系统里原本需要靠数据库锁或者分布式事务才能实现的逻辑变得非常简单直接。当你理解了这些再看各种技术文章里“Redis做中间件”的说法就不会觉得是个空泛的概念了。最后说点真心话。Redis这东西表面上看就是 set/get 不到一百条命令但真正用好的关键在于理解它的线程模型和内存特性。我见过太多服务器被几个大key拖垮、被忘了设TTL的缓存吃满内存、被错误分布式锁搞到数据错乱的案例全都是栽在“会命令但不会用”上。希望大家把这一套从装到调、从单机到集群的路子走一遍踩过的坑自然就是你的经验。如果后面有时间我再聊聊Redis 7新增的底层数据结构优化以及多线程IO模式下运维指标的变化这些又是另一个坑位了。