当前位置: 首页 > article >正文

Redis五中数据类型的底层实现

String字符串

字符串是 Redis 中最基础的数据类型,可以存储整数、浮点数或字符串。

底层实现:int整数编码和SDS简单动态字符串

SDS(Simple Dynamic String简单动态字符串)

Redis 并未直接使用 C 语言的 char 数组来存储字符串,而是实现了一种名为 SDS(简单动态字符串) 的结构,它比 C 语言的字符串更高效和灵活。

核心特点:

  • 动态扩展:避免频繁的内存分配和复制操作。
  • 常数时间O(1)获取字符串长度(SDS 结构会存储字符串的长度)。
  • 末尾有空字符 \0,确保可以兼容 C 语言的字符串函数。

常用命令

#设置key-value类型的值
>SET name lin
OK
#根据key 获得对应的value
>GET name
"lin"
#判断某个 key是否存在
>EXISTS name
(integer)1
#返回key所储存的字符串值的长度
>STRLEN name
(integer)3
#删除某个 key对应的值
>DEL name
(integer)1

#批量设置key-value类型的值
>MSET key1 value1 key2 value2OK
#批量获取多个 key 对应的value
>MGET key1 key2
1)value1"
2) "value2"

#设置key-value类型的值
>SET number o
OK
#将key中储存的数字值增一
>INCR number
(integer)1
# 将key中存储的数字值加10
>INCRBY number 10
(integer)11
#将 key中储存的数字值减一
> DECR number
(integer)10
#将key中存储的数字值键10
>DECRBY number 10
(integer)0

#不存在就插入(not exists)//分布式锁
>SETNX key value
(integer)1

应用场景

  1. 常规计数。因为Redis处理命令是单线程,所以执行命令的过程是原子的。因此 String 数据类型适合计数场景,比如计算访问次数、点赞、转发、库存数量等等。
  2. 分布式锁。SET命令有个NX参数可以实现「key不存在才插入J,可以用它来实现分布式锁
  3. 共享Session信息。

Hash哈希 

哈希类型是一个键值对的集合,可以类比为一个小型的字典或哈希表。

底层实现:Ziplist(压缩列表)和Hashtable(哈希表)

Ziplist(压缩列表):

如果哈希类型元素个数小于512个(默认值,可由hash-max-ziplist-entries配置),所有值小于64字节(默认值,可由hash-max-ziplist-value配置)的话,Redis 会使用压缩列表作为Hash类型的底层数据结构;

Hashtable(哈希表):

当哈希表中的键值对数量增多或键值对的长度较大,不满足上面条件时,Redis 会将底层实现切换为字典(hashtable)。Redis 的 hashtable 使用开放寻址法来解决哈希冲突,并通过渐进式 rehash 来应对扩展和收缩。

常用命令

#存储一个哈希表key的键值
HSET key field value

#获取哈希表key对应的field键值
HGET key field

#在一个哈希表key中存储多个键值对
HMSET key field value [field value. . .]

#批量获取哈希表key中多个field键值
HMGET key field [field ...]

#删除哈希表key中的field键值
HDEL key field [field ...]

#返回哈希表key中field的数量
HLEN key

#返回哈希表key中所有的键值
HGETALL key

#为哈希表key中field键的值加上增量n
HINCRBY key field n

应用场景

  • 缓存对象(购物车等)

List列表

列表类型用于存储一系列的有序字符串,支持从头部和尾部操作(如插入、删除)等。

底层实现:Ziplist(压缩列表)、Linkedlist(双向链表)、Quicklist(快速列表)

Linkedlist(双向链表):

当列表中的元素较多或元素较长时,Redis 会使用双向链表来存储列表。双向链表可以有效地支持 O(1) 的头尾插入和删除操作,同时还支持正向和反向遍历

Quicklist(快速列表):

Redis 3.2 之后,引入了一种新的数据结构 Quicklist(只用它了),它结合了压缩列表和双向链表的优点。Quicklist 是由多个压缩列表组成的双向链表,既减少了内存开销,又保留了双向链表的灵活性。

常用命令

# 将一个或多个值value插入到key列表的表头(最左边),最后的值在最前面
LPUSH key value [value ...]

# 将一个或多个值value插入到key列表的表尾(最右边)
RPUSH key value [value ...]

#移除并返回key列表的头元素
LPOP key

#移除并返回key列表的尾元素
RPOP key

#返回列表key中指定区间内的元素,区间以偏移量start和stop指定,从o开始
LRANGE key start stop

# 从key列表表头弹出一个元素,没有就阻塞timeout秒,如果timeout=0则一直阻塞
BLPOP key [key ...] timeout

# 从key列表表尾弹出一个元素,没有就阻塞timeout秒,如果timeout=0则一直阻塞
BRPOP key[key ... ] timeout

应用场景

  1. 消息队列。列表用来存储多个有序的字符串,既然是有序的,那么就满足消息队列的特点。使用lpush+rpop或者rpush+lpop实现消息队列。除此之外,redis支持阻塞操作,在弹出元素的时候使用阻塞命令来实现阻塞队列。

  2. 栈。由于列表存储的是有序字符串,满足队列的特点,也就能满足栈先进后出的特点,使用lpush+lpop或者rpush+rpop实现栈。

  3. 文章列表。因为列表的元素不但是有序的,而且还支持按照索引范围获取元素。因此我们可以使用命令lrange key 0 9分页获取文章列表

Set集合

集合类型用于存储不重复的字符串元素,支持集合运算如交集、并集、差集等。

底层实现:Intset(整数集合)和Hashtable(哈希表)

Intset(整数集合):

当集合中的元素都是整数且数量较少时,Redis 会使用整数集合(intset)来存储数据。整数集合是一块连续的内存,存储了排序后的整数,并且不允许重复,适用于存储较少数量的整数集合。

Hashtable(哈希表):

当集合中的元素增多或包含非整数类型时,集合会使用哈希表存储。哈希表的键是集合中的元素,值为特殊的占位符,这样可以快速判断集合中是否包含某个元素。

常用命令

#往集合key中存入元素,元素存在则忽略,若key不存在则新建
SADD key member [member ...]

#从集合key中删除元素
SREM key member [member ...]

#获取集合key中所有元素
SMEMBERS key

#获取集合key中的元素个数
SCARD key

#判断member元素是否存在于集合key中
SISMEMBER key member

#从集合key中随机选出count个元素,元素不从key中删除
SRANDMEMBER key [count]

#从集合key中随机选出count个元素,元素从key中删除
SPOP key [ count]


#交集运算
SINTER key [key ...]

#将交集结果存入新集合destination中
SINTERSTORE destination key [key ...]

#并集运算
SUNION key [key ...]

#将并集结果存入新集合destination中
SUNIONSTORE destination key [key ...]

#差集运算
SDIFF key [key ...]

#将差集结果存入新集合destination中
SDIFFSTORE destination key [key ...]

应用场景

  1. 点赞。
    Set类型可以保证一个用户只能点一个赞,这里举例子一个场景,key是文章id, value是用户id。

  2. 共同关注。
    Set类型支持交集运算,所以可以用来计算共同关注的好友、公众号等。
  3. 抽奖活动
    存储某活动中中奖的用户名,Set类型因为有去重功能,可以保证同一个用户不会中奖两次。
     

Zset有序集合

Zset类型(有序集合类型)相比于Set类型多了一个排序属性score(分值),对于有序集合ZSet 来说,每个存储元素相当于有两个值组成的,一个是有序集合的元素值,一个是排序值。
有序集合保留了集合不能有重复成员的特性(分值可以重复),但不同的是,有序集合中的元素可以排序。
底层实现:Ziplist(压缩列表)、Skiplist(跳表) + Hashtable(哈希表)

Skiplist(跳表) + Hashtable(哈希表):

当有序集合中的元素较多时,Redis 会使用跳表和哈希表的组合结构来实现有序集合:

  • 跳表(skiplist):跳表是一种用于快速查找的有序数据结构,能够在 O(logN) 时间复杂度下查找、插入和删除数据。跳表是 Redis 有序集合中保证数据按分数排序的核心数据结构。
  • 哈希表(hashtable):哈希表用来存储有序集合中的元素和值的映射关系,确保能够在 O(1) 时间内查找到元素的分数。

常用命令

#往有序集合key中加入带分值元素
ZADD key score member [[score member]...]

#往有序集合key中删除元素
ZREM key member[member. . .]

#返回有序集合key中元素member的分值
ZSCORE key member

#返回有序集合key中元素个数
ZCARD key

#为有序集合key中元素member的分值加上
incrementZINCRBY key increment member

#正序获取有序集合key从start下标到stop下标的元素
ZRANGE key start stop [WITHSCORES]

#倒序获取有序集合key从start下标到stop下标的元素
ZREVRANGE key start stop [WITHSCORES]

#返回有序集合中指定分数区间内的成员,分数由低到高排序。
ZRANGEBYSCORE key min max [WITHSCORES][LIMIT offset count]

#返回指定成员区间内的成员,按字典正序排列,分数必须相同。
ZRANGEBYLEX key min max [LIMIT offset count]

#返回指定成员区间内的成员,按字典倒序排列,分数必须相同
ZREVRANGEBYLEX key max min [LIMIT offset count]

应用场景 

  1.  排行榜。有序集合比较典型的使用场景就是排行榜。例如学生成绩的排名榜、游戏积分排行榜、视频播放排名、电商系统中商品的销量排名等。

  2. 电话、姓名排序。使用有序集合的ZRANGEBYLEX或ZREVRANGEBYLEX可以帮助我们实现电话号码或姓名的排序,我们以ZRANGEBYLEX(返回指定成员区间内的成员,按key正序排列,分数必须相同)为例。
    注意:不要在分数不一致的SortSet集合中去使用ZRANGEBYLEX和ZREVRANGEBYLEX指令,因为获取的结果会不准确。
     

http://www.kler.cn/a/313929.html

相关文章:

  • 【2024软考架构案例题】你知道 Es 的几种分词器吗?Standard、Simple、WhiteSpace、Keyword 四种分词器你知道吗?
  • Unity3D学习FPS游戏(12)敌人检测和攻击玩家
  • win32 / WTL 开发多线程应用,子线程传递大对象给UI线程(主窗口)的方法
  • 算法——二分查找(leetcode704)
  • STM32嵌入式闹钟系统设计与实现
  • D67【python 接口自动化学习】- python基础之数据库
  • nodejs+express+vue教辅课程辅助教学系统 43x2u前后端分离项目
  • mysql-死锁
  • EP16 自定义头部导航栏
  • ubuntu64位系统无法运行32位程序的解决办法
  • C++校招面经(二)
  • Sentinel组件学习
  • 力扣题解815
  • vue 入门一
  • 浪潮信息金风慧能:打造智慧新能源运营平台
  • DMA学习
  • 【pyVista】在三维模型中的网格属性
  • JavaScript发送邮件:实现前端触发的教程?
  • 【VitualBox】VitualBox的网络模式+网络配置
  • VuePress搭建文档网站/个人博客(详细配置)主题配置
  • 自动登录 RPA 的进阶:滑块验证的巧妙实现
  • 远程连接MySQL并操作
  • PostgreSQL JAVA与SQL集成之PL/Java
  • 科研绘图系列:R语言散点图和小提琴图(scatter plot violin plot)
  • 【ORACLE】客户端或plsql无法连接Oracle问题之一
  • 基于A2C与超启发式的航天器星载自主任务规划算法-笔记