Redis 5 种基本数据类型的前两个详解

Redis 共有 5 种基本数据类型:String(字符串)、List(列表)、Set(集合)、Hash(散列)、Zset(有序集合)。

这 5 种数据类型是直接提供给用户使用的,是数据的保存形式,其底层实现主要依赖这 8 种数据结构:简单动态字符串(SDS)、LinkedList(双向链表)、Dict(哈希表/字典)、SkipList(跳跃表)、Intset(整数集合)、ZipList(压缩列表)、QuickList(快速列表)。

Redis 5 种基本数据类型对应的底层数据结构实现如下表所示:

StringListHashSetZset
SDSLinkedList/ZipList/QuickListDict、ZipListDict、IntsetZipList、SkipList

Redis 3.2 之前,List 底层实现是 LinkedList 或者 ZipList。 Redis 3.2 之后,引入了 LinkedList 和 ZipList 的结合 QuickList,List 的底层实现变为 QuickList。从 Redis 7.0 开始, ZipList 被 ListPack 取代。

你可以在 Redis 官网上找到 Redis 数据类型/结构非常详细的介绍:

未来随着 Redis 新版本的发布,可能会有新的数据结构出现,通过查阅 Redis 官网对应的介绍,你总能获取到最靠谱的信息。

String(字符串)

介绍

String 是 Redis 中最简单同时也是最常用的一个数据类型。

String 是一种二进制安全的数据类型,可以用来存储任何类型的数据比如字符串、整数、浮点数、图片(图片的 base64 编码或者解码或者图片的路径)、序列化后的对象。

虽然 Redis 是用 C 语言写的,但是 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 官网对应的介绍:Commands | Docs

基本操作

> SET key value
OK
> GET key
"value"
> EXISTS key
(integer) 1
> STRLEN key
(integer) 5
> DEL key
(integer) 1
> GET key
(nil)

批量设置

> MSET key1 value1 key2 value2
OK
> MGET key1 key2 # 批量获取多个 key 对应的 value
1) "value1"
2) "value2"

计数器(字符串的内容为整数的时候可以使用):

> SET number 1
OK
> INCR number # 将 key 中储存的数字值增一
(integer) 2
> GET number
"2"
> DECR number # 将 key 中储存的数字值减一
(integer) 1
> GET number
"1"

设置过期时间(默认为永不过期)

> EXPIRE key 60
(integer) 1
> SETEX key 60 value # 设置值并设置过期时间
OK
> TTL key
(integer) 56

应用场景

需要存储常规数据的场景

  • 举例:缓存 Session、Token、图片地址、序列化后的对象(相比较于 Hash 存储更节省内存)。
  • 相关命令:SETGET

需要计数的场景

  • 举例:用户单位时间的请求数(简单限流可以用到)、页面单位时间的访问数。
  • 相关命令:SETGETINCRDECR

分布式锁

利用 SETNX key value 命令可以实现一个最简易的分布式锁(存在一些缺陷,通常不建议这样实现分布式锁)。

List(列表)

介绍

Redis 中的 List 其实就是链表数据结构的实现。我在 线性数据结构 :数组、链表、栈、队列 这篇文章中详细介绍了链表这种数据结构,我这里就不多做介绍了。

许多高级编程语言都内置了链表的实现比如 Java 中的 LinkedList,但是 C 语言并没有实现链表,所以 Redis 实现了自己的链表数据结构。Redis 的 List 的实现为一个 双向链表,即可以支持反向查找和遍历,更方便操作,不过带来了部分额外的内存开销。

 

常用命令

命令介绍
RPUSH key value1 value2 ...在指定列表的尾部(右边)添加一个或多个元素
LPUSH key value1 value2 ...在指定列表的头部(左边)添加一个或多个元素
LSET key index value将指定列表索引 index 位置的值设置为 value
LPOP key移除并获取指定列表的第一个元素(最左边)
RPOP key移除并获取指定列表的最后一个元素(最右边)
LLEN key获取列表元素数量
LRANGE key start end获取列表 start 和 end 之间 的元素

更多 Redis List 命令以及详细使用指南,请查看 Redis 官网对应的介绍:Commands | Docs

通过 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"
> LRANGE myList 0 -1
1) "value2"
2) "value3"

通过 RPUSH/RPOP或者LPUSH/LPOP 实现栈

> RPUSH myList2 value1 value2 value3
(integer) 3
> RPOP myList2 # 将 list的最右边的元素取出
"value3"

我专门画了一个图方便大家理解 RPUSH , LPOP , lpush , RPOP 命令:

通过 LRANGE 查看对应下标范围的列表元素

> RPUSH myList value1 value2 value3
(integer) 3
> LRANGE myList 0 1
1) "value1"
2) "value2"
> LRANGE myList 0 -1
1) "value1"
2) "value2"
3) "value3"

通过 LRANGE 命令,你可以基于 List 实现分页查询,性能非常高!

通过 LLEN 查看链表长度

> LLEN myList
(integer) 3

应用场景

信息流展示

  • 举例:最新文章、最新动态。
  • 相关命令:LPUSHLRANGE

消息队列

List 可以用来做消息队列,只是功能过于简单且存在很多缺陷,不建议这样做。

相对来说,Redis 5.0 新增加的一个数据结构 Stream 更适合做消息队列一些,只是功能依然非常简陋。和专业的消息队列相比,还是有很多欠缺的地方比如消息丢失和堆积问题不好解决。

### Redis 支持的五种数据类型 #### 1. 字符串 (String) 字符串是最基本数据类型,在 Redis 中,字符串可以是纯文本形式也可以是二进制安全的。除了作为普通的键值对存储外,还可以执行一些额外的操作,比如设置过期时间和原子性的递增/递减数值。 ```python SET key value # 设置指定key对应的value GET key # 获取指定key对应的value INCR key # 将key所储存的值加一 DECR key # 将key所储存的值减一 ``` 这种类型的性能非常高效,因为所有的操作都是 O(1),即常数时间内完成[^1]。 #### 2. 列表 (List) 列表是以链表的形式来保存一组按顺序排列的字符串元素。可以通过命令向列表两端添加新成员或将现有成员弹出。这对于构建队列或栈非常有用。 ```python LPUSH mylist "item1" # 向mylist左侧插入项目 RPUSH mylist "item2" # 向mylist右侧插入项目 LPOP mylist # 移除并返回mylist的第一个元素 RPOP mylist # 移除并返回mylist最后一个元素 LRANGE mylist start stop # 返回mylist中start到stop之间的元素 ``` 由于内部实现了双向链表结构,所以即使是在大型列表里也能快速访问头部和尾部节点。 #### 3. 集合 (Set) 集合是一组无序且不重复的字符串项组成的容器。提供了诸如交集、并集以及差集等丰富的集合运算功能。非常适合用来做唯一性验证或者社交网络中的好友关系管理等工作。 ```python SADD userset user1 # 添加一个member到set中 SMEMBERS userset # 查看整个set的内容 SISMEMBER userset member # 测试某个member是否存在于此set内 SINTER set1 set2 # 计算两个sets之间共同拥有的members ``` 这些操作大多能在平均情况下达到O(n)复杂度级别,其中n代表参与计算的最大集合大小[^5]。 #### 4. 哈希表 (Hash) 哈希表由字段(field)-值(value)对构成,类似于其他编程语言里的字典(Dictionary)/关联数组(Associative Array)概念。适用于表示对象属性及其对应值的关系模型。 ```python HSET person name "Alice" # 给person这个hash增加name->"Alice" HGET person name # 取得person hash下的name field对应的value HMSET person age 28 city BJ # 批量更新多个fields-values组合 HGETALL person # 获得所有field-value对 ``` 当涉及到大量记录时,相比于直接使用大量的独立keys更加节省空间,并且提高了批量处理效率[^2]。 #### 5. 有序集合 (Sorted Set) 有序集合不仅能够保持成员的独特性和不可变性,还能按照分数(score)来进行排序展示。因此非常适合于排行榜之类的场景应用。 ```python ZADD leaderboard 90 playerA # 插入playerA的成绩为90分 ZRANK leaderboard playerB # 查询playerB在整个leaderboard上的位置 ZSCORE leaderboard playerC # 得知playerC的具体得分情况 ZRANGEBYSCORE leaderboard min max # 提取score介于min-max范围内的players名单 ``` Redis 使用跳跃表(Skip List)而非传统意义上的平衡树(Balanced Tree)实现该特性,从而简化了算法逻辑的同时也保证了高效的查找速度[^4]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值