面试:原来Redis常用的五种数据类型底层结构是这样的

本文涉及的产品
云数据库 Tair(兼容Redis),内存型 2GB
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
简介: 在Redis中会涉及很多数据结构,比如SDS,双向链表、字典、压缩列表、整数集合等等。Redis会基于这些数据结构自定义一个对象系统,而且自定义的对象系统有很多好处

在Redis中会涉及很多数据结构,比如SDS,双向链表、字典、压缩列表、整数集合等等。Redis会基于这些数据结构自定义一个对象系统,而且自定义的对象系统有很多好处。


通过对以下的Redis对象系统的学习,可以了解Redis设计原理以及初衷,为了我们在使用Redis的时候,更加能够理解到其原理和定位问题。


Redis 对象


Redis基于上述的数据结构自定义一个Object 系统,Object结构:


redisObject结构:
   typedef struct redisObject{
  //类型
  unsigned type:4;
  //编码
  unsigned encoding:4;
  //指向底层实现数据结构的指针
  void *ptr;
  ….. 
} 
复制代码


Object 系统包含五种Object:


  • String:字符串对象
  • List:列表对象
  • Hash:哈希对象
  • Set:集合对象
  • ZSet:有序集合


Redis使用对象来表示数据库中的键和值,即每新建一个键值对,至少创建有两个对象,而且使用对象的具有以下好处: 1. redis可以在执行命令前会根据对象的类型判断一个对象是否可以执行给定的命令 2. 针对不同的使用场景,为对象设置不同的数据结构实现,从而优化对象的不同场景夏的使用效率 3. 对象系统还可以基于引用计数计数的内存回收机制,自动释放对象所占用的内存,或者还可以让多个数据库键共享同一个对象来节约内存。 4. redis对象带有访问时间记录信息,使用该信息可以进行优化空转时长较大的key,进行删除!


对象的ptr指针指向对象的底层现实数据结构,而这些数据结构由对象的encoding属性决定,对应关系:


编码常量 编码对应的底层数据结构
REDIS_ENCODING_INT long类型的整数
REDIS_ENCODING_EMBSTR embstr编码的简单动态字符串
REDIS_ENCODING_RAW 简单动态字符串
REDIS_ENCODING_HT 字典
REDIS_ENCODING_LINKEDLIST 双向链表
REDIS_ENCODING_ZIPLIST 压缩列表
REDIS_ENCODING_INTSET 整数集合
REDIS_ENCODING_SKIPLIST 跳跃表和字典


每种Object对象至少有两种不同的编码,对应关系:


类型 编码 对象
String int 整数值实现
String embstr sds实现 <=39 字节
String raw sds实现 > 39字节
List ziplist 压缩列表实现
List linkedlist 双端链表实现
Set intset 整数集合使用
Set hashtable 字典实现
Hash ziplist 压缩列表实现
Hash hashtable 字典使用
Sorted set ziplist 压缩列表实现
Sorted set skiplist 跳跃表和字典


## String 对象


字符串对象编码可以int 、raw或者embstr,如果保存的值为整数值且这个值可以用long类型表示,使用int编码,其他编码类似。


比如:int编码的String Object


redis> set number 520 
 ok
 redis> OBJECT ENCODING number 
"int"
复制代码


String Object结构:


4.png


String 对象之间的编码转换


int编码的字符串对象和embstr编码的字符串对象在条件满足的情况下,会被转换为raw编码的字符串对象。


比如:对int编码的字符串对象进行append命令时,就会使得原来是int变为raw编码字符串


## List对象


list对象可以为ziplist或者为linkedlist,对应底层实现ziplist为压缩列表,linkedlist为双向列表。


Redis>RPUSH numbers “Ccww” 520 1
复制代码


用ziplist编码的List对象结构:


5.png


用linkedlist编码的List对象结构:


6.png


List对象的编码转换:


当list对象可以同时满足以下两个条件时,list对象使用的是ziplist编码: 1. list对象保存的所有字符串元素的长度都小于64字节 2. list对象保存的元素数量小于512个, 不能满足这两个条件的list对象需要使用linkedlist编码。


Hash对象


Hash对象的编码可以是ziplist或者hashtable 其中,ziplist底层使用压缩列表实现:


  • 保存同一键值对的两个节点紧靠相邻,键key在前,值vaule在后
  • 先保存的键值对在压缩列表的表头方向,后来在表尾方向


hashtable底层使用字典实现,Hash对象种的每个键值对都使用一个字典键值对保存:


  • 字典的键为字符串对象,保存键key
  • 字典的值也为字符串对象,保存键值对的值


比如:HSET命令


redis>HSET author name  "Ccww"
(integer)
redis>HSET author age  18
(integer)
redis>HSET author sex  "male"
(integer)
复制代码


ziplist的底层结构:


7.png


hashtable底层结构:


8.png


Hash对象的编码转换:


当list对象可以同时满足以下两个条件时,list对象使用的是ziplist编码: 1. list对象保存的所有字符串元素的长度都小于64字节 2. list对象保存的元素数量小于512个, 不能满足这两个条件的hash对象需要使用hashtable编码


Note:这两个条件的上限值是可以修改的,可查看配置文件hash-max-zaiplist-value和hash-max-ziplist-entries


## Set对象: Set对象的编码可以为intset或者hashtable + intset编码:使用整数集合作为底层实现,set对象包含的所有元素都被保存在intset整数集合里面 + hashtable编码:使用字典作为底层实现,字典键key包含一个set元素,而字典的值则都为null

inset编码Set对象结构:


redis> SAD number  1 3 5 
复制代码


9.png


hashtable编码Set对象结构:


redis> SAD Dfruits  “apple”  "banana" " cherry"
复制代码


10.png


Set对象的编码转换:


使用intset编码: 1. set对象保存的所有元素都是整数值 2. set对象保存的元素数量不超过512个 不能满足这两个条件的Set对象使用hashtable编码


ZSet对象


ZSet对象的编码 可以为ziplist或者skiplist ziplist编码,每个集合元素使用相邻的两个压缩列表节点保存,一个保存元素成员,一个保存元素的分值,然后根据分数进行从小到大排序。


ziplist编码的ZSet对象结构:


Redis>ZADD price 8.5 apple 5.0 banana 6.0 cherry
复制代码


11.png


skiplist编码的ZSet对象使用了zset结构,包含一个字典和一个跳跃表


Type struct zset{
  Zskiplist *zsl;
  dict *dict;
  ...
}
skiplist编码的ZSet对象结构
复制代码


12.png


ZSet对象的编码转换


当ZSet对象同时满足以下两个条件时,对象使用ziplist编码 1. 有序集合保存的元素数量小于128个 2. 有序集合保存的所有元素的长度都小于64字节 不能满足以上两个条件的有序集合对象将使用skiplist编码。


Note: 可以通过配置文件中zset-max-ziplist-entries和zset-max-ziplist-vaule


各位看官还可以吗?喜欢的话,动动手指点个💗,点个关注呗!!谢谢支持!



相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore &nbsp; &nbsp; ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库&nbsp;ECS 实例和一台目标数据库&nbsp;RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&amp;RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
目录
相关文章
|
1天前
|
存储 缓存 NoSQL
解决Redis缓存数据类型丢失问题
解决Redis缓存数据类型丢失问题
109 85
|
2月前
|
存储 关系型数据库 MySQL
阿里面试:为什么要索引?什么是MySQL索引?底层结构是什么?
尼恩是一位资深架构师,他在自己的读者交流群中分享了关于MySQL索引的重要知识点。索引是帮助MySQL高效获取数据的数据结构,主要作用包括显著提升查询速度、降低磁盘I/O次数、优化排序与分组操作以及提升复杂查询的性能。MySQL支持多种索引类型,如主键索引、唯一索引、普通索引、全文索引和空间数据索引。索引的底层数据结构主要是B+树,它能够有效支持范围查询和顺序遍历,同时保持高效的插入、删除和查找性能。尼恩还强调了索引的优缺点,并提供了多个面试题及其解答,帮助读者在面试中脱颖而出。相关资料可在公众号【技术自由圈】获取。
|
1月前
|
缓存 NoSQL 关系型数据库
大厂面试高频:如何解决Redis缓存雪崩、缓存穿透、缓存并发等5大难题
本文详解缓存雪崩、缓存穿透、缓存并发及缓存预热等问题,提供高可用解决方案,帮助你在大厂面试和实际工作中应对这些常见并发场景。关注【mikechen的互联网架构】,10年+BAT架构经验倾囊相授。
大厂面试高频:如何解决Redis缓存雪崩、缓存穿透、缓存并发等5大难题
|
17天前
|
存储 NoSQL Redis
redis常见数据类型
Redis 是一种基于内存的键值存储数据库,支持字符串、哈希表、列表、集合及有序集合等多种数据类型,每种类型均有特定用途与适用场景,提供丰富的命令操作,适用于高速数据访问与处理。
31 5
|
1月前
|
存储 NoSQL 算法
阿里面试:亿级 redis 排行榜,如何设计?
本文由40岁老架构师尼恩撰写,针对近期读者在一线互联网企业面试中遇到的高频面试题进行系统化梳理,如使用ZSET排序统计、亿级用户排行榜设计等。文章详细介绍了Redis的四大统计(基数统计、二值统计、排序统计、聚合统计)原理和应用场景,重点讲解了Redis有序集合(Sorted Set)的使用方法和命令,以及如何设计社交点赞系统和游戏玩家排行榜。此外,还探讨了超高并发下Redis热key分治原理、亿级用户排行榜的范围分片设计、Redis Cluster集群持久化方式等内容。文章最后提供了大量面试真题和解决方案,帮助读者提升技术实力,顺利通过面试。
|
1月前
|
存储 NoSQL 算法
面试官:Redis 大 key 多 key,你要怎么拆分?
本文介绍了在Redis中处理大key和多key的几种策略,包括将大value拆分成多个key-value对、对包含大量元素的数据结构进行分桶处理、通过Hash结构减少key数量,以及如何合理拆分大Bitmap或布隆过滤器以提高效率和减少内存占用。这些方法有助于优化Redis性能,特别是在数据量庞大的场景下。
面试官:Redis 大 key 多 key,你要怎么拆分?
|
1月前
|
存储 缓存 Java
大厂面试必看!Java基本数据类型和包装类的那些坑
本文介绍了Java中的基本数据类型和包装类,包括整数类型、浮点数类型、字符类型和布尔类型。详细讲解了每种类型的特性和应用场景,并探讨了包装类的引入原因、装箱与拆箱机制以及缓存机制。最后总结了面试中常见的相关考点,帮助读者更好地理解和应对面试中的问题。
58 4
|
1月前
|
存储 消息中间件 NoSQL
使用Java操作Redis数据类型的详解指南
通过使用Jedis库,可以在Java中方便地操作Redis的各种数据类型。本文详细介绍了字符串、哈希、列表、集合和有序集合的基本操作及其对应的Java实现。这些示例展示了如何使用Java与Redis进行交互,为开发高效的Redis客户端应用程序提供了基础。希望本文的指南能帮助您更好地理解和使用Redis,提升应用程序的性能和可靠性。
38 1
|
2月前
|
存储 消息中间件 NoSQL
Redis 数据类型
10月更文挑战第15天
43 1
|
1月前
|
存储 NoSQL Redis
【赵渝强老师】Redis的存储结构
Redis 默认配置包含 16 个数据库,通过 `databases` 参数设置。每个数据库编号从 0 开始,默认连接 0 号数据库,可通过 `SELECT &lt;dbid&gt;` 切换。Redis 的核心存储结构包括 `dict`、`expires` 等字段,用于处理键值和过期行为。添加键时需指定数据库信息。视频讲解和代码示例详见内容。
下一篇
DataWorks