redis底层数据结构 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 typedef  struct  redisObject {unsigned  type:4 ;unsigned  encoding:4 ;void  *ptr;int  refcount;unsigned  lru:22 ;struct  sdshdr  {unsigned  int  len;unsigned  int  free;char  buf[];
获取编码类型:
1 object  encoding str  //获取str 的编码类型
redis支持的编码:
int、embstr、raw 
linkedlist 
ziplist 
hashtable 
intset 
skiplist 
 
1 字符串 字符串的长度不能超过512M。
内部编码有3种,int(8字节长整型)/embstr(小于等于39字节字符串,redis3.2之后使44字节)/raw(大于39个字节字符串,redis3.2是44字节)
1 2 3 4 5 SDS_TYPE_5 
1.1  int 数字型字符串(long):最大值=2^(8x8-1)-1=9223372036854775807
incr/decr/incrby/decrby 数字操作,一定要是数字才能进行加减,当操作的结果大于long的最大值时会报错。
1 2 3 4 5 6 7 8 127.0.0.1:6379 > set str 9223372036854775807 127.0.0.1:6379 > object encoding str"int" 127.0.0.1:6379 > set str 9223372036854775808 127.0.0.1:6379 > object encoding str"embstr" 
问题:当 int 编码保存的值不再是整数,或大小超过了long的范围时,自动转化为raw。 
1 2 3 4 5 6 127.0.0.1:6379 > set str 9223372036854775807 127.0.0.1:6379 > object encoding str"int" 127.0.0.1:6379 > incr str
上面的问题我没有测试成功,当超过long的最大值,就会报错。
1 2 3 4 127 .0 .0 .1 :6379 > set str 1 OK 127 .0 .0 .1 :6379 > debug object strValue  at:00007 FA524C0D370 refcount:8  encoding:int serializedlength:2  lru:3830714  lru_seconds_idle:5562 
1.2 embstr 优点:创建时少分配一次空间,删除时释放一次空间,数据相连查找方便。
缺点:字符串的长度增加需要重新分配内存时,整个redisObject和sds都需要重新分配空间,因此redis中的embstr实现为只读。
embstr,这种形式使得 RedisObject和SDS 内存地址是连续的。 
64字节,减去RedisObject头信息19字节,再减去3字节SDS头信息,剩下45字节,再去除\0结尾。这样最后可以存储44字节。 
1 2 3 4 127.0.0.1:6379 > set str a127.0.0.1:6379 > object encoding str"embstr" 
在对embstr对象进行修改时,都会先转化为raw再进行修改,因此,只要是修改embstr对象,修改后的对象一定是raw的,无论是否达到了44个字节。 
1 2 3 4 5 6 7 8 9 10 11 12 127.0.0.1:6379 > set str a127.0.0.1:6379 > get str"a" 127.0.0.1:6379 > object encoding str"embstr" 127.0.0.1:6379 > append str b2 127.0.0.1:6379 > get str"ab" 127.0.0.1:6379 > object encoding str"raw" 
1.3 raw embstr与raw都使用redisObject和sds保存数据 ,区别:
embstr的使用只分配一次内存空间(因此redisObject和sds是连续的 ) 
raw需要分配两次内存空间(分别为redisObject和sds分配空间)  
 
2 list Redis 列表是简单的字符串列表,按照插入顺序排序。可以添加一个元素导列表的头部(左边)或者尾部(右边)。它的底层实际是个链表。
1 2 3 4 简介:列表(list )类型是用来存储多个有序的字符串,一个列表最多可以存储2 ^32 -1 个元素。lrange  key start end
2.1 linkedlist 2.2 ziplist 
1、列表保存元素个数小于512个 
2、每个元素长度小于64字节 
 
 不能满足这两个条件的时候使用 linkedlist 编码。
 两个条件可以在redis.conf 配置文件中的 list-max-ziplist-value选项和 list-max-ziplist-entries 选项进行配置。
1 2 3 4 5 6 7 8 127.0.0.1:6379 > lpush strs 1 1 127.0.0.1:6379 > object encoding strs"ziplist" 127.0.0.1:6379 > lpush strs 1222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa2 127.0.0.1:6379 > object encoding strs"linkedlist" 
1 2 3 4 5 6 7 8 9 typedef  struct  zlentry  {unsigned  int  prevrawlensize; unsigned  int  prevrawlen;     unsigned  int  lensize;        unsigned  int  len;            unsigned  int  headersize;     unsigned  char  encoding;      unsigned  char  *p;            
3 hash 1 2 3 4 5 简介:在Redis中,哈希类型是指v(值)本身又是一个键值对(k-v)结构field  value 、hget key field field ,建议使用hmget。
3.1 ziplist 3.2 hashtable hashtable 编码的哈希表对象底层使用字典数据结构,哈希对象中的每个键值对都使用一个字典键值对。
使用ziplist(压缩列表)编码:
1、列表保存元素个数小于512个, set-max-intset-entries 进行修改 
2、每个元素长度小于64字节 
 
4 set 1 2 3 4 5 简介:集合(set )类型也是用来保存多个的字符串元素,但是不允许重复元素lrange 、hgetall都属于比较重的命令,如果元素过多存在阻塞Redis的可能性,可以使用sscan来完成。
4.1 intset 使用 intset 编码条件:
1、集合对象中所有元素都是整数 
2、集合对象所有元素数量不超过512 ,可以set-max-intset-entries 进行配置 
1 2 3 4 5 6 7 8 9 10 127.0.0.1:6379 > sadd set1 1 1 127.0.0.1:6379 > smembers set11 ) "1" 127.0.0.1:6379 > object encoding set1"intset" 127.0.0.1:6379 > sadd set1 a1 127.0.0.1:6379 > object encoding set1"hashtable" 
4.2 hashtable 5 zset 
简介:已排序的字符串集合,同时元素不能重复 
简单格式举例:zadd key score member [score member ...],zrank key member 
底层内部编码:ziplist(压缩列表)、skiplist(跳跃表) 
应用场景:排行榜,社交需求(如用户点赞) 
 
 
与列表使用索引下标作为排序依据不同,有序集合为每个元素设置一个分数(score)作为排序依据。 
5.1 ziplist  ziplist 编码的有序集合对象使用压缩列表作为底层实现,每个集合元素使用两个紧挨在一起的压缩列表节点来保存,第一个节点保存元素的成员,第二个节点保存元素的分值。并且压缩列表内的集合元素按分值从小到大的顺序进行排列,小的放置在靠近表头的位置,大的放置在靠近表尾的位置。 
使用 ziplist 编码条件:
1、保存的元素数量小于128; 
2、保存的所有元素长度都小于64字节。 
 
可以通过Redis配置文件zset-max-ziplist-entries 选项和 zset-max-ziplist-value 进行修改。
1 2 3 4 5 6 7 8 9 10 11 12 13 127.0.0.1:6379 > zadd zset1 0 .1  1 1 127.0.0.1:6379 > zadd zset1 0 .2  2 1 127.0.0.1:6379 > object encoding zset1"ziplist" 127.0.0.1:6379 > zadd zset1 0 .3  a1 127.0.0.1:6379 > object encoding zset1127.0.0.1:6379 > zadd zset1 0 .4  aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa1 127.0.0.1:6379 > object encoding zset1"skiplist" 
5.2 skiplist skiplist 编码的有序集合对象使用 zet 结构作为底层实现,一个 zset 结构同时包含一个字典和一个跳跃表: 
1 2 3 4 5 6 7 typedef struct  zset {* zsl;dict  * dice;