ARTICLE DETAIL

资讯详情

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

Redis命令详解:从底层数据结构到缓存、分布式锁实战指南

Redis命令详解:从底层数据结构到缓存、分布式锁实战指南 聊到 Redis很多人第一反应是“快”第二反应可能是“我只会 set 和 get”。说实话我见过不少同学用了一年 Redis翻来覆去还是那几个命令一旦遇到缓存穿透、分布式锁、批量处理这些场景就不知道该怎么用命令组合去解决只能去搜现成代码。这篇博文不打算做命令文档的搬运工而是把 Redis 的命令体系拆开揉碎从设计逻辑、底层数据结构、典型业务场景、踩坑经验几个维度来讲清楚每个命令到底该怎么用、为什么这么用、哪些参数是必须注意的。无论你是刚接触 Redis 的新手还是写了好几年业务的开发或者正在准备面试想突击一下命令细节这篇文章都值得仔细看一遍。我会尽量用实际场景来说话而不是干巴巴地列语法。比如同样的一个 INCR为什么在秒杀场景里用它就是对的在计数不准的场景里就得换方案这些光看官方文档是体会不到的。1. 命令体系整体拆解先搞懂 Redis 的“语言逻辑”1.1 为什么命令详解比背 API 更重要很多人学 Redis 命令是零散地记今天用到一个查一个明天又忘了。这是因为没有理解 Redis 命令背后的设计逻辑。Redis 本质上是一个基于内存的键值数据库它的命令体系围绕两个核心维度展开数据怎么存数据类型和数据怎么管生命周期、内存、持久化。命令不是孤立的 API它们是对底层数据结构的一种操作封装。比如 HSET 操作的是哈希表LPUSH 操作的是双向链表ZADD 操作的是跳表加哈希表的组合。你如果只看命令名称很难理解为什么 ZSET 可以同时支持“按分数查询”和“按成员查询”但一旦知道底层是“跳表 字典”的组合结构一切就顺理成章了。这也是为什么我建议所有做后端的人学命令的同时一定要补一下 Redis 的底层数据结构课。另外命令的使用方式直接决定了 Redis 的性能表现。同样是对一个 key 做写入SET 和 APPEND 的底层操作路径完全不同同样是删除一个大 keyDEL 会阻塞主线程UNLINK 却可以异步回收内存。这些差异只看文档是记不住的必须在理解底层逻辑之后才能形成肌肉记忆。1.2 命令分类的四个维度别再把所有命令混为一谈站在使用者的角度我习惯把 Redis 命令分成四类这个分类思路对学习和排查问题都很有帮助第一类是数据类型操作命令包括 String、Hash、List、Set、ZSet 这五种数据类型的增删改查。这是日常开发中用得最多的一类也是这篇文章重点拆解的部分。第二类是通用键命令比如 DEL、EXPIRE、TTL、EXISTS、TYPE、RENAME它们不区分数据类型作用于 key 本身。这类命令容易被忽略但恰恰是调优和排查问题的关键。第三类是事务与脚本命令包括 MULTI、EXEC、DISCARD、WATCH 以及 Lua 脚本相关命令。这类命令解决的是“多条命令组合操作的原子性”问题是分布式场景下非常关键的工具。第四类是运维管理命令比如 INFO、CONFIG GET/SET、SLOWLOG、CLIENT LIST、MONITOR、DBSIZE、FLUSHDB 等。这类命令通常由运维或资深开发使用用来观察 Redis 的运行状态、定位慢请求。分类的好处在于当你脑子里的命令是“分桶”的遇到问题时就能快速定位该用哪个桶里的工具。比如缓存不生效先查通用键命令里的 TTL 和 EXISTS确认 key 还在不在线上 CPU 飙升先查运维命令里的 INFO commandstats 和 SLOWLOG看是哪些命令在拖垮实例。而不是漫无目的地乱试。2. 核心命令深度剖析从场景与底层看真实用法2.1 String 命令不只是 SET 和 GET细节里藏着大坑String 是 Redis 最基础的数据类型底层是 SDS简单动态字符串支持字符串、整数、浮点数三种表现形式。日常用的最多的是 SET 和 GET但真正常用且容易出错的是那批带参数的扩展命令。先说 SET 的完整语法这一点必须记牢SET key value [NX | XX] [GET] [EX seconds | PX milliseconds | EXAT unix-time-seconds | PXAT unix-time-milliseconds | KEEPTTL]这里的 NX 表示只有当 key 不存在时才设置XX 表示只有 key 存在时才设置。这两个选项是后面讲分布式锁的基础也是很多人在命令行里手误用错的地方。我见过有人用SET key value NX EX 60实现分布式锁这里 NX 和 EX 是可以同时出现的Redis 2.6.12 以后支持这种组合写法这是官方推荐的原子性加锁方式。GETSET 这个命令现在很多人已经不用了但它在某些场景里依然好用比如要“取旧值并设置新值”时GETSET 可以一步完成省去一次网络往返。Redis 6.2 还新增了 GETDEL先取值再删除和 GETEX取值并同时设置过期时间这两个命令在处理一次性令牌、验证码场景时非常顺手。再说到 INCR、INCRBY、DECR、DECRBY这些命令是原子性的自增自减操作。很多人觉得它们只是“帮你在内存里做了个 1”其实关键在于原子性。在并发场景下如果先 GET 再 SET中间一定会有窗口期导致丢更新但 INCR 是在 Redis 服务端内部完成的单条命令天然串行不存在竞态问题。这也是秒杀库存扣减可以直接用 INCR 减库存的原因。但注意热词里有“redis incr不准”这通常不是 INCR 本身的问题而是使用姿势错了。常见错误包括没有设置过期时间导致 key 永久增长在集群模式下 key 分布不均匀导致单节点热点或者干脆是用 Lua 脚本里 GET 加 SET 的方式误以为原子但实际没加锁。INCR 的结果本身不会“不准”要排查的是业务逻辑中是否有多处写入源没有统一走 INCR。MSET 和 MGET 是批量版 SET 和 GET一次命令操作多个 key能显著减少网络往返。比如批量查用户的多个信息字段用 MGET 一次搞定比循环 GET 快得多。这里的坑是批量命令虽然能减少 RTT但在 Redis Cluster 集群模式下如果 key 不在同一个 slotMGET 就无法跨节点执行通常只能分段批量或者用 Hash Tag 把相关 key 放到同一个 slot。2.2 Hash 命令字段级操作在业务建模中的妙用Hash 类型底层有两种编码数据量少时用 ziplist紧凑列表数据量大时转为 hashtable。HSET、HGET、HDEL、HGETALL 是最基本的操作但在实际业务中我强烈建议掌握 HINCRBY 和 HSCAN。HINCRBY 可以对 Hash 中的某个字段做原子自增。这在统计场景中很常用比如要记录一个商品维度的多个计数浏览量、收藏量、加购量用 HSET 加 HINCRBY 组合就能在一个 key 里维护多个计数器避免每个计数器单独占用一个 key。相比 String 的 INCRHINCRBY 的粒度更细但代价是每次操作都多了一个字段维度底层对 ziplist 的读写略复杂。数据量小的时候无所谓一旦字段数量破了阈值性能会有一定波动。HGETALL 看起来方便一次取出所有字段和值。但它很容易被误用特别是哈希里字段很多的时候。HGETALL 是 O(N) 操作field 一多命令耗时线性上升在 QPS 高的场景下容易拖垮 Redis。官方也因此提供了 HSCAN 这类游标式遍历命令。HSCAN 的用法和后面要说的 SCAN 一样通过游标分批返回不阻塞主线程。Hash 还有一个经常被忽略的优点字段级过期控制是做不到的这是设计上需要注意的。如果你需要某个字段在指定时间后自动失效只能整体过期整个 Hash key或者用另一种方案——把字段设计成独立的 String key灵活但牺牲了聚合性。没有一种方案是完美的关键在于你的业务更看重聚合管理还是更看重粒度控制。2.3 List 命令队列场景的底层支撑与阻塞版本List 底层是双向链表quicklist 结构兼具栈和队列的特性。基础命令是 LPUSH、RPUSH、LPOP、RPOP、LRANGE、LINDEX、LLEN、LREM 等。其中 LPUSH 加 RPOP 组合就是一个标准的 FIFO 消息队列RPUSH 加 LPOP 也是一个队列只是方向反了。这里要特别说的是阻塞版本的 LPOPBLPOP 和 BRPOP。这两个命令是消息队列实现中不可或缺的利器。它们的作用是如果列表里没有元素客户端会阻塞等待直到有元素进来或者超时。可以指定多个 key 按顺序检查还可以设置超时时间0 表示永久阻塞。那为什么不用 LPOP 轮询因为轮询会频繁发起空查询白白消耗网络和 CPU延迟还高。BLPOP 把“等待”这件事下沉到了 Redis 端不占用业务线程实现更优雅。用BLPOP queue 5这样的命令如果 5 秒内没有消息返回 nil客户端可以做其他处理。这种方式比 sleep 加 LPOP 效率高一个数量级。项目中我还经常用 LRANGE 做分页读取比如查看一个任务队列的前 10 条记录。注意 LRANGE 的区间是闭区间LRANGE list 0 9取的是第一条到第十条。很多新手会写成LRANGE list 0 10结果多取了一条。LREM key count value 的参数 count 有正数、负数、0 三种含义正数表示从头部开始删除最多 count 个匹配项负数表示从尾部开始删除0 表示删除所有匹配项。这个细节面试中也经常被拿来当考点。2.4 Set 命令集合运算在标签、好友、推荐系统中的实战Set 底层是整数集合intset或哈希表hashtable特性是无序、元素唯一。基础命令 SADD、SREM、SISMEMBER、SMEMBERS、SCARD 比较简单真正有强大价值的是集合运算命令SINTER交集、SUNION并集、SDIFF差集。举个典型的业务场景一个 APP 要给用户推送个性化内容需要找到“用户 A 的好友集合”和“喜欢篮球的用户的集合”的交集用 SINTERSTORE 把结果缓存到一个临时 key再配合 EXPIRE 设置过期时间比在业务代码里做双重循环高效得多。又比如标签系统给一篇文章打标签集合给一个用户兴趣打标签集合SINTER 就能直接找到匹配的内容。SMEMBERS 和 HGETALL 类似是 O(N) 命令集合大了以后要改用 SSCAN 游标遍历避免阻塞。SISMEMBER 则是 O(1) 操作适合高并发场景下的存在性判断。SPOP 和 SRANDMEMBER 这两个命令容易被混淆。SPOP 是从集合中随机弹出一个或多个元素返回后就从集合中移除适合做抽奖、随机淘汰。SRANDMEMBER 是随机返回一个或多个元素但不会移除适合做随机推荐但保留候选池的场景。两者虽然只有一字之差语义完全不同用错会导致业务逻辑严重偏离预期。2.5 ZSet 命令排行榜与延迟队列的利器ZSet有序集合是 Redis 里最“高级”的数据类型底层用跳表skiplist加哈希表实现成员唯一但每个成员关联一个 double 类型的分数按分数排序存储。ZADD、ZSCORE、ZINCRBY、ZRANGE、ZREVRANGE、ZRANGEBYSCORE、ZRANK、ZREM 是高频命令。排行榜是最经典的场景。比如实时更新用户积分榜用 ZADD 或 ZINCRBY 维护一个 zset 类型的 key分数就是积分总值。查询 Top N 直接用ZREVRANGE key 0 N-1 WITHSCORES按分数从高到低取。如果要看某个用户的排名用 ZREVRANK。这些操作都是 O(log N) 级别性能完全不是问题。还有一个很多老手爱用的冷门场景延迟队列。利用 ZSet 的分数存到期时间戳写入任务时 ZADD key 时间戳 member后台轮询ZRANGEBYSCORE key 0 当前时间戳 LIMIT 0 1把到了执行时间的任务取出来处理处理完成后 ZREM 或者用 ZINCRBY 把时间戳往后推。这个方案简单有效而且天然支持按时间排序比用 List 的队列方案灵活得多。ZRANGE 的语法带 WITHSCORES 参数时才会返回分数不带则只返回成员。Redis 6.2 还新增了 ZRANGE 的 REV 参数和 BYSCORE 参数可以用来替代 ZREVRANGE 和 ZRANGEBYSCORE语法更统一。这些新的变化有时候官方文档更新的也不及时需要我们自己去翻 changelog。2.6 通用命令与过期机制EXPIRE、TTL、DEL 的时效性管理我把通用键命令单独拿出来讲因为它们太容易被忽略却又太重要了。EXPIRE 设置过期时间TTL 查看剩余存活时间PERSIST 取消过期DEL 删除 keyEXISTS 判断是否存在TYPE 查看类型RENAME 重命名。这套命令组合起来就是 Redis 的“生命周期管理”。先说 EXPIRE 的一个经典坑SET 一个已存在的 key默认会清除原来的过期时间。因为 SET 会创建新值之前的 TTL 会被重置。如果要保留原来的过期时间必须显式带 KEEPTTL 参数Redis 6.0 以上支持。这个坑我踩过不止一次线上缓存突然“过期时间丢了”十有八九是更新 value 的时候用了不带 KEEPTTL 的 SET。TTL 的返回值需要特别注意-1表示 key 存在但没有设置过期时间-2表示 key 不存在。很多人在业务代码里判断 TTL 返回值时只处理了负数没有区分 -1 和 -2导致逻辑判断错误。比如想“如果 key 快过期了就续期”不能简单判断ttl 10因为 ttl 为 -1 时也小于 10但 -1 表示没有过期时间不需要续期。DEL 是大家最常用但最容易对线上造成事故的命令。DEL 一个非常大的 key比如一个百万成员的 zset在 Redis 主线程里执行时会耗费大量时间清理内存对象直接阻塞其他命令的执行。Redis 4.0 之后提供了 UNLINK 命令功能和 DEL 一样但是异步删除主线程只负责把 key 从键空间摘除真正的内存回收交给后台线程慢慢做。所以删除大 key 时请务必用 UNLINK。3. 实操过程记录从零搭建一套可复用的 Redis 命令工作流3.1 安装、连接工具与可视化客户端的命令配合很多人装 Redis 的时候就卡在第一步。这里分享一个最省事的 macOS 安装方式直接brew install redis装完以后redis-server启动服务redis-cli -h 127.0.0.1 -p 6379进入命令行。Windows 上官方不提供原生支持比较顺手的方式是装 WSL 后在 Linux 子系统里操作或者用 Docker 起一个容器docker run -d --name redis -p 6379:6379 redis。无论哪种方式最终都要有一个能敲命令的 redis-cli 终端。可视化客户端方面我先后用过 Redis Desktop Manager 和 Another Redis Desktop Manager。前者早期免费后来收费后者是目前用得比较顺的开源替代品支持多平台、SSH 隧道、JSON 格式化显示非常适合日常查数据。但请记住可视化工具是查数据的不是压测的更不是执行的。真正常用的命令操作、批量修改我依然推荐在 redis-cli 里完成因为可控性最强每一步做了什么清清楚楚。连接上 redis-cli 之后第一件事建议执行INFO SERVER看版本执行INFO STATS看连接状况和命令执行情况。这两个命令是排查线上问题的基础入口。3.2 典型业务场景的命令组合实战下面我用三个高频率业务场景把上面拆解过的命令串起来给出一套可以直接“抄作业”的命令组合。场景一带过期时间且需要原子更新的用户会话信息用户登录后需要写入会话数据设置 30 分钟过期每次活跃时刷新过期时间但不想每次刷新都重写整个会话。命令组合如下# 写入会话30分钟过期 SET session:user:1001 {...} EX 1800 # 用户活跃时只续期但不修改值 EXPIRE session:user:1001 1800 # 如果要同时更新内容和续期必须注意保留过期时间 SET session:user:1001 {...new...} KEEPTTL第三个命令用KEEPTTL保留了原来的过期时间这是 Redis 6.0 才有的参数旧版本没有替代方案只能先拿到 TTL 再重新 SET中间会有窗口期这也是很多历史代码里隐藏的 bug。场景二排行榜实现游戏积分排行榜玩家每次完成一局游戏积分变动可能加分也可能扣分都要实时反映在榜上。命令组合# 玩家1001增加50分 ZINCRBY leaderboard:game:001 50 user:1001 # 玩家1002增加30分,玩家1003增加80分 ZADD leaderboard:game:001 30 user:1002 80 user:1003 # 查看前三名及分数 ZREVRANGE leaderboard:game:001 0 2 WITHSCORES # 查看玩家1001的当前排名从0开始所以第一名0 ZREVRANK leaderboard:game:001 user:1001这里有一点要注意玩家只玩过一局、没有积分时他根本不存在于 zset 里ZREVRANK会返回 nil。业务代码里要做空值处理别把 nil 当 0 直接塞进 int 类型。场景三简单的消息队列生产者把任务推入 list消费者用阻塞命令取任务取到后处理处理完还能用 LREM 做确认。命令组合# 生产者推送一条订单超时检查任务 RPUSH task:order:check order:10001 # 消费者阻塞等待任务最多等5秒 BLPOP task:order:check 5 # 取出的是一个数组[0]是key名[1]是value # 处理完后清理残留通常在代码中已完成不需要这一步3.3 命令速查表贴在办公桌上的一页纸这里送给读者一张速查表按数据类型分类覆盖最常用的命令及其关键参数。我自己一直用这张表新员工入职也会发一份。类型命令关键说明StringSET key value NX EX secondsNX EX 原子加锁最常用StringMSET k1 v1 k2 v2批量写减少 RTTStringINCR / INCRBY key num原子自增适合计数器、限流StringGETDEL / GETEX6.2 取旧值同时删/设过期HashHSET key field value字段级写入HashHINCRBY key field num字段级原子自增HashHSCAN key cursor大哈希游标遍历忌用 HGETALLListLPUSH / RPUSH / LPOP / RPOP栈与队列基础ListBLPOP / BRPOP key timeout阻塞弹出队列首选ListLRANGE key start stop闭区间分页读取SetSADD / SREM / SISMEMBER标签与存在性判断SetSINTER / SUNION / SDIFF交并差运算SetSPOP / SRANDMEMBER弹出 vs 随机取不会混用ZSetZADD key score member写排行榜ZSetZREVRANGE key start stop WITHSCORES高分到低分取 Top NZSetZINCRBY key num member积分变更通用EXPIRE / TTL / PERSIST生命周期三件套通用DEL / UNLINKDEL 阻塞UNLINK 异步管理INFO commandstats看各命令调用次数和耗时管理SLOWLOG GET 10慢日志排查性能瓶颈4. 常见问题与排查技巧实录4.1 分布式锁命令细节决定成败热词里有“redis分布式锁”这确实是从命令详解到工程实践最经典的跳板。如果你打算在项目里用 Redis 做分布式锁必须先搞清楚几个核心命令的语义。加锁的正确姿势是SET lock_key unique_value NX EX 30。NX 保证只有一个客户端能成功设置EX 30 保证即使处理意外崩溃锁也会在 30 秒后自动释放避免死锁。unique_value 是每个客户端的唯一标识比如 UUID这在释放锁时至关重要。释放锁的推荐姿势是用 Lua 脚本保证原子性先 GET 判断 unique_value 是否是自己持有的锁如果是再 DEL。为什么不能直接 DEL因为如果锁已经过期被别人抢到你直接 DEL 会把别人的锁释放掉。可以先 GET 再 DEL但两步操作有竞态窗口所以在 Redis 里必须用 Lua 脚本把这个判断和删除封装成原子操作。还有一个实际问题锁的过期时间设短了业务还没执行完锁就自动释放了设长了一旦持有锁的进程崩溃其他进程要等很久才能拿到锁。业界常用的方案是“自动续期”比如用 Redisson 的 watchdog在锁快过期时自动续期。手动实现也不难就是后台起一个定时线程每隔 10 秒执行一次EXPIRE lock_key 30前提是 GET 判断锁还属于自己。这个场景就把 EXPIRE 命令用得淋漓尽致了。4.2 缓存治理中的命令陷阱穿透、击穿、雪崩缓存治理这个话题很大但落到命令层面核心就三个怎么让不值得缓存的数据快速绕过、怎么让热点 key 不过期、怎么防止失效瞬间压垮数据库。缓存穿透的典型表现是查询一个不存在的 key每次都会落到数据库。命令行层面的对策有两个一是对空值也做缓存SET key 空值 EX 60把不存在的数据也短暂缓存起来二是用布隆过滤器但这个涉及额外的数据结构这里不展开。空值缓存要注意设置合理过期时间别缓存太久导致数据一直无法更新。缓存击穿是某个热点 key 过期瞬间大量并发查询同时穿透到数据库。命令层面的手段是“互斥重建”用SET lock:key unique_value NX EX 10抢锁抢到锁的请求重新加载数据写缓存抢不到的请求先返回旧值或稍等重试。这时候分布式锁的命令又重新用上了。缓存雪崩是大量 key 在同一时刻过期请求整体压向数据库。命令层面的预防手段很简单SET 时不设固定过期时间而是加一个随机偏移量EXPIRE key 3600 random(0,300)让过期时间错峰。另一个常用手法是用 KEEPTTL 机制在业务低峰期主动刷新 key。这些细节看似简单但能做到位的团队真的不多。4.3 O(N) 命令与阻塞命令别让一条命令毁了整个实例Redis 是单线程执行命令的所以任何 O(N) 命令都可能成为阻塞源头。我以前遇到过线上 redis-slowlog 里全是 SMEMBERS 和 HGETALL再一看这个 key 有几百万个元素业务侧还每秒调几次CPU 直接飙满。建议强制执行的规范有这几条生产环境严禁使用 KEYS 命令排查 key 用 SCAN严禁对超大集合执行 SMEMBERS 或 HGETALL改用 SSCAN 和 HSCAN大批量删除 key 时不要循环 DEL用 UNLINK 异步删除严禁在业务高峰期执行 FLUSHDB 或 FLUSHALL必须执行时用后台异步方式或者凌晨执行。热词里有一个“history命令详解”“linux screen命令详解”虽然它们是 Linux 命令但这里可以类比一下Redis 的 MONITOR 命令就像 Linux 的 history能把所有命令实时打印出来但同样很危险。MONITOR 开启期间 Redis 的吞吐量会大幅下降生产环境千万别开着 MONITOR 去排查问题那等于给自己制造故障。想检查实时命令用CLIENT LIST看连接数用INFO commandstats看命令分布比 MONITOR 安全得多。4.4 序列化、可视化管理与日志配合Redis 存中文或者对象的时候很多人会遇到“可视化管理工具里看到一堆转义字符”的问题。这不一定是 Redis 的错通常是序列化方式的问题。如果用的是 Java 的 JdkSerializationRedisSerializer看到的是\xAC\xED这种二进制乱码用 Jackson 序列化则是一串 JSON 字符串在可视化工具里能直接看懂。建议优先用 JSON 序列化配合 StringRedisTemplate方便排查问题排查速度本身就是生产力。热词里有“systemd 脚本命令 详解包含app的日志输出到终端”这个跟 Redis 命令关系不大但如果你想在服务器上跑 Redis 服务并想实时看到日志输出可以把 Redis 配置文件的 logfile 设成空字符串让日志输出到标准输出再交给 systemd 的 journald 管理。这样journalctl -u redis -f就能实时查看 Redis 运行日志比进容器看文件方便很多。另外配置文件中slowlog-log-slower-than 10000单位微秒可以设置慢日志阈值slowlog-max-len 128控制保存条数。线上排查命令性能问题时SLOWLOG GET 10出来的每条记录都包含执行时间、命令参数、客户端地址是定位问题最直接的证据。4.5 集群模式下命令使用的四个注意点Redis Cluster 环境下命令的使用有很多隐性约束不提前了解会在上线后踩坑。第一多 key 操作MGET、MSET、DEL 多个 key、事务要求 key 必须在同一个 slot否则命令报错。解决办法是用 Hash Tag比如{user:1001}.name和{user:1001}.age花括号内的部分参与哈希计算保证两个 key 落在同一个 slot。第二SCAN 在集群模式下可以在每个节点执行但结果需要客户端自行合并不存在全集群的全局游标。第三事务中的命令如果在执行时发现 key 不在当前节点会直接报错而不是重定向所以事务和 Lua 脚本在多 key 场景下要格外小心尽量把相关 key 聚合到同一个 slot。第四集群模式下分布式锁的语义需要重新考虑。如果在 Master 上获取了锁Master 还没同步到 Slave 就宕机了锁会丢失。这就要引入 RedLock 这样跨多个独立节点的方案或者接受小概率的锁丢失把业务做好幂等兜底。这些权衡思路不是背命令能得来的而是要理解 Redis 集群架构的复制模型和命令分发逻辑之后才能做出合理决策。总结我的个人体会最后说点掏心窝的话。Redis 命令看起来简单但真正拉开开发水平差距的往往就是这些细节。比如 EEXPIRE 与 SET 的过期时间覆盖问题、DEL 与 UNLINK 的阻塞差异、BLPOP 和轮询的效率鸿沟每一处都是血泪教训换来的。我写过很多年代码Redis 命令从没背过完整的文档而是把每个命令放到具体的业务场景里反复砸摸它为什么这么设计久而久之就有了肌肉记忆。如果你现在正准备面试不要只背命令的语法试着问自己三个问题这个命令的底层数据结构是什么这个命令在单线程模型下会不会阻塞这个命令在集群模式下有什么限制能把这三个问题答清楚Redis 命令这块基本就稳了。如果你已经在排查线上问题建议从 INFO commandstats、SLOWLOG 和 TTL 这三把钥匙入手大多数命令层面的问题都能顺着线索摸到根因。记住命令本身没有好坏用对场景才是王道。
返回列表