Redis学习日志(二)

来源:互联网 发布:手机熊猫登录网络 编辑:程序博客网 时间:2024/06/08 04:17

10. 对象

Redis对象系统结构 string(字符串),hash(哈希),list(列表),set(集合)及zset(有序集合)。
五种类型对象的构建用到了以上的主要数据结构:简单动态字符串、双端链表、字典、压缩列表、整数集合。
Redis中的键值对,键总是一个字符串对象,值可以是五种对象中的一种。
“字符串键”指key-value 中的value是字符串对象类型
“列表键”指key-value 中的value是列表对象类型

    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属性值 TYPE命令输出 字符串对象 REDIS_STRING “string” 列表对象 REDIS_LIST “list” 哈希对象 REDIS_HASH “hash” 集合对象 REDIS_SET “set” 有序集合对象 REDIS_ZSET “zset”

对象的ptr指针指向对象的底层实现数据结构,由对象的encoding属性决定。

编码常量 底层数据结构 REDIS_ENCODING_INT long类型整数 REDIS_ENCODING_EMBSTR embstr编码的简单动态字符串 (长度<=32字节) REDIS_ENCODING_RAM 简单动态字符串 REDIS_ENCODING_HT 字典 REDIS_ENCODING_LINKEDLIST 双端链表 REDIS_ENCODING_ZIPLIST 压缩列表 REDIS_ENCODING_INTSET 整数集合 REDIS_ENCODING_SKIPLIST 跳跃表和字典
        /*默认以RAW字符编码,若需要调整则在调用处显式更改 */        robj *createObject(int type, void *ptr) {            robj *o = zmalloc(sizeof(*o));            o->type = type;            o->encoding = REDIS_ENCODING_RAW;            o->ptr = ptr;            o->refcount = 1;            /* Set the LRU to the current lruclock (minutes resolution). */            o->lru = LRU_CLOCK();            return o;        }           /* 创建一个 ZIPLIST 编码的列表对象  */        robj *createZiplistObject(void) {            unsigned char *zl = ziplistNew();            robj *o = createObject(REDIS_LIST,zl);            o->encoding = REDIS_ENCODING_ZIPLIST; //显式更改编码            return o;        }

11. 字符串对象

字符串对象的编码可以是int embstr raw
根据不同的操作,会将值的编码进行转换。
字符串命令和对应编码操作:(具体命令及方式见图8-7字符串命令及操作)
这里写图片描述

命令 意义 SET 以对应编码保存值 GET 以字符串形式返回值 APPEND 以字符串形式追加值 INCRBYFLOAT 将值转换成浮点数进行计算保存 INCRBY 对整数进行加法计算保存 DECRBY 对整数进行减法计算保存 STRLEN 返回对应值的字符串长度 GETRANGE 获取对应值的字符串形式,及其索引字符

12.列表对象

      列表对象的编码可以是ziplist linkedlist        redis>RPUSH members 1 "three" 5        (integer)3    1)若为ziplist编码:        |redisObject        |type=REDIS_LIST        |encoding=REDIS_ENCODING_ZIPLIST        |ptr        ---->|zlbytes|zltail|zllen|1|"three"|5|zlend|        |...    2)若为linkedlist编码:     双端链表中每个节点是一个StringObject,每个StringObject的编码根据对应的值决定        |redisObject        |type=REDIS_LIST        |encoding=REDIS_ENCODING_LINKEDLIST        |ptr        ---->|StringObject:1|StringObject:"three"|StringObject:5|        |...    列表对象采用ziplist编码的条件:(两个都需要满足)    ①列表对象保存的所有字符串元素长度都小于64字节    ②列表对象保存的元素数量小于512个    若不能满足以上两个条件,则采用linkedlist编码。
    列表命令及相应编码操作:(具体见图8-8列表命令及操作)        LPUSH        RPUSH        LPOP        RPOP        LINDEX        LLEN        LINSERT        LREM        LTRIM        LSET

这里写图片描述

13.哈希对象

    哈希对象编码可以是ziplist hashtable        redis> HSET profile name "tom"        (integer)1        redis> HSET profile age 25        (integer)1        redis> HSET profile career "programmer"        (integer)1    1)ziplist编码:当有新键值对要加入时,                   先将保存键的压缩列表节点放置压缩列表表尾,                   再将保存值的压缩列表节点放置压缩列表表尾。      因此同一键值对的节点会紧挨在一起,且先添加入的键值对靠前,后添加的键值对靠后。        |redisObject        |type=REDIS_HASH        |encoding=REDIS_ENCODING_ZIPLIST        |ptr        ---->|zlbytes|zltail|zllen|"name"|"tom"|"age"|25|"career"|"programmer"|zlend|        |...    2)hashtable编码: 每个键值对使用一个字典键值对来保存                      每个键和值都是一个字符串对象。        |redisObject        |type=REDIS_HASH        |encoding=REDIS_ENCODING_HT        |ptr        ----> |dict|        |...              |StringObject:"age"   |-->|StringObject:25|                          |StringObject:"career"|-->|StringObject:"programmer"|                          |StringObject:"name"  |-->|StringObject:"tom"|    哈希对象采用ziplist编码的条件:(两个都需要满足)    ①哈希对象保存的所有键值对的键和值 字符串长度都小于64字节    ②哈希对象保存的键值对数量小于512个    若不能满足以上两个条件,则采用hashtable编码。
    哈希命令及相应编码操作:(具体见图8-9哈希命令及操作)    命令:        HSET        HGET        HEXISTS        HDEL        HLEN        HGETALL

这里写图片描述

14.集合对象:

    集合对象的编码可以是intset hashtable    1)intset编码:保存在整数集合中。        redis> SADD members 1 3 5        (integer)3        |redisObject                    |-> intset        |type=REDIS_SET                 |   encoding=INT16        |encoding=REDIS_ENCODING_INTSET |   length=3        |ptr        ---------------------   contents-->|1|3|5|    1)hashtable编码:字典的每个键都是字符串对象,                     每个字符串对象包含一个集合元素                     字典的值全部设置为null        redis> SADD members "apple" "banana" "cherry"        (integer)3        |redisObject        |type=REDIS_SET        |encoding=REDIS_ENCODING_HT        |ptr        ----> |dict|        |...              |StringObject:"apple" |-->NULL                          |StringObject:"banana"|-->NULL                          |StringObject:"cherry"|-->NULL    集合对象采用intset编码的条件:(两个都需要满足)    ①集合对象保存的所有元素都是整数值    ②集合对象保存的元素数量小于512个    若不能满足以上两个条件,则采用hashtable编码。
    集合命令及相应编码操作:(具体见图8-10集合命令及操作)    命令:        SADD        SCARD        SISMEMBER        SMEMBERS        SRANDMEMBER        SPOP        SREM

这里写图片描述

15.有序集合:

有序集合对象的编码可以是ziplist skiplistredis> SADD members  "apple" 8.0 "banana" 5.0 "cherry" 9.0(integer)3
1)ziplist编码: 当有新键值对要加入时,会对分值低的键值对先插入                先将保存键的压缩列表节点放置压缩列表表尾,                再将保存值的压缩列表节点放置压缩列表表尾。      因此同一键值对的节点会紧挨在一起,分值低的元素靠前,分值高的靠后。        |redisObject        |type=REDIS_ZSET        |encoding=REDIS_ENCODING_ZIPLIST        |ptr        ---->|zlbytes|zltail|zllen|"banana"|5.0|"apple"|8.0|"cherry"|9.0|zlend|        |...2)skiplist编码: 使用zset结构作为底层实现,zset结构包含一个字典和跳跃表        typedef struct zset{            zskiplist *zsl;            dict *dict;        }zset;    zset结构中的zsl跳跃表按分值从小到大保存所有集合元素,每个跳跃表节点都保存了一个集合元素    跳跃表节点的object属性保存元素的成员,score属性保存元素分值。    zset结构中dict字典为有序集合创建了一个从成员到分值的映射,字典每个键值对都保存一个集合元素(成员对象和它的分值)    有序集合每个元素的成员都是字符串对象,元素的分值都是double类型浮点数。    (跳跃表和字典都通过指针共享相同元素的成员和分值,不会有重复元素副本)
为什么有序集合zset结构同时使用跳跃表和字典来实现?    答:有序集合需要满足 有序、查找 等功能        单独使用跳跃表实现,能够保证有序及范围型操作功能,但在根据成员查找分值操作时复杂度为O(logN)        单独使用字典实现,能够保证成员和分值映射查找复杂度为O(1) 但不能以有序方式保存集合元素。skiplist编码的有序集合实现方式,见图8-16skiplist编码有序集合对象
有序集合对象采用ziplist编码的条件:(两个都需要满足)①有序集合对象保存的所有元素成员长度小于64字节②有序集合对象保存的元素数量小于128个若不能满足以上两个条件,则采用skiplist编码。
有序集合命令及相应编码操作:(具体见图8-11有序集合命令及操作)    命令:        ZADD        ZCARD        ZCOUNT        ZRANGE        ZREVRANGE        ZRANK        ZREVRANK        ZREM        ZSCORE

这里写图片描述