Redis设计与实现 --- 数据结构

原Blog:http://blog.csdn.net/bruce128/article/details/47361913#t0

第2章 简单动态字符串

redis里面的字符串对象都采用SDS结构实现。SDS有别于C风格的字符数组和java的String(定长)。这种结构更像C++的String或者java的ArrayList<Character>。长度动态可变。

redis的所有键值及字符串字面量都采用这种结构。

typedef char *sds;

struct sdshdr {
        // 记录 buf 数组中已使用字节的数量
        // 等于 SDS 所保存字符串的长度
        int len;
        // 记录 buf 数组中未使用字节的数量
        int free;
        // 字节数组,用于保存字符串
        char buf[];
};


第3章 链表

redis的list结构采用双向链表实现。这章花大几页讲链表,感觉在扯《数据结构》。有空直接跳过这章,看java的LinkedList源码吧。

第4章 字典

redis的数据库和哈希键采用字典数据结构底层实现。redis采用的字典,确切的说就是java里的HashMap或者C++里的hash_map。

第5章 跳跃表

redis的有序集合键的底层使用的是跳表。跳表的查找时间复杂度是LogN,可以和平衡二叉树相当。但是平衡二叉树实现略复杂,所以redis就采用了实现上稍简单的skiplist。

第6章 整数集合

如果一个集合里面的所有元素都是整数,那么redis底层会采用整数集合这个数据结构。
[sql]  view plain  copy
  1. 127.0.0.1:6379> sadd num 1 2 3 4 5 6 7  
  2. (integer) 7  
  3. 127.0.0.1:6379> object encoding num  
  4. "intset"  

    inset这个struct结构里的整数数组的类型可以是16位的,32位的,64位的。当数组里所有的整数都是16位长度的,如果新加入一个32位的整数,那么整个16的数组将升级成一个32位的数组。只有升级操作,没有对应的降级操作。
    整数数组里数据是有序的。

第7章 压缩列表
    列表键只包含少量列表项,并且每个列表项是小整数值或较短的支符串,那么Redis就会使用压缩列表来做列表键的底层实现

第8章 对象

    redis是用C语言实现的系统,跟redis谈对象比较牵强。redis用struct结构体定义对象。redis数据库依赖字符串对象,列表对象,哈希表对象,有序表对象和集 合对 象5种对象构成。
    redis种每个对象都由redisObject结构表示。定义如下
[cpp]  view plain  copy
  1. typedef struct redisObject {  
  2.     unsigned type;  
  3.     unsigned encoding;  
  4.     void *ptr;  
  5. }  

    type只可能是刚刚说的5种对象的一种,ptr指针则执行对象的真正位置。
    通过type命令可以查出redis键到底属于5种对象的哪一种。示例如下:
[plain]  view plain  copy
  1. 127.0.0.1:6379> hmset profile  addr chengdu country china company jd  
  2. OK  
  3. 127.0.0.1:6379> type profile  
  4. hash  

    5种类型的对象,每种都有自己特殊的命令,这些特殊的命令无法用到其他对象上。如,不可能对一个哈希表进行rpush。因此,每执行一条命令,服务器首先会进行类型检查。书上说type,del等命令是多态命令,还真是扯淡啊。C语言是函数式语言,跟多态八竿子打不着。

    内存回收

    C/C++都不具备Java/C#的内存回收机制。redis才用了一种引用计数法的技术实现了内存回收。但是引用计数法的一个致命弱点就是,如果遇到循环引用,那么循环引用的对象将永不被回收。因此造成内存泄露。所以JVM摒弃这个内存回收技术,采用根路径可达算法。
    可能redis对象简单,不会被循环依赖所以采用这种方式吧。书中对内存回收讲的很少,后面我自己再研究研究。

    对象共享

    如果redis需要产生两个相同的对象,那么redis只会产生一个数据,让两个对象的指针指向这个数据对象。于是对象被共享。
[plain]  view plain  copy
  1. 127.0.0.1:6379> set a 100  
  2. OK  
  3. 127.0.0.1:6379> object refcount a  
  4. (integer) 2  
  5. 127.0.0.1:6379> set b 100  
  6. OK  
  7. 127.0.0.1:6379> object refcount a  
  8. (integer) 3  

    refcount表示对象的数据被引用了几次。

    redisObject结构体还有一个字段,lru,这个字段记录了对象最后一次被客户端访问的时间。object idletime 会用当前时间减去对象的lru时间。
[plain]  view plain  copy
  1. 127.0.0.1:6379> set a 100  
  2. OK  
  3. 127.0.0.1:6379> object idletime a  
  4. (integer) 4  
  5. 127.0.0.1:6379> object idletime a  
  6. (integer) 9  


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值