[redis读书笔记] 第一部分 数据结构与对象 对象以及总结
Posted jiangz222
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[redis读书笔记] 第一部分 数据结构与对象 对象以及总结相关的知识,希望对你有一定的参考价值。
- 从前面redis的基本数据结构来看,可以看出,redis都是在基本结构(string)的基础上,封装了一层统计的结构(SDS),这样让对基本结构的访问能够更快更准确,提高可控制度。
- redis的键值对中,键必然是用字符串对象实现的,所以我们一般说的列表键,指的是字符串键+列表值。
- 但是redis并没用这些数据结构直接实现redis的键值数据库,而是基于这些数据结构有一个对象系统,这个系统包括:字符串对象,列表对象,哈希对象,集合对象和有序集合对象,每一种对象都可能用到一到多种基本的数据结构。对象的实现如下:
typedef struct redisObject { // 类型 unsigned type:4; // 编码 unsigned encoding:4; // 对象最后一次被访问的时间 unsigned lru:REDIS_LRU_BITS; /* lru time (relative to server.lruclock) */ // 引用计数 int refcount; // 指向实际值的指针 void *ptr; } robj;
其中,type指的是对象类型,encoding指的是下面实现的具体数据结构的类型,*ptr指向实现的数据结构,refcount用来做内存回收。
对于某一种对象,它的type是固定的,但是encoding是可以变化的,比如type为REDIS_STRING,encoding可以是RAW(SDS)或者INT,具体组合如下图所示:
这样做的好处是,针对一种固定的type,redis可以根据需要切换底层数据结构实现,从而达到效率最大化:
接下来分析一下各个对象
- 字符串对象:
实现较为简单,对于RAW的编码实现,如下图:
embstr也是使用redisobject和sdshdr,但是和raw编码相比,有一个优势,raw的编码会为redisobject和SDS分配两次内存,而embstr会直接分配一个内存给两个结构用,那么释放的时候也就只要释放一次,同时,由于在同一个内存里,利用缓存来提高访问速率也有优势,
二 列表对象:
总的来说,如果列表对像的存储内容较小,使用ziplist的实现,如果较大,使用双向列表(即前面章节里的链表结构)的实现,双向列表实现较复杂,适合大量数据,方便管理。而ziplist的实现节省空间,但是查找的复杂度是o(N),所以大据量打了并不适合用ziplist。(adlist其实查找也是o(N))
三 哈希对象
哈希对象的编码可以使ziplist或者hashtable,比如下面的输入:
分别ziplist和hash table的实现是:
ziplist依然是用于键值对数量小的情况,或者字符串长度较小的情况,因为节省内存,线性分布易于缓存。hashtable查找快,所以利于大数据量
四 集合对象
集合对象可以用hashtable和intset实现:
数据量小或者素有元素都是整数值时,使用intset,否则使用hashtable,使用hashtable主要还是查找快。
五 有序集合:
如下图所示,有序结合对象,会同时使用字典和ziplist/skiplist两种实现,但是实际的成员和分值都是共享的,所以不会有内存浪费,使用字典为了查找更快,使用ziplist/skiplist,为了更快的进行list的范围型操作更快速(比如获取长度等)
以上是关于[redis读书笔记] 第一部分 数据结构与对象 对象以及总结的主要内容,如果未能解决你的问题,请参考以下文章