面试:原来Redis的五种数据类型数底层结构是这样的
mhr18 2024-10-31 13:25 19 浏览 0 评论
关注我,可以获取最新知识、经典面试题以及微服务技术分享
在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使用对象来表示数据库中的键和值,即每新建一个键值对,至少创建有两个对象,而且使用对象的具有以下好处:
- redis可以在执行命令前会根据对象的类型判断一个对象是否可以执行给定的命令
- 针对不同的使用场景,为对象设置不同的数据结构实现,从而优化对象的不同场景夏的使用效率
- 对象系统还可以基于引用计数计数的内存回收机制,自动释放对象所占用的内存,或者还可以让多个数据库键共享同一个对象来节约内存。
- redis对象带有访问时间记录信息,使用该信息可以进行优化空转时长较大的key,进行删除!
对象的ptr指针指向对象的底层现实数据结构,而这些数据结构由对象的encoding属性决定,对应关系:
编码常量 编码对应的底层数据结构 REDISENCODINGINT long类型的整数 REDISENCODINGEMBSTR embstr编码的简单动态字符串 REDISENCODINGRAW 简单动态字符串 REDISENCODINGHT 字典 REDISENCODINGLINKEDLIST 双向链表 REDISENCODINGZIPLIST 压缩列表 REDISENCODINGINTSET 整数集合 REDISENCODINGSKIPLIST 跳跃表和字典
每种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结构:
String 对象之间的编码转换
int编码的字符串对象和embstr编码的字符串对象在条件满足的情况下,会被转换为raw编码的字符串对象。
比如:对int编码的字符串对象进行append命令时,就会使得原来是int变为raw编码字符串
List对象
list对象可以为ziplist或者为linkedlist,对应底层实现ziplist为压缩列表,linkedlist为双向列表。
Redis>RPUSH numbers “Ccww” 520 1
用ziplist编码的List对象结构:
用linkedlist编码的List对象结构:
List对象的编码转换:
当list对象可以同时满足以下两个条件时,list对象使用的是ziplist编码:
- list对象保存的所有字符串元素的长度都小于64字节
- 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的底层结构:
hashtable底层结构:
Hash对象的编码转换:
当list对象可以同时满足以下两个条件时,list对象使用的是ziplist编码:
- list对象保存的所有字符串元素的长度都小于64字节
- 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
hashtable编码Set对象结构:
redis> SAD Dfruits “apple” "banana" " cherry"
Set对象的编码转换:
使用intset编码:
- set对象保存的所有元素都是整数值
- set对象保存的元素数量不超过512个
- 不能满足这两个条件的Set对象使用hashtable编码
ZSet对象
ZSet对象的编码 可以为ziplist或者skiplistziplist编码,每个集合元素使用相邻的两个压缩列表节点保存,一个保存元素成员,一个保存元素的分值,然后根据分数进行从小到大排序。
ziplist编码的ZSet对象结构:
Redis>ZADD price 8.5 apple 5.0 banana 6.0 cherry
skiplist编码的ZSet对象使用了zset结构,包含一个字典和一个跳跃表
Type struct zset{ Zskiplist *zsl; dict *dict; ... } skiplist编码的ZSet对象结构 
ZSet对象的编码转换
当ZSet对象同时满足以下两个条件时,对象使用ziplist编码
- 有序集合保存的元素数量小于128个
- 有序集合保存的所有元素的长度都小于64字节
- 不能满足以上两个条件的有序集合对象将使用skiplist编码。
Note:可以通过配置文件中zset-max-ziplist-entries和zset-max-ziplist-vaule
相关推荐
- 几种 TCP 连接中出现 RST 的情况
-
现在是一个网络时代了。应该不少程序员在编程中需要考虑多机、局域网、广域网的各种问题。所以网络知识也是避免不了学习的。而且笔者一直觉得TCP/IP网络知识在一个程序员知识体系中必需占有一席之地的。在...
- Redis连接使用报RDB error错误
-
该错误信息:Errorinexecution;nestedexceptionisio.lettuce.core.RedisCommandExecutionException:MISC...
- lua 语法介绍与 NGINX lua 高级用法实战操作
-
一、概述lua是一种轻量小巧的脚本语言,用标准C语言编写并以源代码形式开放,其设计目的是为了嵌入应用程序中,从而为应用程序提供灵活的扩展和定制功能。官网:https://www.lua.org/二、l...
- Python教程——20.协程 - 2
-
异步编程asyncio.Future对象Task继承Future,Task对象内部中的await结果的处理基于Future对象来的在Future对象中会保存当前执行的这个协程任务的状态,如果当...
- “我的足迹”、“浏览历史”,Redis如何快速记录与展示?
-
咱们在网上“买买买”、“逛逛逛”的时候,总会留下各种各样的“足迹”。无论是电商APP里你最近浏览过的商品,视频网站上你刚刚看过的剧集,还是新闻客户端里你点开过的文章……这些“历史记录”,有时候还真挺有...
- 你手机上的“消息推送”,Redis可能参与其中
-
手机上那些时不时就“叮咚”一下的消息推送,确实是咱们数字生活里不可或缺的一部分。这篇咱们就来聊聊,Redis这位“消息灵通人士”,是如何在这场“信息接力赛”中大显身手,确保那些重要的、有趣的通知,能够...
- 短视频APP的“附近的人”,Redis如何快速匹配?
-
刷短视频,除了看各种搞笑段子、才艺展示,有时候是不是也想看看“同城”或者“附近”的人都在发些啥有意思的内容?或者,平台也会时不时地给你推荐一些“附近正在直播”的主播,让你感觉一下子拉近了和这个虚拟世界...
- 微信朋友圈的点赞、评论,Redis在背后默默付出
-
微信朋友圈,这片小小的“自留地”,承载了我们多少喜怒哀乐、生活点滴啊!一张精心修饰的照片,一段随感而发的文字,发出去之后,最期待的是什么?那必须是屏幕下方不断冒出来的小红心和一条条真诚(或者商业互吹)...
- 网站登录老是掉线?Redis帮你记住你是谁!
-
有没有过这样的糟心体验?你好不容易登录了一个网站,刚看了两篇帖子,或者购物车里刚加了几件宝贝,结果一刷新页面,或者稍微离开了一会儿,回来就发现——“哎?我怎么又退出了?!”又得重新输入用户名、密码、...
- 你常用的APP,哪些地方可能用到了Redis?(猜想与分析)
-
咱们现在的生活,简直是离不开各种各样的手机APP了!从早上睁眼刷新闻,到中午点外卖,再到晚上刷短视频、玩游戏,一天到头,指尖在屏幕上就没停过。这些APP为了让我们用得爽、用得顺心,背后可是使出了浑身解...
- Redis是啥?为啥程序员天天挂嘴边?小白也能看懂!
-
这Redis到底是何方神圣?为啥那些天天在电脑前敲代码的程序员小哥哥小姐姐们,老是把它挂在嘴边,好像离了它地球都不转了似的?别担心,咱们今天不说那些听了就头大的代码和术语,就用大白话,保证你听完一拍大...
- 面试官:请你说说Redis为什么这么快?
-
1)Redis是基于内存的存储数据库,绝大部分的命令处理只是纯粹的内存操作,内存的读写速度非常快。2)Redis是单进程线程的服务(实际上一个正在运行的RedisServer肯定不止一个线程,但只有...
- 有了强大的关系型数据库,为什么还需要Redis?
-
在数字世界的浩瀚海洋中,关系型数据库,例如我们熟知的MySQL、PostgreSQL或Oracle,无疑是那些承载着核心业务数据、坚如磐石的“国家图书馆”或“银行金库”。它们以严谨的结构、强大的事务处...
- Java 中间件数据可靠性串讲:从 MQ 、MySQL、Redis 不丢失的保障之道
-
引言在现代分布式系统中,中间件扮演着至关重要的角色,它们是构建高可用、高性能、高可扩展应用架构的基石。消息队列(MQ)、数据库(如MySQL)、缓存(如Redis)等是其中最具代表性的组件。然而,...
- 运维部署方式之——虚机部署
-
标准化使用作業系统:LinuxCentOS7自动化方式通过Ansible系统初始化playbook来管理。目的系统初始化工作是一个简单、繁复的工作,从云网得到的虚拟主机只是一个基础的系统环境,...
你 发表评论:
欢迎- 一周热门
- 最近发表
- 标签列表
-
- oracle位图索引 (63)
- oracle批量插入数据 (62)
- oracle事务隔离级别 (53)
- oracle 空为0 (50)
- oracle主从同步 (55)
- oracle 乐观锁 (51)
- redis 命令 (78)
- php redis (88)
- redis 存储 (66)
- redis 锁 (69)
- 启动 redis (66)
- redis 时间 (56)
- redis 删除 (67)
- redis内存 (57)
- redis并发 (52)
- redis 主从 (69)
- redis 订阅 (51)
- redis 登录 (54)
- redis 面试 (58)
- 阿里 redis (59)
- redis 搭建 (53)
- redis的缓存 (55)
- lua redis (58)
- redis 连接池 (61)
- redis 限流 (51)