在Redis中会涉及很多数据结构,比如SDS,双向链表、字典、压缩列表、整数集合等等。Redis会基于这些数据结构自定义一个对象系统,而且自定义的对象系统有很多好处。
通过对以下的Redis对象系统的学习,可以了解Redis设计原理以及初衷,为了我们在使用Redis的时候,更加能够理解到其原理和定位问题。
Redis 对象
Redis基于上述的数据结构自定义一个Object 系统,Object结构:
- redisObject结构:
- typedef struct redisObject{
- //类型
- unsigned type:4;
- //编码
- unsigned encoding:4;
- //指向底层实现数据结构的指针
- void *ptr;
- …..
- }
Object 系统包含五种Object:
Redis使用对象来表示数据库中的键和值,即每新建一个键值对,至少创建有两个对象,而且使用对象的具有以下好处:
1. redis可以在执行命令前会根据对象的类型判断一个对象是否可以执行给定的命令
2. 针对不同的使用场景,为对象设置不同的数据结构实现,从而优化对象的不同场景夏的使用效率
3. 对象系统还可以基于引用计数计数的内存回收机制,自动释放对象所占用的内存,或者还可以让多个数据库键共享同一个对象来节约内存。
4. redis对象带有访问时间记录信息,使用该信息可以进行优化空转时长较大的key,进行删除!
对象的ptr指针指向对象的底层现实数据结构,而这些数据结构由对象的encoding属性决定,对应关系:
每种Object对象至少有两种不同的编码,对应关系:
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编码:
1. list对象保存的所有字符串元素的长度都小于64字节
2. list对象保存的元素数量小于512个,
不能满足这两个条件的list对象需要使用linkedlist编码。
Hash对象
Hash对象的编码可以是ziplist或者hashtable
其中,ziplist底层使用压缩列表实现:
hashtable底层使用字典实现,Hash对象种的每个键值对都使用一个字典键值对保存:
比如: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编码:
1. list对象保存的所有字符串元素的长度都小于64字节
2. list对象保存的元素数量小于512个,
不能满足这两个条件的hash对象需要使用hashtable编码
Note:这两个条件的上限值是可以修改的,可查看配置文件hash-max-zaiplist-value和hash-max-ziplist-entries
Set对象:
Set对象的编码可以为intset或者hashtable
inset编码Set对象结构:
- redis> SAD number 1 3 5
hashtable编码Set对象结构:
- redis> SAD Dfruits “apple” "banana" " cherry"
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
skiplist编码的ZSet对象使用了zset结构,包含一个字典和一个跳跃表
- Type struct zset{
- Zskiplist *zsl;
- dict *dict;
- ...
- }
skiplist编码的ZSet对象结构
ZSet对象的编码转换
当ZSet对象同时满足以下两个条件时,对象使用ziplist编码
1. 有序集合保存的元素数量小于128个
2. 有序集合保存的所有元素的长度都小于64字节
不能满足以上两个条件的有序集合对象将使用skiplist编码。
Note:可以通过配置文件中zset-max-ziplist-entries和zset-max-ziplist-vaule
支持多线程的 Redis 6.0 版本于 2020-05-02 终于发布了,为什么 Redis 忽然要支...
1.为什么所有技术人都要懂业务架构 因为业务架构是连接业务与IT的纽带,可以帮助...
本文转载自微信公众号「 小姐姐味道」,转载本文请联系 小姐姐味道公众号。 相对...
阿里云开发者4月走进厦门和无锡 更有阿里云、滴滴等大牛面对面交流 陪你度过这不...
本文转载自微信公众号「KK架构师」,作者wangkai。转载本文请联系KK架构师公众号...
随着Kubernetes和微服务的采用,边缘已从简单的硬件负载平衡器演变为包括API网关...
对于那些希望加强员工队伍以应对冠状病毒大流行的IT领导者来说,再培训正在成为...
作者个人研发的在高并发场景下,提供的简单、稳定、可扩展的延迟消息队列框架,...
医保电子凭证 即日起,医保电子凭证已面向全国开通,覆盖全国13.5亿参保人。用户...
对于那些选择美国云服务器建站的朋友们来说。目前,除了使用美国虚拟主机、美国...