redis中的对象

1、结构

type占4位,encoding占4位,lru占24位。lru表示LRU time时指的是对于全局lru_clock的相对时间,表示LFU data时,低8位表示频率,高16位表示访问时间。

2、类型及编码

(1)String

字符串对象的编码可以是int,embstr, raw。

如果一个字符串对象保存的整数值,并且这个整数值可以用long类型来表示,会将整数值保存到ptr属性里面,并将编码设置为int

如果字符串长度小于等于44,并且编码是raw,则转成embstr。embstr编码是通过一次内存分配,将redisObject和sdshdr分配好

robj *tryObjectEncoding(robj *o) {
    long value;
    sds s = o->ptr;
    size_t len;

    /* Make sure this is a string object, the only type we encode
     * in this function. Other types use encoded memory efficient
     * representations but are handled by the commands implementing
     * the type. */
    serverAssertWithInfo(NULL,o,o->type == OBJ_STRING);

    /* We try some specialized encoding only for objects that are
     * RAW or EMBSTR encoded, in other words objects that are still
     * in represented by an actually array of chars. */
    if (!sdsEncodedObject(o)) return o;

    /* It's not safe to encode shared objects: shared objects can be shared
     * everywhere in the "object space" of Redis and may end in places where
     * they are not handled. We handle them only as values in the keyspace. */
     if (o->refcount > 1) return o;

    /* Check if we can represent this string as a long integer.
     * Note that we are sure that a string larger than 20 chars is not
     * representable as a 32 nor 64 bit integer. */
    len = sdslen(s);
    if (len <= 20 && string2l(s,len,&value)) {
        /* This object is encodable as a long. Try to use a shared object.
         * Note that we avoid using shared integers when maxmemory is used
         * because every object needs to have a private LRU field for the LRU
         * algorithm to work well. */
        if ((server.maxmemory == 0 ||
            !(server.maxmemory_policy & MAXMEMORY_FLAG_NO_SHARED_INTEGERS)) &&
            value >= 0 &&
            value < OBJ_SHARED_INTEGERS)
        {
            decrRefCount(o);
            incrRefCount(shared.integers[value]);
            return shared.integers[value];
        } else {
            if (o->encoding == OBJ_ENCODING_RAW) {
                sdsfree(o->ptr);
                o->encoding = OBJ_ENCODING_INT;
                o->ptr = (void*) value;
                return o;
            } else if (o->encoding == OBJ_ENCODING_EMBSTR) {
                decrRefCount(o);
                return createStringObjectFromLongLongForValue(value);
            }
        }
    }

    /* If the string is small and is still RAW encoded,
     * try the EMBSTR encoding which is more efficient.
     * In this representation the object and the SDS string are allocated
     * in the same chunk of memory to save space and cache misses. */
    if (len <= OBJ_ENCODING_EMBSTR_SIZE_LIMIT) {
        robj *emb;

        if (o->encoding == OBJ_ENCODING_EMBSTR) return o;
        emb = createEmbeddedStringObject(s,sdslen(s));
        decrRefCount(o);
        return emb;
    }

    /* We can't encode the object...
     *
     * Do the last try, and at least optimize the SDS string inside
     * the string object to require little space, in case there
     * is more than 10% of free space at the end of the SDS string.
     *
     * We do that only for relatively large strings as this branch
     * is only entered if the length of the string is greater than
     * OBJ_ENCODING_EMBSTR_SIZE_LIMIT. */
    trimStringObjectIfNeeded(o);

    /* Return the original object. */
    return o;
}

set key value [EX seconds| PX milliseconds|KEEPTTL] [NX|XX] [GET]

EX seconds:设置超时时间,单位s

PX :milliseconds:设置超时时间,单位ms

NX:如果key不存在则设置

XX:如果key存在则设置

KEEPTTL:保留key相关的超时时间

GET:当设置新值时,返回旧值;如果key不存在,则返回nil

(2)List

使用的编码是quicklist

命令说明实现
LPUSH key element [element ...]插入一个或者多个元素到列表头中quicklistPush(subject->ptr, value->ptr, len, QUICKLIST_HEAD)
RPUSH key element [element ...]插入一个或者多个元素到列表尾中quicklistPush(subject->ptr, value->ptr, len, QUICKLIST_TAIL)
LPUSHX key element [element ...]列表存在时插入一个或者多个元素到列表头中
RPUSHX key element [element ...]列表存在时插入一个或者多个元素到列表尾中
LINSERT key BEFORE|AFTER pivot element在列表中的元素pivot前或者后插入元素从头到尾开始扫描,确定pivot,然后确定quicklistInsertAfter/quicklistInsertBefore
LLEN key获取列表长度

quicklistCount

LINDEX key index获取列表下标为index的元素

quicklistIndex

LSET key index element设置列表下标为key的元素为element

quicklistReplaceAtIndex

LPOP key [count]从列表头删除一个或者count个元素

listTypePop/quicklistDelRange

RPOP key [count]从列表尾删除一个或者count个元素
LRANGE key start stop获取列表指定区间范围内的元素首先

listTypeInitIterator确定起始位置,然后遍历listTypeNext

LTRIM key start stop修改列表,保留区间范围内的元素

quicklistDelRange来删除[0,start)和(stop, len]

LPOS key element [RANK rank] [COUNT num-matches] [MAXLEN len]获取元素在列表中的位置。RANK选项指定第几个匹配位置, COUNT选项指定返回的匹配个数,0表示所有的匹配。MAXLEN指定扫描的最大元素个数

listTypeInitIterator来确定起始位置,listTypeNext来遍历

LREM key count element删除列表中count个元素等于element的元素。count >0时表示从头到尾遍历,count<0表示从尾到头遍历,count=0表示删除所有等于element的

listTypeInitIterator来确定起始位置,listTypeNext来遍历,listTypeDelete作删除

LMOVE source destination LEFT|RIGHT LEFT|RIGHT从一个列表删除,添加到另外一个列表中

lmoveGenericCommand

RPOPLPUSH source destination从一个列表尾删除 ,添加到另一个列表头
BLPOP key [key...] timeout从一个或者多个列表头阻塞删除

blockingPopGenericCommand

BRPOP key [key...] timeout从一个或者多个列表尾阻塞删除
BLMOVE source destination LEFT|RIGHT LEFT|RIGHT timeout阻塞操作从一个列表删除,添加到另外一个列表中
BRPOPLPUSH source destination timeout阻塞从一个列表尾删除,添加到另外一个列表头

(3)hash

编码使用ziplist或者hashtable

ziplist转为hashtable条件:

  • key或者value字符串长度大于参数server.hash_max_ziplist_value,默认是64
  • ziplist中的元素个数大于512
命令说明实现
HSETNX key field value如果field不存在则设置

hashTypeExists判断是否存在,hashTypeSet设置字段值

HSET key field value [field value...]设置或者批量设置field value值遍历使用

hashTypeSet来设置

HINCRBY key field increment增加hash表field值+increment调用 

hashTypeSet来添加

HINCRBYFLOAT key field increment给field作浮点数加法
HGET key field获取字段值

hashTypeGetFromZiplist/hashTypeGetFromHashTable

HMGET key field [field...]获取一系列字段值
HDEL key field [field...]删除一个或者多个field

hashTypeDelete

HLEN key获取哈希表总字段数

hashTypeLength

HSTRLEN key field获取哈希表字段field对应值的长度

hashTypeGetValueLength

HKEYS key获取哈希表所有的field
HVALS key获取哈希表所有的values
HGETALL key获取哈希表的所有field-value对
HEXISTS key field判断field在哈希表中是否存在
HSCAN key cursor [MATCH pattern] [COUNT count]

(4)set

编码使用intset或者hashtable

使用intset条件:

  • 元素是整数值并且不超过ULONGLONG(0xffffffffffffffff)
  • 元素数量不超过server.set_max_intset_entries,默认是512
命令说明实现
SADD key memeber [member...]集合中添加一个或者多个成员不存夺时

setTypeCreate创建,添加使用setTypeAdd

SREM key member [member...]删除一个或者多个成员使用

setTypeRemove来删除

SMOVE source destination member将成员从一个集合移动到另外一个集合中
SISMEMBER key member判断是不是集合中成员

setTypeIsMember

SCARD key获取集合成员数

setTypeSize

SPOP key [count]从集合中随机删除一个或者多个成员

setTypeRandomElement获取随机元素,删除使用intsetRemove/setTypeRemove

SRANDMEMBER key [count]随机获取一个或者多个元素

setTypeRandomElement

SINTER key [key...]多个集合的交集读取多个集合,根据集合大小从小到大排序,然后遍历求交集
SINTERSTORE destination key [key...]多个集合的交集,并且将结果存储
SUNION key [key...]求多个集合的并集
SUNIONSTORE destination key [key..]求多个集合的并集并且存储
SDIFF key [key...]集合差集
SDIFFSTORE destination key [key...]集合差集并且存储
SSCAN key cursor [MATCH pattern] [COUNT count]

(5)有序集合

编码使用ziplist或者skiplist

使用ziplist条件:

元素长度不大于server.zset_max_ziplist_value,元素数量不大于server.zset_max_ziplist_entries

命令说明 实现
ZADD key [NX|XX] [GT|LT] [CH] [INCR] score member [score member...]添加一个或者多个成员,如果存在更新分数
ZINCRBY key increment member添加成员分数
ZREM key member [member...]删除一个或者多个成员

zsetDel

ZREMRANGEBYRANK key start stop删除有序集合中指定rank范围的所有成员
ZREMRANGEBYSCORE key min max删除有序集合中指定分数的成员
ZREMRANGEBYLEX key min max删除有序集合中指定字典序range内的成员

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

kgduu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值