Redis核心数据结构与常用命令全解析:从入门到实战应用 📅 2026/8/8 9:03:31 1. Redis初印象为什么它成了“瑞士军刀”如果你刚接触后端开发或者系统架构听到“Redis”这个词的频率可能仅次于“MySQL”。但和关系型数据库那种规规矩矩的表结构不同Redis给人的第一感觉是“快”和“灵活”。你可以把它理解成一个超级高效、功能多样的“内存工作台”。所有数据主要放在内存里操作所以读写速度能达到微秒级比基于磁盘的数据库快几个数量级。但这不仅仅是快它的价值在于提供了丰富的数据结构比如字符串、列表、哈希、集合等让你能用更贴合业务逻辑的方式来存储和操作数据而不用像在关系型数据库里什么都得先拆成行和列。我刚开始用Redis时主要就拿它做缓存把一些查询耗时的结果比如用户信息、热门文章列表丢进去下次请求直接取数据库压力瞬间就下来了。但用着用着就发现它的能力远不止于此。比如用它的List做个简单的消息队列用Set做点赞去重用Sorted Set做实时排行榜用HyperLogLog估算UV独立访客数…… 它就像一把“瑞士军刀”在需要高性能、实时性的场景里总能找到趁手的工具。而熟练使用这些工具的第一步就是掌握它的基本命令。这不仅仅是记住几个单词更是理解其设计哲学和适用场景避免“拿着锤子看什么都像钉子”。2. 环境准备与连接迈出第一步在开始敲命令之前我们得先有个Redis服务可以操作。虽然生产环境通常是独立的服务器但本地学习和测试最方便的就是自己安装一个。2.1 快速搭建Redis测试环境对于大多数开发者我推荐直接用Docker来跑Redis干净又省事不用担心污染本地环境。如果你还没安装Docker去官网下载安装就好这里假设你已经有了。打开终端一行命令就能拉起一个最新版的Redis服务docker run -d --name my-redis -p 6379:6379 redis:latest这条命令做了几件事-d表示后台运行--name my-redis给容器起个名字方便管理-p 6379:6379把容器内的Redis默认端口6379映射到本机的6379端口最后指定使用redis:latest镜像。启动后你可以用下面命令进入容器内的Redis命令行界面CLIdocker exec -it my-redis redis-cli看到127.0.0.1:6379这个提示符就说明你已经成功连接上Redis服务了。这是我们的主战场。注意生产环境绝不会这么简单。你需要配置密码通过requirepass、考虑持久化方案RDB/AOF、设置内存上限maxmemory和淘汰策略maxmemory-policy可能还需要搭建主从复制或集群。但对于学习和命令练习这个单机无认证的实例足够了。2.2 命令行客户端redis-cli的基本操作连接上之后我们先熟悉一下这个命令行环境。它支持一些基本的交互操作ping测试服务是否存活。服务器会回复PONG。select db_index切换数据库。Redis默认有16个数据库编号0-15默认使用0号库。这个功能现在不太推荐了因为容易混淆更好的实践是用不同的Key前缀来区分业务。auth password如果服务端配置了密码需要用这个命令认证。quit或exit退出CLI。一个常见的检查流程是连上后先ping一下确保连接通畅。3. 核心数据结构与命令全解析Redis的强大根基在于其五种核心数据结构。理解它们是灵活运用Redis的关键。我们一个一个来看并配上最常用的命令。3.1 String字符串最简单的键值对String是Redis最基本的数据类型一个Key对应一个Value。但这个Value不仅是文本也可以是数字整数或浮点数甚至是二进制数据如图片序列化后的字节流。常用命令SET key value设置键值对。例如SET user:1001:name “张三”。GET key获取键对应的值。例如GET user:1001:name。DEL key删除键。例如DEL user:1001:name。INCR key/DECR key将键存储的整数值加一/减一。常用于计数器如INCR article:100:view_count。INCRBY key increment/DECRBY key decrement按指定步长增减。例如INCRBY inventory:item_001 5。SETEX key seconds value设置键值对并指定过期时间秒。这是实现缓存最常用的命令之一比如SETEX session:abc123 3600 “{userId: 1001}”表示这个会话数据1小时后自动消失。MSET key1 value1 key2 value2 .../MGET key1 key2 ...批量设置/获取多个键值能有效减少网络往返开销提升性能。实操心得Key的设计艺术好的Key名是自描述的。我习惯用冒号分隔形成一种伪命名空间比如业务:对象:ID:属性user:1001:profile。这比无规律的字符串清晰得多也方便用KEYS或SCAN命令按模式查找尽管生产环境慎用KEYS。数字的妙用INCR命令是原子性的这意味着即使多个客户端同时对一个Key执行INCR也不会出现竞争条件导致计数错误。这让它成为实现分布式系统里全局计数器的完美选择。SETEX是缓存标配一定要为缓存数据设置合理的过期时间这既是内存管理的要求也能保证数据的最终时效性避免脏数据一直留存。3.2 Hash哈希表存储对象Hash适合存储对象比如用户信息、商品信息。它可以将一个对象的多个字段和值存储在一个Redis键下类似于编程语言里的Map或dict。常用命令HSET key field value设置哈希表中字段的值。例如HSET user:1001 name “张三” age 30。HGET key field获取哈希表中指定字段的值。例如HGET user:1001 name。HGETALL key获取哈希表中所有字段和值。它会以交替的字段名、值的形式返回。HDEL key field1 field2 ...删除哈希表中的一个或多个字段。HINCRBY key field increment为哈希表中的整数字段值增加指定步长。例如HINCRBY user:1001 score 10。实操心得与String的取舍是把一个用户对象序列化成JSON字符串用SET存还是用Hash分字段存我的经验是如果需要频繁更新对象的部分字段或者需要单独访问某些字段Hash更高效因为它可以独立操作每个字段不用像String那样每次都要序列化/反序列化整个对象。但如果对象字段很少或者总是整体存取那么用String序列化可能更简单。HGETALL的陷阱HGETALL会返回哈希的所有内容。如果这个Hash非常大字段成千上万这个操作可能会阻塞Redis较长时间并消耗大量网络带宽。在生产环境中对于大的Hash更推荐使用HSCAN命令进行增量迭代或者明确使用HMGET获取你真正需要的几个字段。3.3 List列表有序的元素集合List是一个按照插入顺序排序的字符串元素列表。你可以从左侧头部或右侧尾部添加、弹出元素实现栈后进先出或队列先进先出的功能。常用命令LPUSH key value1 value2 .../RPUSH key value1 value2 ...将一个或多个值插入列表的头部左边/尾部右边。LPOP key/RPOP key移除并返回列表的头部/尾部元素。LRANGE key start stop获取列表中指定范围内的元素。0 -1表示获取所有元素。LLEN key获取列表长度。BLPOP key1 key2 ... timeout/BRPOP ...阻塞式弹出。如果列表为空命令会阻塞连接直到等待超时timeout秒或有其他客户端向列表插入元素为止。这是实现简单消息队列的核心。实操心得实现消息队列生产者用LPUSH向列表如task_queue尾部添加任务消费者用BRPOP从列表头部阻塞获取任务。这种方式简单可靠但注意它没有ACK确认机制消息被弹出就没了适合允许少量丢失的场景。最新N条记录用LPUSH加入新元素然后用LTRIM key 0 N-1来修剪列表只保留最新的N个元素。这常用于实现“最近访问记录”、“最新评论”等功能。性能注意List的底层实现是“快速列表”quicklist在元素不多时表现很好。但要注意LRANGE一个非常大的列表比如获取全部同样有性能风险。3.4 Set集合无序且唯一Set是一个无序的字符串集合其特点是元素不重复。它支持交集、并集、差集等集合运算功能非常强大。常用命令SADD key member1 member2 ...向集合添加一个或多个成员。SREM key member1 member2 ...移除集合中一个或多个成员。SMEMBERS key返回集合中的所有成员。SISMEMBER key member判断成员是否在集合中。SINTER key1 key2 ...返回多个集合的交集。SUNION key1 key2 ...返回多个集合的并集。SDIFF key1 key2 ...返回第一个集合与其他集合的差集。实操心得去重与判存这是Set最直观的用途。比如存储文章的所有点赞用户IDSADD article:100:likes user:1 user:2可以天然保证同一个用户不会重复点赞。用SISMEMBER可以快速检查某个用户是否点过赞。标签系统为每篇文章存储一个标签集合SADD article:100:tags tech database同时为每个标签存储一个包含文章ID的集合SADD tag:tech:articles 100。这样要找带有“tech”和“database”两个标签的文章只需对两个标签的文章ID集合求交集SINTER tag:tech:articles tag:database:articles效率极高。共同关注在社交网络中计算两个用户的共同关注就是对他们“关注的人”集合求交集。SMEMBERS的警告和HGETALL类似SMEMBERS也会一次性返回所有成员。对于大集合请使用SSCAN命令进行迭代。3.5 Sorted Set有序集合带权重的SetSorted Set在Set的基础上为每个元素关联了一个分数score元素根据分数从小到大排序。分数可以重复但元素member不能重复。常用命令ZADD key score1 member1 score2 member2 ...向有序集合添加一个或多个成员或者更新已存在成员的分数。ZRANGE key start stop [WITHSCORES]按分数从低到高返回指定排名区间的成员。WITHSCORES选项会同时返回分数。ZREVRANGE key start stop [WITHSCORES]按分数从高到低返回指定排名区间的成员。ZRANK key member/ZREVRANK key member返回成员在集合中的正序/逆序排名从0开始。ZSCORE key member返回成员的分数。ZINCRBY key increment member为成员的分数增加指定值。ZRANGEBYSCORE key min max [WITHSCORES]返回分数在指定区间内的成员。实操心得排行榜的天然实现这是Sorted Set的杀手级应用。比如游戏玩家得分榜ZADD leaderboard 2500 “player:A” 1800 “player:B”。要取前三名ZREVRANGE leaderboard 0 2 WITHSCORES。要更新玩家分数ZINCRBY leaderboard 100 “player:A”。所有操作都是原子且高效的。时间轴将时间戳作为分数事件内容作为成员可以构建一个按时间排序的事件流或消息时间线。范围查询ZRANGEBYSCORE可以用来做范围筛选比如查找分数在80到90之间的所有学生。分数设计分数是双精度浮点数可以表示整数、小数甚至是负数和很大的数。在设计排行榜时如果需要“分数相同按时间先后排”一个常见的技巧是把实际分数乘以一个很大数如1e10再加上一个由时间戳转换的递减序列号组合成一个新的分数。4. 键管理、生存时间与持久化窥探掌握了核心数据结构的操作我们还需要一些全局性的命令来管理这些键以及理解Redis如何管理数据生命周期。4.1 键的通用操作KEYS pattern查找所有符合给定模式pattern的键。例如KEYS user:*查找所有以user:开头的键。严重警告KEYS命令在生产环境必须禁用或极其谨慎使用因为它会遍历数据库中的所有键在键数量巨大时会导致Redis服务短暂阻塞卡住。替代方案是使用SCAN命令它以游标方式增量迭代不会阻塞服务。SCAN cursor [MATCH pattern] [COUNT count]安全地迭代数据库中的键。cursor是迭代游标从0开始一次调用返回下一个游标和部分键。当返回的游标为0时迭代结束。EXISTS key检查键是否存在。TYPE key返回键所存储的值的类型。RENAME key newkey重命名键。DEL key1 key2 ...删除一个或多个键。UNLINK key1 key2 ...异步删除键Redis 4.0。它与DEL不同它会在后台线程中回收内存对于删除大键不会阻塞主线程更友好。4.2 生存时间TTL与过期Redis可以为任何键设置生存时间到期后键会自动被删除。这是实现缓存、验证码过期、限时活动等功能的基础。EXPIRE key seconds为键设置过期时间单位秒。PEXPIRE key milliseconds为键设置过期时间单位毫秒。TTL key以秒为单位返回键的剩余生存时间。返回-2表示键不存在-1表示键存在但没有设置过期时间。PTTL key以毫秒为单位返回键的剩余生存时间。PERSIST key移除键的过期时间使其永久有效。实操心得过期删除策略Redis采用“惰性删除”“定期删除”两种策略。惰性删除指在访问一个键时检查它是否过期如果过期就删除。定期删除是Redis每隔一段时间随机检查一批键并删除过期的。这意味着一个键即使到了过期时间也可能不会立刻被删除直到它被再次访问或轮到定期检查时才会被清理。这在大多数场景下没问题但如果你对过期时间的精确性有严格要求比如秒杀库存就需要在业务逻辑上做额外保障。SETEXvsSETEXPIRESETEX是原子操作而先SET再EXPIRE是两个命令中间可能发生故障导致键没有设置过期时间。在需要保证一致性的场景优先使用SETEX或SET命令的EX选项如SET key value EX 60。4.3 持久化相关命令浅析虽然持久化配置主要在服务端redis.conf但了解相关命令有助于排查问题。SAVE同步保存数据到磁盘RDB文件。这会阻塞所有客户端请求直到保存完成。生产环境几乎不用。BGSAVE后台异步保存数据到磁盘。Redis会fork一个子进程来执行保存操作主进程继续服务客户端。这是常用的手动触发RDB快照的方式。LASTSAVE返回最近一次成功将数据保存到磁盘的Unix时间戳。可以用来检查后台保存是否成功。INFO persistence这个命令可以查看详细的持久化相关信息如RDB/AOF的状态、上次保存时间、重写情况等是监控Redis健康状态的重要信息来源。5. 事务与管道提升效率与保证批次操作5.1 事务Multi/ExecRedis的事务和关系型数据库的ACID事务不太一样。它更像一个命令的打包批处理用MULTI开启一个事务之后输入的命令都会被放入队列最后用EXEC一次性原子性地执行队列中的所有命令。MULTI SET balance:alice 100 DECRBY balance:alice 20 INCRBY balance:bob 20 EXEC重要特性与陷阱原子性EXEC执行时队列中的命令会作为一个整体、按顺序执行不会被其他客户端的命令打断。这保证了批次操作的原子性。没有回滚Rollback这是Redis事务最特别的一点。如果在EXEC执行前用DISCARD可以取消事务。但如果在EXEC执行过程中某条命令失败了比如对字符串执行了HINCRBYRedis不会回滚之前已执行的命令而是会继续执行队列中的剩余命令。开发者需要自己确保入队的命令语法正确、类型匹配。乐观锁WatchWATCH命令可以实现CASCheck-And-Set操作。它用于监视一个或多个键如果在EXEC执行前这些被监视的键被其他客户端修改了那么整个事务将会失败EXEC返回nil。这可以用来实现简单的乐观锁控制。5.2 管道Pipeline管道是另一种提升性能的技术。它的原理是将多个命令打包一次性发送给Redis服务器然后再一次性读取所有回复。这极大地减少了网络往返时间RTT的开销。在没有管道的情况下执行N条命令需要N次网络往返。使用管道后理论上只需要1次网络往返发送一批命令 接收一批回复。如何使用管道在编程中几乎所有Redis客户端库都支持管道。在命令行中你可以通过将命令写入文件然后用管道符重定向来模拟(echo -en “PING\r\nSET key1 hello\r\nGET key1\r\n”; sleep 1) | nc localhost 6379或者更简单地在redis-cli中使用--pipe选项。管道 vs 事务目的不同管道主要为了提升性能减少RTT事务主要为了保证批次操作的原子性不被其他命令打断。可以结合你可以在MULTI…EXEC事务块中使用管道这样既保证了原子性又提升了网络效率。实操心得对于需要连续执行多个不相关命令的场景比如初始化一批数据优先使用管道性能提升立竿见影。对于需要保证“要么全做要么全不做”的关联操作比如转账使用事务MULTI/EXEC并结合WATCH来防止竞态条件。管道打包的命令数量也不是越多越好因为服务器需要一次性为所有命令分配输出缓冲区。通常一个管道包含几百到几千个命令是比较合适的。6. 运维与调试常用命令实录当你把Redis用起来之后总会遇到需要查看状态、排查问题的时候。下面这些命令就是你的“手术刀”。6.1 信息获取与监控INFO [section]这是最强大的诊断命令。不加参数会返回所有信息内容非常多。通常按模块查看INFO server服务器基本信息版本、运行时间、进程ID等。INFO clients客户端连接信息。INFO memory内存使用详情包括总内存、使用峰值、碎片率等是排查内存问题的关键。INFO stats一般统计信息命令处理数、连接数、网络流量等。INFO replication主从复制信息。INFO cpuCPU消耗统计。CLIENT LIST列出所有连接到服务器的客户端详细信息包括连接ID、地址、空闲时间、正在执行的命令等。可以用来排查异常连接或找出执行慢查询的客户端。SLOWLOG GET [n]获取慢查询日志。Redis可以记录执行时间超过指定阈值slowlog-log-slower-than配置的命令。这个命令对于发现性能瓶颈至关重要。MONITOR这是一个调试命令它会实时打印出服务器接收到的所有命令。警告在生产环境运行MONITOR会严重降低性能因为它会输出大量信息只应在绝对必要时临时使用。6.2 连接与配置管理CLIENT SETNAME connection-name为当前连接设置一个名字方便在CLIENT LIST中识别。CONFIG GET parameter获取运行时的配置参数。例如CONFIG GET maxmemory。CONFIG SET parameter value动态修改运行时的配置参数。例如CONFIG SET maxmemory 2gb。注意不是所有参数都能动态修改且CONFIG SET的修改在重启后会失效永久修改需要改redis.conf文件。CONFIG REWRITE将当前通过CONFIG SET设置的配置持久化到redis.conf文件中。6.3 数据备份与迁移BGSAVE如前所述手动触发RDB持久化生成数据快照文件通常是dump.rdb。这个文件可以用于备份、迁移或复制。在命令行中直接复制RDB文件或AOF文件是最简单的冷备份方式。迁移时在新服务器上启动Redis并加载这些文件即可。7. 常见问题与排查技巧实录在实际使用中你肯定会遇到各种“坑”。下面是我总结的一些典型问题和解决方法。7.1 内存使用异常高问题现象INFO memory显示used_memory接近或超过maxmemory但实际业务数据量感觉没这么大。排查思路检查数据是否真的多用INFO keyspace看看各个数据库的键数量。也可以用SCAN粗略估算。检查是否有大Key使用redis-cli --bigkeys命令或编写脚本用SCAN配合TYPE、MEMORY USAGE命令扫描找出占用内存过大的Key。大Key如一个Hash有百万字段或一个String有几十MB不仅占用内存在删除、过期时也会引起阻塞。检查内存碎片率INFO memory中的mem_fragmentation_ratio碎片率。如果这个值远大于1.5比如超过2说明内存碎片比较严重。可以尝试重启Redis实例如果允许来回收碎片或者使用Redis 4.0的MEMORY PURGE命令如果支持。检查客户端输出缓冲区某些连接如长时间订阅Pub/Sub或Monitor可能导致输出缓冲区积压大量数据占用内存。用CLIENT LIST查看omem输出缓冲区内存字段。检查过期键清理大量已过期的键如果未被及时清理也会占用内存。可以手动执行DEBUG OBJECT key查看某个键的serializedlength或观察INFO stats中的expired_keys和evicted_keys数量。7.2 响应变慢问题现象客户端请求延迟明显增加。排查思路检查慢查询立刻执行SLOWLOG GET 10查看最近10条慢查询命令。分析是哪些命令慢是否使用了KEYS、HGETALL、SMEMBERS对大集合等危险命令或者是否是对大Key的操作。检查持久化影响如果正在生成RDB快照BGSAVE或重写AOF文件BGREWRITEAOF尤其是内存很大时fork子进程的过程可能会导致主进程短暂阻塞与内存量和系统有关。观察INFO persistence中的rdb_bgsave_in_progress和aof_rewrite_in_progress。检查网络和系统使用top、iostat等系统命令检查服务器CPU、内存、磁盘I/O是否饱和。网络是否拥堵。检查连接数INFO clients中的connected_clients是否过多连接数过多会消耗资源。检查CLIENT LIST中是否有空闲时间idle很长的连接考虑设置timeout配置让Redis自动关闭空闲连接。7.3 键丢失或数据不一致问题现象明明设置了键过一会儿就没了或者值不对。排查思路确认过期时间TTL用TTL key检查键是否设置了较短的过期时间。检查内存淘汰策略当内存达到maxmemory时Redis会根据maxmemory-policy如allkeys-lru,volatile-lru淘汰一些键。用INFO stats查看evicted_keys计数是否在增长。确保你理解的淘汰策略和配置一致。主从复制延迟如果使用了主从架构从库的数据可能会有延迟。在从库上读取的数据可能是旧的。检查INFO replication中的master_repl_offset和slave_repl_offset的差距。事务使用不当回顾事务部分确认是否因为事务中某条命令失败但其他命令执行了导致部分数据被修改。应用程序逻辑错误这是最常见的原因。检查代码中是否有覆盖写、条件判断错误等逻辑Bug。可以使用MONITOR命令在测试环境跟踪一段时间内对特定Key的所有操作。7.4 连接失败或超时问题现象客户端无法连接到Redis或连接频繁断开。排查思路检查基础网络ping服务器IP/端口用telnet或nc测试6379端口是否通畅。检查Redis配置bind是否绑定了正确的IP地址默认127.0.0.1只允许本地连接。protected-mode如果是非本地连接且未配置密码保护模式会拒绝连接。requirepass是否配置了密码客户端连接时是否提供了正确的AUTH。maxclients是否达到了最大连接数上限。检查系统限制服务器的防火墙如iptables, firewalld是否放行了6379端口。操作系统的最大文件描述符限制是否够用ulimit -n。检查客户端配置客户端的连接池配置、超时时间设置是否合理。不合理的超时设置可能导致连接被服务端主动关闭timeout配置。掌握这些基本命令和排查思路你就能应对Redis日常使用中80%以上的场景和问题。记住命令是工具理解其背后的数据结构和设计思想才能让你在合适的场景选择最合适的工具真正发挥出Redis这把“瑞士军刀”的威力。