Redis 各类数据结构指令详解
Redis 是一个开源(BSD 许可)的内存数据结构存储,可用作数据库、缓存和消息代理。它支持多种类型的数据结构,如字符串(strings)、哈希(hashes)、列表(lists)、集合(sets)、有序集合(sorted sets)等。理解并熟练使用这些数据结构及其相关指令,是高效利用 Redis 的关键。
Redis 的强大之处在于其在内存中操作这些丰富的数据结构,使得读写速度极快。掌握每个数据结构的使用场景和对应指令,是进行高性能应用开发的基础。
一、通用键指令 (Generic Commands)
这些指令适用于所有数据类型的键。
| 指令 | 描述 | 示例 |
|---|---|---|
DEL key [key ...] |
删除一个或多个键。 | DEL mykey mylist |
EXISTS key [key ...] |
检查给定键是否存在。返回存在的键的数量。 | EXISTS mykey |
EXPIRE key seconds |
设置键的过期时间(秒)。 | EXPIRE mykey 60 (60秒后过期) |
TTL key |
获取键的剩余过期时间(秒)。-1 表示永久,-2 表示键不存在或已过期。 |
TTL mykey |
PERSIST key |
移除键的过期时间,使其变为永久。 | PERSIST mykey |
TYPE key |
返回键存储值的类型。 | TYPE mykey (可能返回 string, list 等) |
KEYS pattern |
查找所有符合给定模式的键。应避免在生产环境中使用,会阻塞 Redis。 | KEYS user:* |
RENAME key newkey |
重命名键。 | RENAME oldkey newkey |
SCAN cursor [MATCH pattern] [COUNT count] |
用于迭代数据库中的键,避免 KEYS 的问题。 |
SCAN 0 MATCH user:* COUNT 100 |
二、字符串 (Strings)
Redis 最基本的数据类型,可以存储文本、整数、浮点数,甚至是二进制数据。最大能存储 512MB。
| 指令 | 描述 | 示例 |
|---|---|---|
SET key value [EX seconds] [PX milliseconds] [NX|XX] |
设置键值对。EX:过期秒数, PX:过期毫秒数, NX:键不存在才设置, XX:键存在才设置。 |
SET mykey "hello"SET mykey "world" EX 10SET mykey "new" NX |
GET key |
获取键的值。 | GET mykey |
MSET key value [key value ...] |
同时设置多个键值对。 | MSET key1 v1 key2 v2 |
MGET key [key ...] |
同时获取多个键的值。 | MGET key1 key2 |
INCR key |
将键存储的整数值加 1。如果键不存在,则初始化为 0 后再加 1。 | INCR counter |
DECR key |
将键存储的整数值减 1。 | DECR counter |
INCRBY key increment |
将键存储的整数值增加指定量。 | INCRBY counter 10 |
DECRBY key decrement |
将键存储的整数值减少指定量。 | DECRBY counter 5 |
GETSET key value |
设置键的新值并返回旧值。 | GETSET mykey "new_value" |
APPEND key value |
将值追加到键的末尾。如果键不存在,则创建键并设置值。 | APPEND mykey " world" (mykey 的值变为 hello world) |
GETRANGE key start end |
获取字符串的子字符串。 | GETRANGE mykey 0 4 (返回 hello) |
SETEX key seconds value |
设置键值对并指定过期时间(秒)。 | SETEX mykey 60 "value" |
场景示例: 用户会话存储、计数器、短 URL 映射。
三、哈希 (Hashes)
哈希是字段(field)和值(value)的映射表,非常适合存储对象。一个哈希可以存储多个字段-值对。
| 指令 | 描述 | 示例 |
|---|---|---|
HSET key field value [field value ...] |
设置哈希中一个或多个字段的值。 | HSET user:1 name "Alice" age 30 city "New York" |
HGET key field |
获取哈希中指定字段的值。 | HGET user:1 name |
HMSET key field value [field value ...] |
同时设置多个字段的值。(已被 HSET 替代,但仍兼容) |
HMSET user:2 name "Bob" age 25 |
HMGET key field [field ...] |
同时获取多个字段的值。 | HMGET user:1 name city |
HGETALL key |
获取哈希中所有字段和值。 | HGETALL user:1 |
HDEL key field [field ...] |
删除哈希中一个或多个字段。 | HDEL user:1 age |
HLEN key |
获取哈希中字段的数量。 | HLEN user:1 |
HEXISTS key field |
检查哈希中是否存在指定字段。 | HEXISTS user:1 name |
HKEYS key |
获取哈希中所有字段名。 | HKEYS user:1 |
HVALS key |
获取哈希中所有字段值。 | HVALS user:1 |
HINCRBY key field increment |
将哈希中指定字段的值增加指定量。字段值必须是整数。 | HINCRBY user:1 visits 1 |
HINCRBYFLOAT key field increment |
将哈希中指定字段的浮点数值增加指定量。 | HINCRBYFLOAT product:1 price 1.5 |
HSETNX key field value |
只有当字段不存在时,才设置哈希中字段的值。 | HSETNX user:1 email "alice@example.com" (如果 email 字段已存在,则不会更新) |
场景示例: 存储用户对象信息、商品详情、配置设置。
四、列表 (Lists)
列表是值的有序集合。你可以向列表的两端(左侧或右侧)添加元素。
| 指令 | 描述 | 示例 |
|---|---|---|
LPUSH key value [value ...] |
将一个或多个值插入到列表的头部(左侧)。 | LPUSH mylist "apple" "banana" (列表: banana, apple) |
RPUSH key value [value ...] |
将一个或多个值插入到列表的尾部(右侧)。 | RPUSH mylist "cherry" (列表: banana, apple, cherry) |
LPOP key |
移除并返回列表的头部元素。 | LPOP mylist (返回 banana, 列表: apple, cherry) |
RPOP key |
移除并返回列表的尾部元素。 | RPOP mylist (返回 cherry, 列表: apple) |
LRANGE key start stop |
返回列表中指定范围内的元素。0 表示第一个元素,-1 表示最后一个元素。 |
LRANGE mylist 0 -1 (返回所有)LRANGE mylist 0 0 (返回第一个) |
LLEN key |
获取列表的长度。 | LLEN mylist |
LINDEX key index |
通过索引获取列表中的元素。 | LINDEX mylist 0 |
LREM key count value |
从列表中移除与指定值相等的元素。count > 0: 从头开始移除 count 个。count < 0: 从尾开始移除 ` |
count |
LINSERT key BEFORE|AFTER pivot value |
在 pivot 元素之前或之后插入值。 |
LINSERT mylist BEFORE "apple" "pear" (列表: banana, pear, apple, cherry) |
TRIM key start stop |
将列表修剪到指定范围,保留范围内的元素,移除范围外的元素。通常用于实现固定长度列表。 | LTRIM mylist 0 99 (只保留最新的100个元素) |
BLPOP key [key ...] timeout |
阻塞式左弹出。如果列表为空,则阻塞直到有元素可弹出或超时。 timeout 为 0 表示永远阻塞。 | BLPOP queue1 queue2 0 |
BRPOP key [key ...] timeout |
阻塞式右弹出。 | BRPOP queue1 5 (阻塞最多 5 秒) |
场景示例: 消息队列、最新文章列表、关注者时间线、任务队列。
五、集合 (Sets)
集合是无序的、不重复的字符串元素集合。
| 指令 | 描述 | 示例 |
|---|---|---|
SADD key member [member ...] |
将一个或多个成员添加到集合。如果成员已存在,则忽略。 | SADD myset "apple" "banana" |
SMEMBERS key |
返回集合中的所有成员。 | SMEMBERS myset (返回 apple, banana,顺序不确定) |
SISMEMBER key member |
判断成员是否是集合的成员。 | SISMEMBER myset "apple" (返回 1) |
SCARD key |
获取集合的成员数量。 | SCARD myset |
SREM key member [member ...] |
从集合中移除一个或多个成员。 | SREM myset "banana" |
SPOP key [count] |
随机移除并返回集合中的一个或多个成员。 | SPOP myset |
SRANDMEMBER key [count] |
随机返回集合中的一个或多个成员,但不移除。 | SRANDMEMBER myset 2 (随机返回两个成员) |
SINTER key [key ...] |
返回所有给定集合的交集。 | SADD set1 a b cSADD set2 b c dSINTER set1 set2 (返回 b, c) |
SUNION key [key ...] |
返回所有给定集合的并集。 | SUNION set1 set2 (返回 a, b, c, d) |
SDIFF key [key ...] |
返回第一个集合与所有其他集合的差集。 | SDIFF set1 set2 (返回 a) |
SINTERSTORE destination key [key ...] |
将交集结果存储到目标集合。 | SINTERSTORE common_elements set1 set2 |
SUNIONSTORE destination key [key ...] |
将并集结果存储到目标集合。 | SUNIONSTORE all_elements set1 set2 |
SDIFFSTORE destination key [key ...] |
将差集结果存储到目标集合。 | SDIFFSTORE unique_to_set1 set1 set2 |
场景示例: 标签系统、共同关注、抽奖程序、用户权限管理(例如,一个用户属于哪些角色)。
六、有序集合 (Sorted Sets / ZSETS)
有序集合是集合的变种,每个成员都关联一个分数(score),集合中的成员是唯一的,但分数可以重复。元素按照分数从小到大排序。分数相同的元素,再根据成员的字典序排序。
| 指令 | 描述 | 示例 |
|---|---|---|
ZADD key [NX|XX] [GT|LT] [CH] [INCR] score member [score member ...] |
将分数和成员添加到有序集合。NX: 成员不存在才添加, XX: 成员存在才更新, CH: 改变计数, INCR: 分数递增。 |
ZADD myzset 1 "one"ZADD myzset 2 "two" 3 "three"ZADD myzset INCR 1 "one" (将 “one” 的分数加 1) |
ZRANGE key start stop [WITHSCORES] |
返回有序集合中指定排名范围内的成员。0 是第一个元素,-1 是最后一个元素。WITHSCORES 返回分数。 |
ZRANGE myzset 0 -1 WITHSCORES |
ZREM key member [member ...] |
从有序集合中移除一个或多个成员。 | ZREM myzset "one" |
ZCARD key |
获取有序集合的成员数量。 | ZCARD myzset |
ZSCORE key member |
获取有序集合中指定成员的分数。 | ZSCORE myzset "two" |
ZRANK key member |
返回有序集合中指定成员的排名(分数从小到大排,排名从 0 开始)。 | ZRANK myzset "two" |
ZREVRANK key member |
返回有序集合中指定成员的逆序排名(分数从大到小排,排名从 0 开始)。 | ZREVRANK myzset "two" |
ZRANGEBYSCORE key min max [WITHSCORES] [LIMIT offset count] |
返回有序集合中指定分数范围内的成员。min 和 max 可以是 -inf (负无穷大) 或 +inf (正无穷大)。 |
ZRANGEBYSCORE myzset -inf 2 WITHSCORESZRANGEBYSCORE myzset (1 3 (排除分数 1 和 3)ZRANGEBYSCORE myzset 1 3 LIMIT 0 1 |
ZCOUNT key min max |
返回有序集合中指定分数范围内的成员数量。 | ZCOUNT myzset 1 3 |
ZINCRBY key increment member |
对有序集合中指定成员的分数进行增量操作。 | ZINCRBY myzset 1 "one" |
ZREMRANGEBYRANK key start stop |
移除有序集合中指定排名范围内的所有成员。 | ZREMRANGEBYRANK myzset 0 99 (移除排名前 100 的成员) |
ZREMRANGEBYSCORE key min max |
移除有序集合中指定分数范围内的所有成员。 | ZREMRANGEBYSCORE myzset baits 100 200 |
ZUNIONSTORE destination numkeys key [key ...] [WEIGHTS weight [weight ...]] [AGGREGATE SUM|MIN|MAX] |
计算给定多个有序集合的并集,并将结果存储到目标有序集合中。可指定权重和聚合方式。 | ZADD zset1 1 "a" 2 "b" ZADD zset2 3 "a" 4 "c"ZUNIONSTORE zunion 2 zset1 zset2 AGGREGATE MAX (a:3, b:2, c:4) |
ZINTERSTORE destination numkeys key [key ...] [WEIGHTS weight [weight ...]] [AGGREGATE SUM|MIN|MAX] |
计算给定多个有序集合的交集,并将结果存储到目标有序集合中。 | ZINTERSTORE zinter 2 zset1 zset2 AGGREGATE SUM (a:4) |
场景示例: 排行榜(游戏积分榜、最热文章榜)、带有优先级的任务队列、根据分数范围筛选数据。
七、Stream (流)
Redis 5.0 引入了 Stream 数据结构,它是一个只追加的数据结构,用于处理日志流、事件流等时间序列数据。它支持多消费者组。
| 指令 | 描述 | 示例 |
|---|---|---|
XADD key ID field value [field value ...] |
添加新的条目到 Stream。ID 可以是 * (自动生成),或手动指定。 |
XADD mystream * sensor_id 123 temperature 25.5XADD mystream 1-0 event_type "login" user_id 456 |
XRANGE key start end [COUNT count] |
获取 Stream 中指定 ID 范围内的条目。min 和 max 可以是 "-" (最小ID) 或 "+" (最大ID)。 |
XRANGE mystream - +XRANGE mystream 1678881330000-0 1678881330999-999 COUNT 10 |
XREAD [COUNT count] [BLOCK milliseconds] STREAMS key [key ...] ID [ID ...] |
从一个或多个 Stream 中读取条目。BLOCK 实现阻塞读取。 |
XREAD COUNT 2 STREAMS mystream 0-0XREAD BLOCK 0 STREAMS mystream $ (阻塞读取最新条目) |
XGROUP CREATE key groupname ID [MKSTREAM] |
创建消费者组。ID 指定消费者组的起始 ID(例如 $ 表示从最新开始,0 表示从头开始)。MKSTREAM:如果 Stream 不存在则自动创建。 |
XGROUP CREATE mystream mygroup $ MKSTREAM |
XREADGROUP GROUP groupname consumername COUNT count [BLOCK milliseconds] STREAMS key [key ...] ID [ID ...] |
从消费者组中读取条目。ID 为 > 表示从未发送给当前消费者的条目开始。 |
XREADGROUP GROUP mygroup myconsumer COUNT 1 STREAMS mystream > |
XACK key groupname ID [ID ...] |
确认消费者已处理完某个条目。 | XACK mystream mygroup 1678881330000-0 |
XPENDING key groupname [IDLE min-idle-time] [start end count] [consumer] |
获取消费者组中待处理消息列表。 | XPENDING mystream mygroup |
XCLAIM key groupname consumername min-idle-time ID [ID ...] |
夺回(claim)其他消费者已读取但长时间未确认的条目。 | XCLAIM mystream mygroup newconsumer 3600000 1678881330000-0 |
XTRIM key MAXLEN [~] count |
裁剪 Stream,保留指定数量的最新条目。~ 大约保留。 |
XTRIM mystream MAXLEN 1000 |
场景示例: 实时消息系统、事件溯源、微服务间通信、物联网数据采集。
八、HyperLogLog (HLL)
HyperLogLog 是一种概率性数据结构,用于估算集合中元素的唯一数量(即基数)。它使用的内存非常少(固定 12KB),但会存在小部分误差。
| 指令 | 描述 | 示例 |
|---|---|---|
PFADD key element [element ...] |
添加一个或多个元素到 HyperLogLog。 | PFADD users:20231010 "user1" "user2" "user3" |
PFCOUNT key [key ...] |
返回 HyperLogLog 的近似基数。 | PFCOUNT users:20231010 |
PFMERGE destkey sourcekey [sourcekey ...] |
将多个 HyperLogLog 合并到一个新的 HyperLogLog 中。 | PFMERGE users:total users:20231010 users:20231011 |
场景示例: 网站独立访客数统计、用户日活/月活统计、热门商品访问量统计。
九、Geospatial (地理空间)
Redis 3.2 引入了地理空间索引,允许存储和查询地理空间坐标,通常用于基于位置的服务 (LBS)。
| 指令 | 描述 | 示例 |
|---|---|---|
GEOADD key longitude latitude member [longitude latitude member ...] |
添加一个或多个地理空间成员(经度、纬度和名称)。 | GEOADD city_locations 13.361 38.084 "Palermo" 15.087 37.502 "Catania" |
GEOPOS key member [member ...] |
获取指定成员的经度和纬度。 | GEOPOS city_locations "Palermo" |
GEODIST key member1 member2 [UNIT] |
计算两个成员之间的距离。UNIT 可以是 m (米), km (千米), mi (英里), ft (英尺)。 |
GEODIST city_locations "Palermo" "Catania" km |
GEORADIUS key longitude latitude radius IN|OUT [UNIT] [WITHCOORD] [WITHDIST] [WITHHASH] [COUNT count] [ASC|DESC] [STORE key] [STOREDIST key] |
根据中心点和半径查询附近的成员。WITHCOORD 返回坐标,WITHDIST 返回距离。 |
GEORADIUS city_locations 15 37 100 km WITHCOORD WITHDIST COUNT 5 ASC |
GEOSEARCH key [FROMMEMBER member|FROMLONLAT longitude latitude] [BYRADIUS radius unit|BYBOX width height unit] [ASC|DESC] [COUNT count [ANY]] [WITHCOORD] [WITHDIST] [WITHHASH] |
更灵活的地理空间查询指令 (Redis 6.2+)。 | GEOSEARCH city_locations FROMLONLAT 15 37 BYRADIUS 100 km |
场景示例: 查找附近的人/店铺、地理围栏、LBS 游戏。
十、总结
Redis 凭借其丰富的数据结构和闪电般的读写速度,使其成为现代应用开发中不可或缺的工具。
- 字符串:最简单,用于缓存、计数器、KV 存储。
- 哈希:适合存储对象,如用户会话、商品信息。
- 列表:实现消息队列、时间线、LIFO/FIFO 队列。
- 集合:去重、集合运算,如标签、共同兴趣、权限管理。
- 有序集合:排行榜、带优先级队列、范围查询。
- Stream:处理时间序列数据、消息队列、事件日志。
- HyperLogLog:大数据集的基数估算,节省内存。
- Geospatial:地理位置信息存储与查询,LBS 应用。
通过理解每种数据结构的特性和适用场景,并熟练运用其相关指令,你将能够更好地设计和优化你的应用程序,充分发挥 Redis 的强大潜力。开始使用这些指令,构建你的高性能、高并发应用吧!
