ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Redis从入门到实战:数据类型、持久化、缓存治理与分布式锁全解析

Redis从入门到实战:数据类型、持久化、缓存治理与分布式锁全解析 不少后端同学学Redis都是东一榔头西一棒子今天看到一道面试题背一下明天遇到缓存穿透查一篇博客后天部署集群又踩一遍坑。等真正上了生产环境才发现自己会的只是冰山一角连INFO命令打印出来的指标都看不懂。我最早接触Redis是在一个秒杀项目里当时只觉得它是个“快一点的HashMap”直到后来在缓存一致性、分布式锁、主从切换这些真实场景里反复被折腾才慢慢把整张知识网串起来。这篇内容不是官方文档的搬运而是我把自己从入门到实战踩过的、用过的、踩完又重新理解的东西完整梳理了一遍。覆盖了Redis安装部署Windows、macOS、Linux、Docker全都有、九种核心数据类型及底层原理、持久化机制、缓存穿透/击穿/雪崩的治理方案、分布式锁的工程实现、主从复制与集群搭建、可视化客户端选型还有大厂高频面试题的精讲。不管你是刚接触Redis的小白还是准备跳槽想系统过一遍的开发者都可以直接照着往下走。1. 入门先搞清楚Redis到底解决什么问题凭什么这么快很多人上来就背“Redis是开源的、基于内存的、支持多种数据结构的键值对存储数据库”这句话对但没用。工程上你更需要的答案是项目里哪个痛点最适合用Redis来解。1.1 核心定位缓存是地基但不是全部Redis最常见的定位就是缓存层把热点数据从MySQL里搬到内存把响应时间从几十毫秒压到几毫秒。但如果你只把Redis当缓存用后面这些场景你照样会碰见分布式锁多个服务实例同时操作同一份资源需要跨进程互斥排行榜游戏、社区、电商都离不开实时排名ZSet天生就是干这个的限流与计数接口防刷、库存扣减INCR配合过期时间就是最轻量的计数器消息队列轻量级场景下List的LPUSHBRPOP完全可以替代MQ分布式Session多实例部署时Session共享Redis是默认解位图统计用户签到、在线状态SETBIT能省出惊人的内存。所以学习Redis的第一件事是把“它不只是缓存”这个观念刻进脑子里。否则你会在很多系统设计里明明Redis能一行代码解决却绕一大圈去造轮子。1.2 高性能的秘密内存、IO多路复用、单线程模型关于Redis为什么快面试官喜欢问实际做架构选型时也值得理解纯内存操作数据读写都发生在内存内存的随机访问速度是纳秒级别磁盘是毫秒级别差好几个数量级IO多路复用Redis用epoll同时监听大量客户端连接一个线程就能处理成千上万个并发请求没有线程切换开销单线程执行命令所有命令在一个线程内串行执行避免了锁竞争和上下文切换。你可能会问那为什么6.0又引入了多线程因为瓶颈不在命令执行而在网络IO的读写6.0把socket读写放到了多线程命令执行仍然是单线程的所以不存在线程安全问题。这里有一个关键认知单线程不等于性能差反而让Redis的原子性变得非常简单。因为有单线程模型INCR、SETNX这类命令天然就是原子的不需要额外加锁。1.3 和 MySQL、Memcached 的边界在哪做技术选型时经常有人问既然Redis这么强能不能把MySQL干掉答案是不能。Redis内存型容量受物理内存限制数据可靠性依赖持久化策略适合放热数据MySQL/PostgreSQL磁盘型容量大事务能力强适合放全量数据和强一致要求的业务数据Memcached纯缓存只支持简单的KV结构没有持久化、没有丰富数据结构现在基本被Redis替代新项目不建议再用。一句话总结选型逻辑全量数据进MySQL热数据进Redis需要复杂结构List/Hash/ZSet的场景只选Redis。2. 安装部署实操Windows、macOS、Linux和Docker一网打尽这一章我按平台逐个走一遍每个平台都标出我实际踩过的坑。别小看安装环境起不来后面的学习全是空谈。2.1 Windows下安装Redis官方不原生支持但有变通方案Redis官方并不提供Windows版本Windows上流行的是微软技术团队维护的旧分支停留在3.x/5.x或者tporadowski维护的5.0.14版本。你搜“redis windows 下载”会看到很多来源直接认准GitHub上带Windows标识的release包即可。具体步骤下载zip压缩包解压到一个无中文、无空格的路径比如D:\dev\redis;打开目录可以看到redis-server.exe、redis-cli.exe、redis.windows.conf等文件;启动服务双击redis-server.exe或者更推荐在命令行执行cd D:\dev\redis redis-server.exe验证另开一个命令行窗口执行redis-cli.exe ping返回PONG说明成功。Windows下部署Redis做生产环境我是不建议的。路径分隔符、服务注册、权限方面能遇到一堆小毛病更适合本地调试。真要上生产请直接用Linux。设置密码这一步Windows版就是在配置文件里找到requirepass这一行改成requirepass 你的密码然后重启服务。注意Windows下编辑配置文件要用UTF-8编码保存否则中文注释会乱码导致解析失败。2.2 macOS安装RedisHomebrew一条命令macOS的安装路径很清晰打开终端brew install redis这会自动安装Redis并附带安装redis-cli和redis-server。安装完后启动服务# 前台启动适合看日志 redis-server # 后台启动用Homebrew服务管理 brew services start redis配置文件默认在/opt/homebrew/etc/redis.confApple Silicon或/usr/local/etc/redis.confIntel。macOS上最容易踩的坑是redis-server版本和redis-cli版本对不上比如用brew upgrade redis之后老进程还占着端口解决方案是brew services stop redis后重新启动。2.3 Linux安装Redis源码编译最稳妥Linux上主流有两种方式包管理器和源码编译。CentOS的yum install redis装的可能版本偏旧我建议直接源码编译# 下载稳定版以7.0为例 wget https://download.redis.io/releases/redis-7.0.12.tar.gz tar xzf redis-7.0.12.tar.gz cd redis-7.0.12 # 编译 make # 安装到 /usr/local/bin make installRedis没有configure脚本make之后直接就能用。启动方式# 以后台守护进程方式启动 redis-server /etc/redis.conf --daemonize yes源码编译的本质是生成redis-server、redis-cli、redis-sentinel、redis-check-aof等二进制文件所以make install之后这些命令会进入系统PATH随时可用。2.4 Docker部署Redis最推荐的学习方式Docker是现在跑Redis最省心的方式没有之一。一条命令起一个干净的实例docker run -d --name redis-test \ -p 6379:6379 \ -v /data/redis/conf:/etc/redis \ -v /data/redis/data:/data \ redis:7.0 redis-server /etc/redis/redis.conf这里有三个参数要解释清楚-p 6379:6379必须暴露端口否则容器外部访问不到-v挂载配置文件和数据目录容器删了数据还在生产环境必须做最后跟的redis-server /etc/redis/redis.conf覆盖默认启动命令加载你自己挂载进去的配置。再补充一个坑搜“docker search redis”时如果你看到docker search redis request returned 500 internal server error这类报错大概率不是Redis仓库的问题而是Docker Desktop的网络层没起来或镜像加速失效。处理顺序是先docker login确认认证状态再检查/etc/docker/daemon.json里的镜像源最后重启Docker服务。2.5 安装后的基础验证与常见连接问题不管是哪种方式装好的验证三步走# 1. 确认进程 ps -ef | grep redis # 2. 确认端口 netstat -an | grep 6379 # 3. 命令行连通 redis-cli ping我几乎每天都会遇到“redis-cli能连但程序连不上”的问题。排查路径固定在四层第一bind配置是不是写死了127.0.0.1默认只允许本机其他机器连不上第二防火墙放行6379没有第三protected-mode是否开启默认yes只在本地连接时正常第四密码配置是否在客户端填上了。Windows下如果客户端工具连不上很大概率是protected-mode在作怪直接把protected-mode yes改成no并重启就能通。3. 核心数据类型九种数据结构逐个拆解这是Redis的地基。很多人问“Redis为什么面试必考数据类型”因为数据结构决定了你能用它解决什么场景问题也决定了你写出的代码性能和可维护性。3.1 String字符串String是Redis最简单的结构但也是最常被误用的。它的价值在于组合了一个原子计数器# 普通缓存 SET user:10086 {name:tom,age:18} # 原子自增秒杀库存、点赞数 INCR product:buy:count:10086 # 设置过期时间防重提交锁 SET order:lock:1024 1 EX 5 NX注意SET key value EX seconds NX这个命令组合它是后面分布式锁的最原始形态一条命令就完成了“设置值过期时间不存在才设置”三个动作原子性靠单线程模型保证。我见过很多同学用两步走先SETNX再EXPIRE这种写法是错的两步之间如果进程崩溃锁会变成永不释放的死锁。3.2 Hash哈希Hash适合存对象。比如用户实体比用String存JSON更灵活HSET user:10086 name tom age 18 HGETALL user:10086 HINCRBY user:10086 age 1用Hash存对象的场景优势是字段级操作。你只想改用户的age字段不用把整个JSON串读出来反序列化再写回去直接HINCRBY即可。购物车、Session、配置中心都以它为基础。3.3 List列表List本质是个双向链表两端操作都是O(1)# 右侧入队左侧出队消息队列模型 LPUSH mq:task task1 BRPOP mq:task 0 # 阻塞式消费BRPOP key 0里的0表示永不超时阻塞这是实现轻量级队列的关键。LIFO后进先出的场景比如最近浏览记录直接用LPUSHLTRIM限制列表长度。3.4 Set集合与ZSet有序集合Set里的元素不能重复天然适合去重# 抽奖已抽过的不再抽 SADD lottery:2024 user:10086 # 集合运算共同关注、好友推荐 SINTER user:10086:follows user:10088:followsZSet在Set基础上多了score分值按score排序。排行榜、延时队列都靠它# 游戏分数排行 ZADD rank:game 100 user:10086 ZREVRANGE rank:game 0 9 WITHSCORES # 取前10名之所以能高效排序是因为ZSet底层是跳跃表skip list哈希表。哈希表用来快速定位成员跳跃表用来按score区间有序遍历。这是理解“为什么ZSet能做排行榜”的关键单纯知道命令不够。3.5 其他类型Bitmap、HyperLogLog、Geo、Stream这四类属于“特定场景神器”问的人不多但项目里用对了非常加分Bitmap位图单个bit表示一个状态适合月活统计、用户签到。一亿用户只需约12MB内存HyperLogLog基数统计UV误差约0.81%内存固定约12KB用空间换实现简单Geo地理位置基于ZSet实现存经纬度后可以算两点距离、找附近的人StreamRedis 5.0引入的专门消息队列支持消费者组、ACK确认比List更可靠。3.6 序列化问题为什么存到Java里全是“乱码”这是实战高频问题。你用Spring Data Redis存一个对象再通过redis-cli查看发现value是\xAC\xED\x00\x05t...这种乱码这是Java原生序列化的结果。解决方案有两种思路在RedisTemplate中自定义RedisSerializerkey用StringRedisSerializervalue用Jackson2JsonRedisSerializer或GenericFastJsonRedisSerializer干脆就用StringRedisTemplate自己负责Json转换先JSON.toJSONString(obj)再存读出来再转回对象。我本人倾向于方案二原因很简单中间件里存的东西必须能被人看懂、能被运维排查。乱码的value在排障时就是灾难你根本不知道线上缓存里到底存了什么。如果你想保证缓存结构清晰从最早就要把序列化策略定清楚。4. 持久化机制RDB与AOF一个都不能迷信Redis是内存数据库一旦宕机内存数据全部丢失。持久化就是为了把数据从内存落盘在重启后恢复。这里有两个方案面试必问工程必配。4.1 RDB快照全量二进制备份RDB会fork一个子进程把当前内存数据生成一个二进制快照文件默认dump.rdb。触发方式有配置触发比如save 900 1表示900秒内至少1次写操作就快照、手动BGSAVE、关闭时自动保存。RDB的优点文件紧凑、加载速度快、非常适合做备份和灾备。缺点是两次快照之间的数据会丢。比如间隔15分钟最后15分钟写入的数据全都丢了。这在很多业务上是不可接受的。4.2 AOF追加写日志AOF记录的是“写操作命令本身”类似数据库的binlog。每来一条写命令Append Only File追加一条。恢复时把文件里的命令重放一遍。AOF有三种刷盘策略appendfsync always每次写命令都fsync到磁盘最安全但性能最差appendfsync everysec每秒刷一次盘最多丢1秒数据appendfsync no交给操作系统决定性能最好但可能丢几秒数据。生产环境我推荐everysec丢一秒业务可接受性能和可靠性能兼顾。4.3 4.0之后的混合持久化Redis 4.0引入了混合持久化AOF文件头部是RDB格式的全量快照后面是增量AOF日志。重启时先加载RDB快照再重放少量AOF既有RDB加载快的优点又避免全量重放AOF的慢启动。开启方式就一行aof-use-rdb-preamble yes4.4 实战建议备份策略不能只靠Redis本身不管你选RDB还是AOF都要定期把dump文件复制到异地或云存储。原因很简单Redis的持久化文件是为了“宕机重启”不是为了应对“磁盘损坏”。如果Redis所在的机器磁盘物理损坏本地的RDB/AOF一起完蛋。正确姿势是写个定时任务crontab每天凌晨把rdb文件rsync到备份服务器。注意主从架构下一般只在主节点开启AOF从节点默认也会同步主节点数据但不要在从节点上单独开持久化否则会增加无谓的磁盘IO。5. 缓存治理穿透、击穿、雪崩的完整解决方案这一章是面试重灾区也是线上故障高发区。很多人背概念背得很溜一问“你怎么解决”就只会说“布隆过滤器”“加锁”但落到代码上完全站不住脚。5.1 缓存穿透查的数据根本不存在“穿透”指请求查找一个缓存和数据库都不存在的数据。因为缓存里没有每次都miss请求全部打到数据库。恶意攻击者只要不停构造不存在的ID就能把数据库打挂。方案有三个层次参数校验非法ID直接返回错误这是第一道门缓存空值查数据库结果为空也往Redis里写一个空值并设置较短过期时间比如2-5分钟。这是最简单有效的方案布隆过滤器Bloom Filter把所有可能存在的数据ID预先加载到bit数组里请求来的时候先判断ID是否可能存在不存在的直接挡掉。布隆过滤器有个特点判断“不存在”绝对准确判断“存在”可能误判。用大白话说它只会漏网不会错杀。在用过滤器前你得接受“极少数合法请求可能被误判拦截”的小概率风险。5.2 缓存击穿热点key过期瞬间的并发冲击击穿和穿透容易混。击穿专指“某个热点key在过期的瞬间大量并发请求同时落到数据库”。比如秒杀商品的详情页缓存key刚好在抢购那一刻失效几千请求全打到MySQL。解决手段// 1. 互斥锁业界主流 public String get(String key) { String value redis.get(key); if (value null) { // 请求互斥只有一个线程能查库并重建缓存 if (redis.setnx(key :lock, 1, 3, TimeUnit.SECONDS)) { try { value db.query(key); redis.set(key, value, 300, TimeUnit.SECONDS); redis.del(key :lock); } finally { redis.del(key :lock); } } else { // 其他线程等一会儿再读缓存 Thread.sleep(100); return get(key); } } return value; }逻辑过期缓存里不设物理过期时间而是多存一个逻辑过期时间字段。每次读取时对比逻辑时间发现超过预期时间就异步重建缓存。好处是永远不会让请求直接打到数据库坏处是实现复杂、存在短暂数据不一致。5.3 缓存雪崩大量key同时失效如果大量key设置了相同过期时间比如都设5分钟同一时刻集体过期会有瞬间海量请求落到数据库。解决办法过期时间加随机数把5分钟改成300 Random.nextInt(600)秒分散过期时间多级缓存Redis之上再加一层本地缓存Caffeine/JVM Map双保险服务降级核心数据走数据库非核心数据直接返回降级结果比如热门推荐从默认推荐列表顶上。5.4 缓存一致性问题更新数据库后缓存怎么办这块没有银弹只有取舍。最稳妥的通用模式是Cache Aside旁路缓存读先读缓存命中返回未命中读数据库回填缓存并设置过期时间写先更新数据库再删除缓存。有人会问为什么不先删缓存再更新数据库因为这两个操作都存在窗口期。先删缓存后更新数据库在“删除缓存→更新数据库”的间隙老数据会被其他线程重新写回缓存导致缓存里一直是旧值。先更新数据库再删缓存只要删缓存那一瞬间失败概率极低整体一致性水平就好得多。延迟双删Delayed Double Delete是更进一步的方案更新数据库后先删缓存等几百毫秒再删一次缓存目的是解决读写并发时的“脏缓存”窗口。但要注意延迟双删不是绝对可靠一致性要求极高的系统应该走消息队列异步删除或Canal订阅binlog删除。6. 分布式锁从SETNX到Redisson的正确演进路线分布式锁是Redis的高级用法之一。为什么要分布式锁因为多个Java实例部署在不同机器上JVM里的synchronized只能锁住本进程管不到别的进程。6.1 第一阶段SETNX EXPIRE的原始实现最原始的写法是SETNX lock:order:10086 1返回1表示抢到锁返回0表示没抢到。解锁时直接DEL。这个方案的致命问题是持有锁的进程崩溃了锁永远不会释放。所以加上了EXPIRE设置过期时间。但“SETNX”和“EXPIRE”两条命令分开执行中间进程崩溃锁还是死锁。正确的原子写法是前面提过的SET lock:order:10086 1 EX 10 NX这条命令的意思是“如果key不存在就设置key且10秒后自动过期”。这是分布式锁的第一版正确形态。6.2 第二阶段解锁校验与超时续期直接DEL解锁有隐患如果线程A持有的锁已经超时自动释放了线程B拿到锁此时A执行完业务再去DEL会把B的锁误删。解决办法是设置一个唯一标识# 加锁时放入唯一标识 SET lock:order:10086 uuid-xxx EX 10 NX # 解锁前先比较是自己的锁才删除 if redis.get(lock:order:10086) uuid-xxx: redis.del(lock:order:10086)注意上面这个比较删除不是原子的需要用Lua脚本包裹。Redis在执行Lua脚本时也是原子性的所以业界统一用Lua脚本来保证“判断值删除”的原子性。还有超时续期问题业务执行时间超过锁的过期时间锁提前释放了怎么办更健壮的做法是用Redisson的看门狗Watch Dog机制默认每10秒检查一次锁快过期了就自动续期到30秒直到业务执行完毕手动解锁。这个机制保证了“锁和业务同生共死”。6.3 第三阶段主从架构下的锁不可靠问题单机Redis的分布式锁很好用但Redis如果用了主从主节点挂了会自动切到从节点问题是主从复制是异步的锁刚写入主节点还没来得及同步到从节点主节点宕机从节点顶上后发现锁丢了其他线程可以再次抢到锁。这就是锁失效的安全隐患。Redisson官方给出的解决方案是RedLock红锁向多个独立的Redis节点同时加锁只有超过半数节点加锁成功才算获取锁成功。但RedLock在工程界争议很大因为它在极端网络分区情况下依然可能失效。我的实操建议是业务场景允许偶尔失效用单机Redis Redisson即可性能好、实现简单一致性要求极高比如金融级优先考虑ZooKeeper或etcd实现的分布式锁它们通过强一致性协议保证锁可靠代价是性能略低。6.4 防重幂等分布式锁的常见误区有一个高频误区分布式锁写完接口就“幂等”了吗答案是否定的。比如支付回调接口你加锁保证同一笔订单不会并发处理但业务处理失败后客户端重试还是会产生新问题。幂等是业务层面的概念需要唯一业务号结果状态表配合锁只是并发控制手段两者不能互相替代。7. 高可用架构主从、哨兵、集群的搭建与对比单机Redis再稳也有单点故障风险。高可用架构升级路径是主从复制 - 哨兵模式 - Redis Cluster集群。7.1 主从复制数据备份的起点主从复制的核心价值是“读写分离 数据热备份”。主节点负责写从节点负责读主节点数据异步同步到从节点。Redis的复制机制分两步全量同步从节点首次连接主节点主节点生成RDB快照发给从节点从节点加载快照增量同步后续主节点用repl_backlog缓冲区把新的写命令推给从节点。用Docker搭建一套主从是最快捷的方式# 主节点 docker run -d --name redis-master -p 6379:6379 redis:7.0 # 从节点连主节点 docker run -d --name redis-slave -p 6380:6379 \ redis:7.0 redis-server --slaveof 172.17.0.2 6379从节点配置文件里加上replicaof 主节点IP 6379即可。权限方面主从都设置了密码时从节点要配置masterauth否则复制会因认证失败中断。7.2 哨兵模式自动故障转移主从复制解决了“数据冗余”但主节点挂了从节点不会自动升级。哨兵Sentinel就是干这个的监控主节点状态发现主节点挂了自动从从节点中选举一个提升为新的主节点。哨兵部署至少3个实例形成奇数集群用Raft协议达成一致性决策。它的“客观下线”判定至少需要多少哨兵同意这个数量通常设置为2一方面防止单个哨兵误判另一方面保证多数派。7.3 Redis Cluster真正的分片集群Redis Cluster是Redis 3.0引入的分布式方案解决了“数据量超过单机内存”的问题。它把整个key空间分成16384个哈希槽slot每台机器负责一部分槽位。当你存取一个key时Redis对key做CRC16计算对16384取模定位到具体槽位。# 创建集群三主三従 redis-cli --cluster create \ 172.17.0.2:6379 172.17.0.3:6379 172.17.0.4:6379 \ 172.17.0.5:6379 172.17.0.6:6379 172.17.0.7:6379 \ --cluster-replicas 1--cluster-replicas 1表示每个主节点配一个从节点。集群模式下客户端会收到MOVED重定向指令但这通常是Jedis等客户端库内部自动处理的你作为业务开发者只需要配置好路由规则。7.4 架构选型建议小项目不要盲目上集群我的实际经验是业务初期QPS不高、数据量不到几十GB单机Redis AOF已经足够。等单机内存接近上限或需要更高吞吐时再考虑哨兵加读写分离。真正需要Redis Cluster至少要等到日活百万级、数据量几百GB以上。否则集群本身的管理、故障排查、批量操作跨slot限制带来的复杂度会直接吃掉你的开发效率。另外Cluster模式有一个明显的坑多key操作如MGET、MSET、Lua脚本要求所有key必须在同一个slot。跨slot的批量操作会直接报错方案是用{}hash tag强制指定相同slot# user:{10086}:name 和 user:{10086}:age 会被分到同一个槽 MSET user:{10086}:name tom user:{10086}:age 188. 可视化工具与日常运维我最终留下了这几个不管你是看数据还是排查问题总不能每次都敲命令。可视化客户端选得好排障效率能翻倍。8.1 Redis Desktop Manager 与 Another Redis Desktop Manager老牌工具是Redis Desktop ManagerRDM但它部分专业功能收费而且有些版本性能不太稳定。后来社区出了一个完全免费的开源版本Another Redis Desktop ManagerGithub上星标很高UI更现代支持连接Cluster、SSH隧道、多种序列化格式查看我现在的主力就是它。连接配置有几个常见坑地址填127.0.0.1但Redis配置了bind 0.0.0.0可能是防火墙拦了密码填了但协议选错Redis 6默认ACL协议老客户端需要填写用户名SSH方式登录时不要把SSH密钥和Redis密码混填。8.2 命令行工具redis-cli才是最终的兜底可视化工具再方便生产环境多半只有终端权限。redis-cli必须熟练# 查看所有key生产慎用会阻塞实例 redis-cli --scan --pattern user:* # 查看内存占用Top redis-cli --bigkeys # 查看慢日志 redis-cli slowlog get 10 # 实时监控命令 redis-cli monitormonitor会打印所有实时执行的命令非常适合排查“谁在偷偷删key”但生产环境不要长时间开着它会把命令输出刷爆客户端连接。8.3 从日志与INFO命令判断Redis健康状况“Redis日志”是排查问题的第一现场。你可以在配置文件里设置loglevel notice logfile /var/log/redis/redis-server.log然后用INFO命令看全维度状态connected_clients当前连接数如果持续打满maxclients排查是否是连接池泄漏used_memory内存占用评估是否触发maxmemory淘汰rejected_connections连接被拒绝数量反映配置上限latest_fork_usec最近一次fork耗时RDB持久化时fork过久会导致阻塞。我排查线上卡顿的基本流程先看INFO commandstats里最耗时的命令Top3再开SLOWLOG GET看慢命令结合MONITOR看到的实际流量90%的问题都能定位。9. 面试高频题目精讲与实战自检清单最后送上一份浓缩版面试题精讲覆盖了我面过几家大厂以及作为面试官问过别人的高频考点。9.1 高频考点速答Redis为什么快内存存储 IO多路复用 单线程避免锁竞争回答到epoll、事件驱动模型最好6.0多线程仅处理网络IO。Redis和Memcached区别数据类型丰富度、持久化能力、原生集群方案、内存淘汰策略更精细。缓存穿透、击穿、雪崩的区别穿透是查不存在的数据击穿是单个热点key过期雪崩是大量key同时过期或Redis宕机。分别对应空值缓存/布隆过滤器、互斥锁/逻辑过期、过期时间随机化/多级缓存/降级。RDB和AOF怎么选追求性能、数据可容忍丢分钟级别选RDB要求数据接近零丢失选AOFeverysec推荐混合持久化。Redis的过期删除策略惰性删除访问时发现过期才删 定期删除随机抽取部分key检查并删除二者结合精确删除用惰性主动清理用定期。内存淘汰策略有哪几种常用的有allkeys-lru全体按LRU淘汰、volatile-lru仅有过期时间的key按LRU淘汰、allkeys-random随机淘汰、noeviction不淘汰直接报错。生产建议allkeys-lru。Redis是单线程的为什么Lua脚本能保证原子性因为Lua脚本在Redis里整体作为一个命令执行执行期间不会被其他命令插入。并发下INCR为什么会不准INCR本身是原子命令不可能不准。所谓的“redis incr不准”通常出现在“先GET后SET”这类业务代码中两个操作之间被并发请求插队了。解决方案是用INCR本身而不是GETSET。分布式锁如何实现按我第6章的演进路线回答SETNXEXPIRE - SET EX NX - 加唯一标识Lua解锁 - Redisson看门狗续期 - 谈RedLock的局限性。9.2 实战自检清单每过一阶段自查一遍如果下面任何一项你回答不上来就说明对应的环节还没吃透回到对应章节再琢磨能在一分钟内用Docker起一个带密码的Redis实例吗能说清楚String、Hash、ZSet各自适合什么业务场景吗知道缓存击穿和缓存穿透的本质区别吗能画出来吗收到线上报警“Redis连接数暴涨”准备先执行哪三条命令排查能解释Redis主从复制全量同步和增量同步的触发条件吗知道Cluster模式为什么报了MOVED错误吗怎么处理能不能手写一个带过期时间、带唯一标识校验、用Lua解锁的分布式锁能解释RDB和AOF混合持久化的加载流程吗redis-benchmark测出来的QPS数据你知道怎么解读吗能说出INFO命令下至少5个关键指标的含义吗以上10条全部过关Redis这块的工程能力就算真正立住了。我见过不少五年经验的工程师Redis命令背得滚瓜烂熟但遇到线上缓存穿透照样手足无措原因就是只学了“怎么用”没学“什么时候用什么、为什么用”。这套学习路径是我反复验证过的照着走你踩过的坑会比我少很多。
返回列表