
做后端这几年Redis几乎是无处不在登录态缓存、热点数据加速、分布式锁、限流计数器、排行榜……可以说只要系统做到一定规模就离不开它。很多朋友跑来问我Redis怎么学、怎么用其实官方文档虽然全但过于零散刷面试题又太碎片化。所以我整理了这份“Redis速记”把日常开发中最常打交道的部分——安装、数据类型、序列化、缓存治理、分布式锁、高可用部署——浓缩成一份能直接照着抄的实操笔记。这份内容不追求面面俱到而是以“用得上”为标准覆盖从零安装到生产部署的完整链路。适合三类人看一是准备面试、需要快速过一遍核心知识点的同学二是已经在用Redis、但遇到序列化异常、缓存穿透、锁失效等问题想找答案的后端开发三是准备在云服务器上用Docker搭一套Redis环境的运维新人。1. 装机与起步三种方式搞定Redis环境1.1 Windows本地快速安装Windows下安装Redis现在简单很多不用折腾旧版的GitHub编译包。开源社区维护的tporadowski/redis项目会持续发布Windows原生版本直接下载MSI安装包一路Next就能装完。安装时记得勾选“Add Redis installation folder to PATH”这样后面可以直接在CMD里敲redis-cli。安装完成后把Redis注册成Windows服务redis-server --service-install redis.windows-service.conf --loglevel verbose redis-server --service-start这里有个容易踩的坑Windows版默认配置文件里bind 127.0.0.1和protected-mode yes是同时开启的如果你的本机Redis想被虚拟机里的Docker容器访问光改bind没用还需要把protected-mode关掉或者配置密码否则连接会被拦。不过说句实在话如果你的开发机已经装了Docker Desktop我建议直接用容器跑Redis下文1.3节会细说比起在Windows里安装原生版更省心版本切换也方便。1.2 Linux服务器上的标准安装流程生产环境最常见的是源码编译安装因为可以指定版本、自定义安装路径后续的systemd管理也更顺手wget https://download.redis.io/releases/redis-7.2.4.tar.gz tar xzf redis-7.2.4.tar.gz cd redis-7.2.4 make -j$(nproc) make install PREFIX/usr/local/redis编译之前记得先装好gcc和make否则会卡在编译阶段yum install -y gcc make # CentOS/RHEL apt install -y build-essential # Ubuntu/Debian装完后把配置文件复制到指定目录mkdir -p /etc/redis cp redis.conf /etc/redis/ redis-server /etc/redis/redis.conf --daemonize yes生产环境建议把daemonize改成yes再配好requirepass和bind。但如果是用systemd托管就不要daemonize yes了让Redis以前台方式运行由systemd负责后台化日志也交给journald统一收集排查问题时会方便很多。1.3 Docker Compose一键拉起生产环境用Docker跑Redis是我个人最推荐的方式隔离干净、版本可控、迁移方便。一个最简单的单机命令docker run -d --name redis \ -p 6379:6379 \ -v /data/redis:/data \ -v /etc/redis/redis.conf:/etc/redis/redis.conf \ redis:7.2-alpine \ redis-server /etc/redis/redis.conf但如果是生产环境强烈建议用Docker Compose管理配置把持久化、密码、日志轮转、资源限制一次性写好services: redis: image: redis:7.2-alpine container_name: redis-master restart: always ports: - 6379:6379 command: redis-server /usr/local/etc/redis/redis.conf volumes: - ./redis.conf:/usr/local/etc/redis/redis.conf - ./data:/data environment: - TZAsia/Shanghai sysctls: - net.core.somaxconn1024 ulimits: nofile: soft: 65536 hard: 65536 deploy: resources: limits: memory: 1g这里有几个关键点值得展开说。第一sysctls里的net.core.somaxconn最好调一下Redis在启动时会提示WARNING: The TCP backlog setting of 511 cannot be enforced这就是内核参数限制导致的容器里如果不开privileged默认改不了用sysctls可以悄悄规避。第二ulimits的nofile关系到高并发下的文件描述符上限连接数一大不调这个会报Cant open so many files之类的错误。第三选择alpine镜像体积只有几十MB但如果你要用Redis Module比如RedisBloom、RedisJSON那还是得用官方标准镜像alpine的模块兼容性偶尔会出问题。2. 数据模型五大类型与三个“隐藏技能”2.1 String、Hash、List的实战定位Redis的数据类型是面试高频区也是日常开发最容易用错的地方。很多新人喜欢一刀切全用String实际上不同类型对应截然不同的使用场景。String是最基础的类型适合存简单的键值对——验证码、SESSION、接口返回的JSON快照、计数器。它的底层是SDS简单动态字符串比C语言的原始字符串多了长度记录和预分配机制所以频繁修改也不会频繁重新分配内存。用INCR做秒杀扣库存、用SETNX实现分布式锁都是基于String的操作。但是String有个“隐形”的成本当你把一个Java对象序列化成JSON塞进Redis一次读写就要两次序列化转换如果这个对象的某个字段需要单独修改你还得把整个JSON拿出来反序列化、改完再塞回去很不爽。这时候就该用Hash。Hash的结构是key - field - value特别适合存储对象属性。比如用户信息user:1001下面挂name、age、phone等字段要单独修改phone一行HSET user:1001 phone 138xxxx就完事。但从内存占用上看Hash在字段很少的时候比String更省内存字段多了反而有额外开销需要权衡。List则天然是个消息队列或栈。LPUSHBRPOP的组合可以实现一个简易的可靠队列比直接拿MQ的架构轻得多。不过注意一点BRPOP在阻塞等待时如果有大量消费者挂在那Redis的client-output-buffer-limit可能会把连接的缓冲区打爆尤其是消费端处理慢、积压多的时候日志里会出现Client closed connection。2.2 Set、ZSet的边界以及Bitmap、HyperLogLog、GeoSet适合做去重、集合运算——共同好友、点赞用户、在线状态。SADD、SISMEMBER、SINTER这三个命令基本能覆盖社交场景里的大部分需求。ZSet有序集合是Redis里最“值钱”的类型每个成员关联一个分数天然支持按分数排序。排行榜、延迟队列用分数存时间戳、滑动窗口限流都拿它实现。要注意的是ZSet底层是跳表加哈希表写入性能比List稍低所以在排行榜这种高频写的场景里可以配合Redis的管道和批量操作来降低开销。除了五大基本类型还有三个容易被忽略但很实用的结构Bitmap本质是String上的位运算适用于亿级用户的签到记录。一个用户一年的签到数据只要365个bit几千个用户也就是几十KB的事。HyperLogLog做UV统计的利器标准误差0.81%12KB的固定内存就能统计2^64个不同值。代价是无法精确删除某个值所以它只适合“统计个大概”的场景。Geo底层就是ZSet常用在“附近的人”这类位置服务里GEOSEARCH命令直接按经纬度搜半径内的成员比自己在MySQL里算球面距离要快得多。选类型有个朴素的判断标准这个数据是要被单独读取还是整体读取要顺序输出吗有集合运算需求吗需要范围查询吗把这几个问题问一遍类型基本就定下来了。3. 检索与可视化命令行、图形客户端与一次生产事故3.1 redis-cli 的高效玩法不管用了什么花哨的可视化工具redis-cli都是排查问题时的第一选择。几个高频命令# 查看所有key生产环境慎用 redis-cli --scan --pattern user:* # 查看key的剩余过期时间 redis-cli -a yourpass TTL user:1001 # 查看某个key的内存占用 redis-cli --bigkeys # 实时监控命令 redis-cli --stat这里要特别强调生产环境千万、千万不要直接执行KEYS *。Redis是单线程KEYS会阻塞整个服务数据量大的时候一次KEYS就能让线上接口集体超时。正确姿势是用--scan加--pattern游标式扫描或者用SCAN 0 MATCH user:* COUNT 100命令手动控制迭代。我刚工作第一年就吃过这个亏在预发环境执行了一次KEYS user:*结果那台机器上所有Redis操作卡了几十秒幸好流量不大没酿成线上事故但也够吓出一身冷汗。3.2 可视化工具的选型与避坑图形化客户端里Redis Desktop ManagerRDM是名气最大的但新版已经闭源收费。免费方案我推荐Another Redis Desktop ManagerGitHub上有开源的Linux/Windows/macOS安装包界面清爽、支持SSH隧道和哨兵模式日常开发和测试完全够用。用RDM或Another RDM连接时最容易遇到两类问题Connection refused要么是Redis绑定的是127.0.0.1只能本机连要么是云服务器的安全组/防火墙没放行6379端口。如果只是本地开发bind 0.0.0.0加requirepass是可以接受的但生产环境不要暴露公网端口。NOAUTH Authentication required没配密码就能连上说明你的requirepass没生效检查配置文件或启动参数里是否写了密码。另外看数据的时候谨慎用“Load all keys”之类的按钮。Redis Desktop Manager早期版本有个操作是批量加载所有key的元数据数据量大时会打满连接效果跟KEYS *差不多。Another Redis Desktop Manager在这一点做得更克制但也别老想着把所有key一次拉出来。3.3 一次线上事故的日志排查实录有一回线上接口突然变慢排查链路发现Redis的响应时间从1ms飙到800ms但CPU和内存都正常。我先用redis-cli --stat看发现connected_clients从几十涨到几千blocked_clients也有值判断是大量命令在阻塞等待。再上SLOWLOG GET 10看慢日志发现清一色都是KEYS命令最后定位到是一个测试脚本误连了生产库。从那之后我在Redis配置里直接设置了rename-command KEYS 和rename-command FLUSHALL 彻底从源头禁止了这类危险命令。这个习惯一直保留到现在新环境的Redis配置第一件事就是禁掉KEYS、FLUSHALL、FLUSHDB宁可后续需要时再手动恢复也不能把它暴露给所有连接者。4. 序列化与Java客户端RedisTemplate的“连环坑”4.1 JDK序列化引发的问题Java接入Redis目前主流的还是Spring Data Redis。新手最容易踩的坑是序列化器没有配置导致存进去的数据变成一堆\xAC\xED\x00\x05t\x00...的乱码。这背后是默认的JDK序列化在作祟。RedisTemplate如果没有显式设置SerializerKey和Value都会用到JdkSerializationRedisSerializer。它的优点是Java原生的Serializable对象开箱即用缺点是三点序列化后是二进制数据在可视化工具里看全是乱码无法排查问题体积膨胀严重一个普通的POJO存成二进制会比JSON大2-5倍白白消耗内存跨语言能力差别说是PHP、Go了就是Java服务之间如果是不同公司维护也不方便直接解析。所以生产项目里必须换上可读性更好的序列化方案。最常用的组合是Configuration public class RedisConfig { Bean public RedisTemplateString, Object redisTemplate(RedisConnectionFactory factory) { RedisTemplateString, Object template new RedisTemplate(); template.setConnectionFactory(factory); // Key使用String序列化方便肉眼查看 StringRedisSerializer keySerializer new StringRedisSerializer(); // Value使用Jackson序列化JSON格式可读性强 GenericJackson2JsonRedisSerializer valueSerializer new GenericJackson2JsonRedisSerializer(); template.setKeySerializer(keySerializer); template.setHashKeySerializer(keySerializer); template.setValueSerializer(valueSerializer); template.setHashValueSerializer(valueSerializer); template.afterPropertiesSet(); return template; } }这里的细节在于Key统一用StringRedisSerializer因为Redis的Key本身就是一个字符串没必要搞特殊Value用GenericJackson2JsonRedisSerializer它在反序列化时会带上class类型信息能还原成原来的对象类型。代价是存进去的JSON里多了一个class字段有点占空间但换来的是省心代价可以接受。如果你的Redis拆成了两块一类是纯字符串缓存比如接口返回的JSON一类是业务对象更推荐的方案是主配置里Value用String业务对象直接用StringRedisTemplate手动JSON序列化。这样最可控不会因为类型转换问题浪费一晚上的排查时间。4.2 increment()报错increment不是integer或out of range围绕搜索热词里有一个非常典型的问题——调用RedisTemplate.opsForValue().increment(key, 1)时报错ERR value is not an integer or out of range。我第一次遇到这个报错时第一反应是“我的Value不是数字”。一查果然之前往同一个key里存过一个JSON字符串再对它执行INCRBYRedis当然报错。原因很简单INCREMENT命令只接受整数类型的字符串如果你的Value是{\name\:\test\}它没法转成数字。但还有一种隐蔽的原因Value序列化器不一致。比如你往key里存数据时用的是GenericJackson2JsonRedisSerializer后来换了配置、或另一个Service用了不同的Template去执行increment()从JDK序列化器读出来的二进制Value传到RedisRedis看到的是一串无法识别的二进制前缀自然就认为它不是整数。这种情况在微服务架构里特别常见A服务写、B服务读两边序列化配置不一样就会出这种“鬼问题”。排查思路就三步先GET key看存的值是什么再确认读写两边用的序列化器是否一致最后确认这个key之前是不是被其他业务复用、写了非数字内容。顺带提一嘴increment()这个操作在高并发下是原子的Redis单线程执行命令不存在“先读后写”的并发问题比getset的Java代码安全得多。做计数器、库存扣减时优先用它。4.3 哪些数据适合走序列化哪些彻底不需要不是所有数据都要走对象序列化。根据我的经验把缓存数据分三类处理最不容易出错String类型纯字符串验证码、Token、前端传入的原始数据直接用StringRedisTemplate序列化配置越简单越好JSON对象接口返回的大JSON、配置项、用户对象用Jackson序列化成字符串存储读出来再反序列化。这里推荐用GenericJackson2JsonRedisSerializer统一处理二进制的文件流/临时上传文件这些根本不应该放Redis用本地磁盘或OSS对象存储更合适。硬塞那些几MB的图片数据进Redis内存很快就烧完了。5. 缓存治理穿透、击穿、雪崩与分布式锁的实操5.1 缓存三大难题的应对策略缓存穿透、缓存击穿、缓存雪崩这三兄弟是面试必问也是线上事故的常见元凶。缓存穿透——请求的数据在缓存和数据库里都不存在每次请求都直接打在数据库上。恶意攻击者拿一个不存在的ID疯狂请求DB的压力会被无限放大。解决方案有两种第一种是缓存空值查询不到数据时也往Redis里写一个Null并设置一个较短的过期时间比如60秒第二种是用布隆过滤器先挡一层把合法的ID都预置进去不存在就直接拒绝不查DB。实际项目中我倾向于先用空值缓存因为实现简单、改动小后续有需要再上布隆过滤器。缓存击穿——某个热点key过期的一瞬间大量并发请求同时打到DB。由于这些请求同时发现缓存失效就会不约而同地回源数据库。解决思路是“让大部分请求等待让一个请求去刷新缓存”。工具就是分布式锁在加载缓存的逻辑里先加锁拿到锁的线程去DB查询并回写缓存其他线程阻塞等待锁释放后直接读缓存。还有一个更优雅的方案是“逻辑过期”不设置物理过期时间而是把过期时间放在Value里读的时候发现逻辑过期就把旧数据直接返回同时异步去更新缓存。这个方案避免了等待但存在短暂的脏读业务上可接受的话就可以用。缓存雪崩——大量key在同一时间段集体过期比如设置过期时间时统一用“当前时间1小时”结果到点后大批key一起失效。解决思路就一句话把过期时间打散。在expire上加上一个随机值比如base new Random().nextInt(300)这样就不会集中失效。还有一种做法是热点数据不设置过期时间用后台定时任务统一刷新。5.2 分布式锁从SETNX到Redisson的演进分布式锁这块我建议直接从Redisson用起但得先理解底层的演进过程因为面试官一定会问而且排查问题时也会涉及。最早期的做法是SETNX key value——只有key不存在时才能设置成功抢到锁。但这个方案有个致命问题如果持有锁的线程崩溃了锁永远不会释放其他线程全部死等。于是引入了SET key value NX EX 30加锁时同时设置一个过期时间防止死锁。这里又出问题了持有锁的线程没崩溃但业务执行超过了30秒锁自动过期了其他线程拿着新锁进入临界区两个线程同时在做“互斥操作”分布式锁名存实亡。而且A线程释放锁时如果没判断是不是自己的锁——它跑完业务后执行DEL删的却是B线程后来获取的新锁。所以原生方案的完整写法应该是String token UUID.randomUUID().toString(); Boolean locked redisTemplate.opsForValue().setIfAbsent(key, token, 30, TimeUnit.SECONDS); if (locked) { try { // 业务逻辑 } finally { if (token.equals(redisTemplate.opsForValue().get(key))) { redisTemplate.delete(key); } } }这个写法能解决误删别人锁的问题token校验但仍没有解决“业务执行超时导致锁提前失效”的痛点。为此Redisson引入了看门狗机制它加锁成功后会启动一个定时任务每隔10秒锁的默认时长检查一次锁是否仍然持有如果持有就自动把锁续期到30秒。这样只要线程还在运行锁就不会被提前释放线程崩溃了看门狗随客户端一起死掉锁在30秒后自然过期。Redisson的使用非常简单RLock lock redissonClient.getLock(order:pay: orderId); boolean success lock.tryLock(3, 10, TimeUnit.SECONDS); if (success) { try { // 处理订单支付 } finally { lock.unlock(); } }还有一个进阶问题值得大家思考在Redis的主从架构下如果Master节点加了锁但还没把数据同步到Slave节点就宕机了哨兵把Slave提升为Master这时锁就丢了。Redis官方给出的RedLock方案向多个独立节点加锁理论上能缓解这个问题但实际操作中架构复杂、争议也大。对于绝大多数业务来说Redis分布式锁已经够用如果对锁的可靠性要求极高建议直接换成ZooKeeper或etcd的分布式锁而不是去折腾RedLock。5.3 数据一致性双删、失败补偿与监听binlog缓存和数据库的一致性是个古老的话题。先明确一个基本结论别指望强一致Redis缓存的定位就是“最终一致”核心手段是失效而不是更新。当前业界最常见的方案是Cache Aside Pattern 延迟双删。读操作先读缓存没有则查DB、写缓存写操作先更新DB再删除缓存。这里有个问题线程A更新DB后还没来得及删缓存线程B读到了旧缓存就会产生不一致。延迟双删的做法是更新DB后先删一次缓存隔几百毫秒再删一次把中间时段被写进去的旧缓存清掉。这个方法不能100%避免不一致但可以把窗口压缩到极小。对一致性要求更高的场景可以考虑订阅MySQL的binlogCanal等中间件把数据变更事件异步同步到Redis。这样业务代码不需要自行处理缓存失效逻辑异常情况也统一由消费端重试算是比较优雅的方案。但复杂度会显著上升团队如果只有两三个人维护不建议一上来就上Canal先确认业务是否能接受短暂的不一致再说。6. 高可用架构从主从复制到Docker化哨兵部署6.1 主从复制的原理与配置要点Redis的主从复制简单来说就是Slave节点主动向Master发起SYNC请求Master持久化当前数据RDB快照发给Slave后续再通过命令传播把写操作不断同步给Slave。主从配置本身不复杂在Slave节点的配置文件里加一行replicaof 192.168.1.10 6379但有几个细节值得注意。第一从Redis 5.0开始推荐用replicaof替代老旧的slaveof二者等效但新配置文件已经全面切换到新术语。第二主从架构下读写要分离Master负责写和热点读Slave负责查询类和异步任务否则主从复制就没有意义。第三如果Slave是只读的一定要在配置里显式设置replica-read-only yes防止人为误写。用Docker拉主从结构时网上很多教程教你写两个不同的Compose文件其实更清晰的是用一个Compose管理多个容器services: redis-master: image: redis:7.2-alpine container_name: redis-master ports: [6379:6379] volumes: [./master.conf:/usr/local/etc/redis/redis.conf] command: redis-server /usr/local/etc/redis/redis.conf redis-slave: image: redis:7.2-alpine container_name: redis-slave depends_on: - redis-master ports: [6380:6379] volumes: [./slave.conf:/usr/local/etc/redis/redis.conf] command: redis-server /usr/local/etc/redis/redis.confSlave的配置文件里只需要设置replicaof redis-master 6379 replica-read-only yes6.2 哨兵与Cluster的选型判断主从复制能解决读扩展和单点故障但它不会自动故障转移——Master挂了Slave并不会自动顶上。自动切换这个活儿由哨兵Sentinel来完成。哨兵本身是一个独立进程它会监控Master和Slave的状态发现Master不可用后从Slave中选举出一个新的Master并把其他Slave的复制目标切换到新Master。一个生产级的哨兵架构至少是“一主两从三哨兵”三哨兵是为了满足“多数派选举”的容错要求。用Docker Compose部署三哨兵核心配置是sentinel monitor mymaster redis-master 6379 2 sentinel down-after-milliseconds mymaster 5000 sentinel failover-timeout mymaster 15000这里数字2表示“至少2个哨兵同意Master下线”才触发故障转移。如果有两个哨兵一个挂了就凑不齐这个数所以一般部署奇数个哨兵3个、5个保证能形成多数派。数据量更大、需要水平扩展时就该上Redis Cluster了。Cluster模式把数据按哈希槽16384个slot分布到多个节点上每个节点负责一部分槽支持自动分区和在线扩容。但要注意Cluster的客户端实现比单机复杂很多MGET、MSET这类多Key操作在key不在同一节点时会直接报错除非用哈希标签事务和Lua脚本也受槽位限制。如果业务只是几百万QPS以内的规模一主两从三哨兵完全够用不必为了“高级”而上Cluster。6.3 Docker Compose部署Redis主从的完整实践最后放一套基于Docker Compose的“生产环境准入门槛”配置包含Master与Replica两个节点。先准备主从两份配置文件master.confbind 0.0.0.0 protected-mode yes port 6379 tcp-backlog 511 timeout 0 tcp-keepalive 300 daemonize no supervised no pidfile /var/run/redis_6379.pid loglevel notice logfile databases 16 always-show-logo no set-proc-title yes save 900 1 save 300 10 save 60 10000 stop-writes-on-bgsave-error yes rdbcompression yes rdbchecksum yes dbfilename dump.rdb dir /data appendonly yes appendfilename appendonly.aof appendfsync everysec requirepass your-redis-password masterauth your-redis-passwordslave.confbind 0.0.0.0 protected-mode yes port 6379 daemonize no replicaof redis-master 6379 replica-read-only yes requirepass your-redis-password masterauth your-redis-password appendonly yes appendfsync everysec dir /dataCompose文件services: redis-master: image: redis:7.2-alpine container_name: redis-master restart: always ports: - 6379:6379 command: [redis-server, /usr/local/etc/redis/redis.conf] volumes: - ./master.conf:/usr/local/etc/redis/redis.conf - ./master-data:/data environment: - TZAsia/Shanghai redis-slave: image: redis:7.2-alpine container_name: redis-slave restart: always depends_on: - redis-master ports: - 6380:6379 command: [redis-server, /usr/local/etc/redis/redis.conf] volumes: - ./slave.conf:/usr/local/etc/redis/redis.conf - ./slave-data:/data environment: - TZAsia/Shanghai执行docker compose up -d之后验证主从状态docker exec -it redis-master redis-cli -a your-redis-password INFO replication输出的role:master和connected_slaves:1就说明主从搭建OK。特别注意主从节点都要配置masterauth因为主节点在故障转移时可能变成从节点需要反向认证从节点也需要masterauth来通过主节点的requirepass认证。这套配置里把appendonly开了使用AOF每分钟刷盘everysec配合RDB做混合持久化兼顾数据安全与性能。实测下来通用业务场景下这个组合的可靠性和性能平衡得最好比单开RDB丢掉几秒数据更稳妥也比每次写操作都刷盘always的吞吐量高很多。如果业务允许丢最后一秒数据还可以调整为纯RDBIO开销更小。7. 日常运维与避坑清单7.1 内存监控、慢查询与性能调优Redis运维的核心其实就是盯住内存、慢查询和连接数三件事。内存方面用INFO memory看used_memory和maxmemory用redis-cli --bigkeys找出大Key。大Key是Redis的心腹之患一个几MB的String在执行GET时才不会出问题但如果用DEL删除它会导致Redis单线程阻塞业务瞬时卡顿。所以删除大Key要用UNLINK异步删除或者分批删除redis-cli --scan --pattern session:* | xargs -L 100 redis-cli UNLINK慢查询方面配置slowlog-log-slower-than 10000单位微秒即10ms和slowlog-max-len 128然后定期看redis-cli SLOWLOG GET 20如果发现大量慢命令是KEYS、HGETALL、LRANGE key 0 -1不用怀疑设计上出了问题要么用了危险命令要么某个key的集合太大需要拆分。连接数方面INFO clients看connected_clients超出预期就查代码里Redis连接是否泄漏重点排查Jedis、Lettuce客户端的连接池配置。7.2 配置安全检查清单结合多年摸爬滚打的经验新装一套Redis后建议逐项检查这些配置requirepass是否设置强密码至少16位不要用123456bind是否限制为内网IP是否暴露到公网protected-mode是否合理公网环境必须yes兼密码危险命令KEYS、FLUSHALL、FLUSHDB、CONFIG是否通过rename-command禁用是否开启AOFappendfsync是否与业务容忍度匹配maxmemory和maxmemory-policy是否配置内存打满时不能指望Redis自动清理。我在一次安全巡检中发现过不少裸奔的Redis实例——没有密码、绑定0.0.0.0、6379端口直接暴露在公网用redis-cli就能连上并写入数据。这不是玩笑大家可以自查一下自己的测试环境和生产环境有没有类似隐患该补的赶紧补。Redis本身的设计非常简洁、可靠绝大部分线上事故都不是Redis的错而是使用姿势的问题。把序列化、过期策略、集群配置这些基础功课做扎实Redis能帮你扛住绝大多数业务压力还几乎不需要额外维护。这也是我为什么一直觉得缓存中间件里Redis是后端同学最值得花时间吃透的一样东西。