Redis的五种基本数据结构(String、List、Hash、Set、Sorted Set)在面试中是经常被询问的话题。本文将帮助你回顾这些结构,并加深对它们的理解。
此外,还有几种特殊的数据结构(HyperLogLogs、Bitmap、Geospatial、Stream)也非常重要,我们将留待下次讨论。

对于Redis的详细数据结构介绍,可以参考Redis官方网站:
随着Redis新版本的发布,未来可能会有新数据结构的推出,查阅Redis官网的相关介绍是获取最新信息的最佳途径。

String(字符串)
概述
String是Redis中最基本且最常用的数据结构。它是一个二进制安全的数据结构,能够存储任何数据类型,如字符串、整数、浮点数、图片(例如图片的base64编码或路径)以及序列化后的对象。
尽管Redis是用C语言编写的,但它采用了一种名为简单动态字符串(Simple Dynamic String,SDS)的字符串表示方式。与C语言的原生字符串相比,Redis的SDS不仅可以存储文本数据,还能处理二进制数据,并且获取字符串长度的复杂度为O(1)(C字符串为O(N))。此外,Redis的SDS API设计确保了安全性,避免了缓冲区溢出的问题。
常用命令
| 命令 | 描述 |
|---|---|
| SET key value | 设置指定key的值 |
| SETNX key value | 仅当key不存在时设置key的值 |
| GET key | 获取指定key的值 |
| MSET key1 value1 key2 value2 … | 同时设置多个指定key的值 |
| MGET key1 key2 ... | 获取多个指定key的值 |
| STRLEN key | 返回key所储存字符串值的长度 |
| INCR key | 将key中存储的数字值加一 |
| DECR key | 将key中存储的数字值减一 |
| EXISTS key | 检查指定key是否存在 |
| DEL key(通用) | 删除指定的key |
| EXPIRE key seconds(通用) | 设置key的过期时间 |
更多Redis String命令和详细使用指南,请查看Redis官网。
基本操作示例
> SET key value
OK
> GET key
"value"
> EXISTS key
(integer) 1
> STRLEN key
(integer) 5
> DEL key
(integer) 1
> GET key
(nil)
应用场景
存储常规数据的场合
- 示例:缓存session、token、图片地址、序列化后的对象(相对Hash存储更节省内存)。
- 相关命令:
SET、GET。
计数功能
- 示例:用户单位时间的请求数(简单限流)、页面单位时间的访问数。
- 相关命令:
SET、GET、INCR、DECR。
分布式锁
利用SETNX key value命令可以实现一个简单的分布式锁(不过存在一些缺陷,因此通常不建议这样实现)。
List(列表)
概述
Redis的List是链表数据结构的实现。虽然许多高级编程语言内置了链表的实现,如Java中的LinkedList,但C语言并没有,因此Redis实现了自己的链表结构。Redis的List采用双向链表的方式,使得反向查找和遍历更加便利,但也带来了额外的内存开销。

常用命令
| 命令 | 描述 |
|---|---|
| RPUSH key value1 value2 ... | 在指定列表的尾部添加一个或多个元素 |
| LPUSH key value1 value2 ... | 在指定列表的头部添加一个或多个元素 |
| LSET key index value | 设置指定列表索引的位置的值 |
| LPOP key | 移除并获取指定列表的第一个元素 |
| RPOP key | 移除并获取指定列表的最后一个元素 |
| LLEN key | 获取列表元素的数量 |
| LRANGE key start end | 获取列表中指定范围的元素 |
更多Redis List命令及详细使用指南,请查看Redis官网。
基本操作示例
通过RPUSH/LPOP或LPUSH/RPOP实现队列:
> RPUSH myList value1
(integer) 1
> RPUSH myList value2 value3
(integer) 3
> LPOP myList
"value1"
> LRANGE myList 0 1
1) "value2"
2) "value3"
应用场景
信息流展示
- 示例:最新文章、动态更新。
- 相关命令:
LPUSH、LRANGE。
消息队列
尽管Redis List可用于实现消息队列,但功能较为简单且存在缺陷,不建议使用。相较之下,Redis 5.0新加入的Stream结构更适合用于这种场景。
Hash(哈希)
概述
Redis中的Hash是一个String类型的field-value(键值对)映射表,尤其适用于存储对象,在后续操作中可以直接修改对象某些字段的值。Hash类似于JDK1.8之前的HashMap,但Redis的Hash经过了多次优化,性能表现更好。

常用命令
| 命令 | 描述 |
|---|---|
| HSET key field value | 设置指定哈希表中指定字段的值 |
| HSETNX key field value | 仅在字段不存在时设置其值 |
| HMSET key field1 value1 field2 value2 ... | 同时设置多个field-value对 |
| HGET key field | 获取指定哈希表中指定字段的值 |
| HMGET key field1 field2 ... | 获取指定字段的值 |
| HGETALL key | 获取指定哈希表中所有键值对 |
| HEXISTS key field | 检查指定字段是否存在 |
| HDEL key field1 field2 ... | 删除一个或多个字段 |
| HLEN key | 获取字段数量 |
更多Redis Hash命令和详细使用指南,请查看Redis官网。
基本操作示例
> HMSET userInfoKey name "guide" description "dev" age "24"
OK
> HEXISTS userInfoKey name
(integer) 1
> HGET userInfoKey name
"guide"
> HGET userInfoKey age
"24"
> HGETALL userInfoKey
1) "name"
2) "guide"
3) "description"
4) "dev"
5) "age"
6) "24"
> HSET userInfoKey name "GuideGeGe"
> HGET userInfoKey name
"GuideGeGe"
应用场景
对象数据存储
- 示例:用户信息、商品信息、文章信息、购物车信息。
- 相关命令:
HSET、HMSET、HGET、HMGET。
Set(集合)
概述
Redis中的Set是一种无序集合,集合中的元素是唯一的,类似Java中的HashSet。当需要存储列表数据且不希望有重复数据时,Set是一个理想选择。Set提供了判断元素是否存在的接口,这是List无法提供的特性。
通过Set可以轻松实现交集、并集和差集等操作。例如,可以将用户的所有关注者和粉丝存储在不同集合中,轻松获取共同关注和共同粉丝。

常用命令
| 命令 | 描述 |
|---|---|
| SADD key member1 member2 ... | 向指定集合添加一个或多个元素 |
| SMEMBERS key | 获取集合中的所有元素 |
| SCARD key | 获取集合的元素数量 |
| SISMEMBER key member | 判断元素是否在集合中 |
| SINTER key1 key2 ... | 获取集合的交集 |
| SUNION key1 key2 ... | 获取集合的并集 |
| SDIFF key1 key2 ... | 获取集合的差集 |
| SPOP key count | 随机移除并获取集合中的元素 |
| SRANDMEMBER key count | 随机获取集合中指定数量的元素 |
更多Redis Set命令和详细使用指南,请查看Redis官网。
基本操作示例
> SADD mySet value1 value2
(integer) 2
> SADD mySet value1
(integer) 0
> SMEMBERS mySet
1) "value1"
2) "value2"
> SCARD mySet
(integer) 2
> SISMEMBER mySet value1
(integer) 1
应用场景
非重复数据存放
- 示例:网站UV统计、文章点赞、动态点赞等场景。
- 相关命令:
SCARD。

集合之间的交集、并集和差集
- 示例:共同好友、共同关注、好友推荐。
- 相关命令:
SINTER、SUNION、SDIFF。

Sorted Set(有序集合)
概述
有序集合与Set类似,但增加了一个权重参数score,使得集合中的元素能够根据score进行排序,并可以通过score的范围获取元素列表。它类似于Java中的HashMap和TreeSet的结合体。

常用命令
| 命令 | 描述 |
|---|---|
| ZADD key score1 member1 score2 member2 ... | 向指定有序集合添加元素 |
| ZCARD key | 获取有序集合的元素数量 |
| ZSCORE key member | 获取指定元素的score值 |
| ZINTERSTORE destination numkeys key1 key2 ... | 求交集并存储 |
| ZUNIONSTORE destination numkeys key1 key2 ... | 求并集并存储 |
| ZDIFF destination numkeys key1 key2 ... | 求差集并存储 |
| ZRANGE key start end | 获取指定范围的元素 |
| ZREVRANGE key start end | 获取指定范围的元素(逆序) |
更多Redis Sorted Set命令和详细使用指南,请查看Redis官网。
基本操作示例
> ZADD myZset 2.0 value1 1.0 value2
(integer) 2
> ZCARD myZset
2
> ZSCORE myZset value1
2.0
> ZRANGE myZset 0 1
1) "value2"
2) "value1"
应用场景
根据权重排序的随机获取场合
- 示例:排行榜功能,如直播间礼物排行榜、游戏段位排行榜等。
- 相关命令:
ZRANGE、ZREVRANGE、ZREVRANK。

需要存储优先级或重要程度的场景
- 示例:优先级任务队列。
- 相关命令:
ZRANGE、ZREVRANGE、ZREVRANK。
参考资料
[1] Redis Data Structures: https://redis.com/redis-enterprise/data-structures/
[2] Redis Data Types Tutorial: https://redis.io/docs/manual/data-types/data-types-tutorial/