zoukankan      html  css  js  c++  java
  • redis基础数据结构及编码方式

    redis基础数据结构和编码方式

    一、底层数据结构

    1)简单动态字符串

    2)双端链表

    3)字典

    4)跳跃表

    5)整数集合

    6)压缩列表

    二、对象类型与编码

      在redis的数据库中创建一个新的键值对时,总是创建两个对象,一个存储键,一个存储值。

    对象的数据结构如下

    typedef struct redisObject{

      unsigned typed:4;

      ungigned encoding:4;

      void *ptr;

    }robj;

    类型常量对应的对象名称

      1)REDIS_String:  字符串对象

      2)REDIS_LIST:    列表对象

      3)REDIS_HASH: 哈希对象

      4)REDIS_SET:    集合对象

      5)REDIS_ZSET: 有序集合对象

    编码和底层实现

      1)REDIS_ENCODING_INT:       long类型的整数(长度不超过32位的整数)

      2)REDIS_ENCODING_EMBSTR:    简单动态字符串(3.2版本 小于44字节(之前是39:https://www.zhihu.com/question/25624589))

      3)REDIS_ENCODING_RAW:      简单动态字符串(3.2版本 大于44字节)

      4)  REDIS_ENCODING_HT:       字典

      5)REDIS_ENCODING_LINGKEDLIST:  双端链表

      6)REDIS_ENCODING_ZIPLIST:     压缩列表

      7)REDIS_ENCODING_INTSET:     整数集合

      8)REDIS_ENCONDING_SKIPLIST :   跳跃表和字典

    三、 字符串对象

    1、字符串的编码:

    字符串对象的编码可以是int、raw或者embstr。

      1)如果一个字符串对象保存的是整数值,并且这个整数值可以用lon类型表示,那么字符串对象将整数值保存在字符串对象结构的ptr属性里面(将void*转换成long),并将字符串对象的编码方式设置为int。

      2)如果字符串对象保存的是一个字符串值,并且这个字符串值的长度大于32字节,那么字符串对象将使用一个简单动态字符串保存这个值,并将对象的编码设置为raw。

      3)如果字符串对象保存的是一个字符串值,并且这个字符串值的长度小于32字节,那么字符串对象将使用embstr编码的方式来保存这个字符串值。

    2、编码的转换

      int编码和embstr编码的字符串对象在满足条件的情况下,会转换为raw编码的字符串对象。

      1)int编码转为raw编码:原对象保存的值不再是整数值,而是一个字符串值,那么会发生编码从int变为raw

      2)redis没有为embstr编码的字符串对象编写任何相应的修改程序(只有int转为raw),所以,embstr编码字符串实际上是只读的,当对embstr编码的字符从执行修改命令时,

      程序会先将对象的embstr转换成raw,然后再执行修改命令。(embstr编码的字符串对象执行APPEND命令后,对象的编码会从embstr变为raw)。

    四、列表对象

    1、列表对象的编码:

      列表对象的编码可以是ziplist或者linkedlistziplist编码的列表对象使用压缩列表作为底层实现,每个压缩列表节点保存一个列表节点。linkedlist编码的列表对象使用双端链表作为底层

    实现。每个双端链表节点(node)都保存一个字符串对象,而每个字符串对象都保存了一个列表元素。

    2、编码的转换

    当列表对象可以同时满足一下两个条件时,列表对象使用ziplist编码,不能满足这两个条件的列表对象需要使用linkedlist编码。

      1)列表对象保存的所有字符串元素的长度都小于64字节

      2)列表对象保存的元素数量小于512个,

    五、哈希对象

    1、哈希对象的编码:

      哈希对象的编码可以是ziplist或者hashtable。

      1)ziplist编码的哈希对象使用压缩列表作为底层实现,每当有新的键值对要加入到哈希对象时,程序会先将保存了键的压缩列表节点推入到压缩列表表尾,然后再将保存了值的压缩列表节点推入压缩列表表尾。因此

    1. 保存了同一键值对的两个节点总是紧挨在一起,保存键的节点在前,保存值的节点在后;
    2. 先添加到哈希对象中的键值对会放在压缩列表的表头方向,而后添加的哈希对象中的键指对会被放在压缩列表的链表方向。

      2)hashtable编码的哈希对象使用字典作为底层实现,哈希对象中的每个键值对都使用一个字典键值对来保存

    1. 字典的每个键都是一个字符串对象,对象中保存了键值对的键。
    2. 字典中每个值都是一个字符串对象,对象中保存了键值对的值。

    2、编码的转换

      当哈希对象可以同时满足以下两个条件时,哈希对象使用ziplist编码,否则使用hashtable编码

      1)哈希对象保存的所有键值对的键和值的字符串长度都小于64个字节

      2)哈希对象保存的键值对数量小于512个。

    六、集合对象

    1、集合对象的编码:

      集合对象的编码可以时intset或者hashtable

      1)intset编码的集合对象使用整数集合作为底层实现,集合对象包含的所有元素都被保存在整数集合里面。

      2)hashtable编码的集合对象使用字典作为底层实现,字典的每个键都是一个字符串对象,每个字符串对象都包含一个集合元素,而字典的值则被全部设置为NULL。

    2、编码的转换

      同时满足两个条件使用intset,否则使用hashtable

      1)集合对象保存的所有值都是整数值

      2)集合对象保存的元素数量不超过512个

    七、有序集合对象

    1、有序集合对象的编码:

      有序集合对象的编码可以时ziplist或者skiplist

      1)ziplist编码的压缩列表对象使用压缩列表作为底层实现,每个集合元素使用两个紧挨在一起的压缩列表节点来保存,第一个节点保存元素的成员(member),第二个元素保存元素的分值(score)

      压缩列表内的集合元素按照分值从小到大进行排序,分值较小的元素被放置在靠近表头的方向,而分值较大的元素则放置在靠近表尾的方向。

      2)skiplist编码的有序集合对象使用zset结构作为底层实现,一个zset结构同时包含一个字典和一个跳跃表。

    1. zset结构中的zsl跳跃表按分值从小到大保存了所有集合元素,每个跳跃表节点都保存一个集合元素:跳跃表即诶单的object属性保存了元素成员,而跳跃表节点的score属性则保存了元素的分值。

      通过跳跃表,程序可以对有序集合进行范围型操作,比如ZRANK、ZRANGE等命令就是基于跳跃表API来实现的

       2. zset结构中的dict字典为有序集合创建了一个从成员到分值的映射,字典中的每个键值对都保存了一个集合元素:字典的键保存了元素的成员,而字典的值则保存了元素的分值。通过字典,程序

      可以用O(1)复杂度查找给定成员的分值,ZSCORE命令就是根据这一特性是实现的。

    2、编码的转换

      同时满足一下两个条件使用ziplist,否则使用skiplist

      1)有序集合所保存的所有元素成员的长度都小于64字节

      2)有序集合保存的元素数量小于128个

    参考:《redis设计与实现》

    字符串对象将使用一个简单动态字符串保存这个值,并将对象的编码设置为raw。

  • 相关阅读:
    QT4.8.7和VS2010环境搭建及使用
    SQL Server--获取磁盘空间使用情况
    SQL SERVER--DBA 常用到的一些脚本
    MySQL--REPLACE INTO与自增
    MySQL--更新自增列的潜在风险
    MySQL--Skip GTID CAP
    MySQL--MHA与GTID
    MySQL--自增列学习
    MySQL--MHA原理
    MySQL--BNL/ICP/MRR/BKA
  • 原文地址:https://www.cnblogs.com/socks/p/11726602.html
Copyright © 2011-2022 走看看