介绍
Redis是一个基于内存的数据库,所有的数据都存储在内存中,所以如何优化存储,减少内存空间占用对成本控制来说是非常重要的。精简键名和键值是最直观的减少内存占用的方式,而Redis则是通过内部编码规则来节省更多的内存空间。
Redis为每种数据类型都提供了两三种内部编码方式,以散列类型为例,散列类型是通过散列表实现的,这样就可以实现0(1)时间复杂度的查找、赋值操作,然而当键中元素很少的时候,0(1)的操作并不会比0(n)有明显的性能提高,所以这种情况下Redis会采用一种更为紧凑但性能稍差(获取元素的时间复杂度为0(n))的内部编码方式。内部编码方式的选择对于开发者来说是透明的,Redis会根据实际情况自动调整。当键中元素变多时Redis会自动将该键的内部编码方式转换成散列表。
一、Redis DB数据结构
Redis中是有16个redisDB库,默认是使用第一个。我们先来看下redisDB的数据结构:
dict:字典
dictht:就是一个hashtable,以o(1)时间复杂度获取size,used当前数组里面用掉了多少空间
dictEntry:数组里面的元素,**table指针指向数组,redis中所有的key都是存在dictEntry中
*var:存储key的值,也是一个指针,指向redisObject结构进行数据存储,这个指针指向真实的数据存储
next:当key发生hash冲突时(比如都是数组0),通过next指针建立一个单向的链表解决hash冲突
robj字段介绍:
type:对外的数据类型,string,list,hash,set,zset等
encoding:内部编码,raw,int,ziplist等,对内存利用率极致追求
LRU_BITS:内存淘汰策略
refcount:redis内存管理需要
*ptr:指向真实的数据存储结构,ziplist等,最终指向数据编码的对象
二、内部编码方式
下面是Redis数据结构与内部编码的关系:
查看一个键的内部编码方式:
127.0.0.1:6379> set foo barOK127.0.0.1:6379> object encoding foo"raw"
Redis的每个键值都是使用一个redisObject结构体保存的,在redis.h中声明的redisObj定义的如下:
typedef struct redisObject { unsigned type:4; /** 4 bit */ unsigned encoding:4; /** 4 bit */ unsigned lru:LRU_BITS; /** 24 bit */ int refcount; /** 4 byte */ void * ptr; /** 8 byte */}robj;
其中type字段表示的是键值的数据类型,取值可以是如下内容:
#define REDIS_STRING 0 #define REDIS_LIST 1 #define REDIS_SET 2 #define REDIS_ZSET 3 #define REDIS_HASH 4
encoding字段表示的就是Redis键值的内部编码方式,取值可以是:
#define REDIS_ENCODING_RAW 0 /** Raw representation */ #define REDIS_ENCODING_INT 1 /** ed as integer */ #define REDIS_ENCODING_EMBSTR 2 /** cpu cache line */ #define REDIS_ENCODING_HT 3 /** Encoded as hash table */ #define REDIS_ENCODING_ZIPMAP 4 /** Encoded as zipmap */ #define REDIS_ENCODING_QUICKEDLIST 5 /** Encoded as regular quicked list */ #define REDIS_ENCODING_ZIPLIST 6 /** Encoded as ziplist */ #define REDIS_ENCODING_INTSET 7 /** Encoded as intset */ #define REDIS_ENCODING_SKIPLIST 8 /** Encoded as skiplist */
各个数据类型可能采用的内部编码方式以及相应的OBJECT ENCODING命令执行结果如下:
数据类型 | 内部编码方式 | OBJECT ENCODING命令结果 |
字符串类型 | REDIS_ENCODING_RAW | "raw" |
REDIS_ENCODING_INT | "int" | |
REDIS_ENCODING_EMBSTR | "embstr" | |
散列类型 | REDIS_ENCODING_HT | "hashtable" |
REDIS_ENCODING_ZIPLIST | "ziplist" | |
列表类型 | REDIS_ENCODING_QUICKEDLIST | "quickedlist" |
REDIS_ENCODING_ZIPLIST | "ziplist" | |
集合类型 | REDIS_ENCODING_HT | "hashtable" |
REDIS_ENCODING_INTSET | "intset" | |
有序集合类型 | REDIS_ENCODING_SKIPLIST | "skiplist" |
REDI |