网站备案去哪里备案,宁波论坛建站模板,哈尔滨城乡建设厅网站,wordpress 段落 两格Redis根据基本数据结构构建了自己的一套对象系统。主要包括字符串对象、列表对象、哈希对象、集合对象和有序集合对象 同时不同的对象都有属于自己的一些特定的redis指令集#xff0c;而且每种对象也包括多种编码类型#xff0c;和实现方式。
Redis对象结构
struct redisOb…Redis根据基本数据结构构建了自己的一套对象系统。主要包括字符串对象、列表对象、哈希对象、集合对象和有序集合对象 同时不同的对象都有属于自己的一些特定的redis指令集而且每种对象也包括多种编码类型和实现方式。
Redis对象结构
struct redisObject {unsigned type:4; // 对象类型unsigned encoding:4; // 编码方式unsigned lru:LRU_BITS; // 最后一次的访问时间或者访问频率int refcount; // 对象被引用的次数void *ptr; // 指向底层数据结构实例
};type 分别表示字符串对象、列表对象、集合对象、有序集合对象和哈希对象。
/* The actual Redis Object */
#define OBJ_STRING 0 /* String object. */
#define OBJ_LIST 1 /* List object. */
#define OBJ_SET 2 /* Set object. */
#define OBJ_ZSET 3 /* Sorted set object. */
#define OBJ_HASH 4 /* Hash object. */encoding 同一种对象可以根据元素的类型和大小可以有选择不同的编码方式。
/* Objects encoding. Some kind of objects like Strings and Hashes can be* internally represented in multiple ways. The encoding field of the object* is set to one of this fields for this object. */
#define OBJ_ENCODING_RAW 0 /* Raw representation */
#define OBJ_ENCODING_INT 1 /* Encoded as integer */
#define OBJ_ENCODING_HT 2 /* Encoded as hash table */
#define OBJ_ENCODING_ZIPMAP 3 /* No longer used: old hash encoding. */
#define OBJ_ENCODING_LINKEDLIST 4 /* No longer used: old list encoding. */
#define OBJ_ENCODING_ZIPLIST 5 /* No longer used: old list/hash/zset encoding. */
#define OBJ_ENCODING_INTSET 6 /* Encoded as intset */
#define OBJ_ENCODING_SKIPLIST 7 /* Encoded as skiplist */
#define OBJ_ENCODING_EMBSTR 8 /* Embedded sds string encoding */
#define OBJ_ENCODING_QUICKLIST 9 /* Encoded as linked list of listpacks */
#define OBJ_ENCODING_STREAM 10 /* Encoded as a radix tree of listpacks */
#define OBJ_ENCODING_LISTPACK 11 /* Encoded as a listpack */lru 使用lru可以计算对象的空转时长refcount 对象的引用计数在内存回收时会检查refcountptr 对象实例保存对象的值
类型检查与命令多态
类型检查
有些命令针对不同的对象均适用比如DEL、TTL等但是有些命令仅适用于特定的对象类型比如LLEN只对列表对象适用所以在对对象执行某个命令前需要检查对象类型是否满足要求。满足要求则正常执行否则返回报错。 以LLEN指令为例指令执行流程如下
命令多态
命令多态包括基于类型的多态和基于编码的多态。
基于类型的多态一个命令可以同时处理多钟不同类型的键。比如LLEN、DEL基于编码的多态一个命令可以同时用于处理多种不同的编码。比如LLEN对应的列表对象可以是ziplist编码或者linkedlist编码
内存回收
Redis使用refcount记录对象被引用次数使用引用计数的原理来实现内存回收。
创建新对象是refcount初始化为1对象被新程序使用时refcount增1对象不再被程序使用时refcount减1对象的refcount变为0时对象所占用的内存会被释放
对象共享
Redis为了尽可能的节省内存还是引用了对象共享的机制。Redis会预创建一些对象后续该对象被新程序引用时不再创建新的对象而是会将对象的refcount进行加1。 预创建的对象有常见OK、Error等错误指令还有[0-9999]的数字常量。
struct sharedObjectsStruct {robj *ok, *err, *emptybulk, *czero, *cone, *pong, *space,*queued, *null[4], *nullarray[4], *emptymap[4], *emptyset[4],*emptyarray, *wrongtypeerr, *nokeyerr, *syntaxerr, *sameobjecterr,*outofrangeerr, *noscripterr, *loadingerr,*slowevalerr, *slowscripterr, *slowmoduleerr, *bgsaveerr,*masterdownerr, *roslaveerr, *execaborterr, *noautherr, *noreplicaserr,*busykeyerr, *oomerr, *plus, *messagebulk, *pmessagebulk, *subscribebulk,*unsubscribebulk, *psubscribebulk, *punsubscribebulk, *del, *unlink,*rpop, *lpop, *lpush, *rpoplpush, *lmove, *blmove, *zpopmin, *zpopmax,*emptyscan, *multi, *exec, *left, *right, *hset, *srem, *xgroup, *xclaim, *script, *replconf, *eval, *persist, *set, *pexpireat, *pexpire, *time, *pxat, *absttl, *retrycount, *force, *justid, *entriesread,*lastid, *ping, *setid, *keepttl, *load, *createconsumer,*getack, *special_asterick, *special_equals, *default_username, *redacted,*ssubscribebulk,*sunsubscribebulk, *smessagebulk,*select[PROTO_SHARED_SELECT_CMDS],*integers[OBJ_SHARED_INTEGERS],*mbulkhdr[OBJ_SHARED_BULKHDR_LEN], /* *value\r\n */*bulkhdr[OBJ_SHARED_BULKHDR_LEN], /* $value\r\n */*maphdr[OBJ_SHARED_BULKHDR_LEN], /* %value\r\n */*sethdr[OBJ_SHARED_BULKHDR_LEN]; /* ~value\r\n */sds minstring, maxstring;
};注意Redis只对整数值的字符串对象共享。因为服务器考虑将一个共享对象设置为键的值对象时程序需要先检查给定的共享对象和键想创建的目标对象是否完全相同只有在共享对象和目标对象完全相同的情况下程序才会将共享对象作为键的值对象而一个共享对象保存的值越复杂验证共享对象和目标对象所需的复杂度就会越高消耗的CPU时间也会越多。
如果共享对象是保存的字符串对象那么验证操作的复杂度为O(1)如果共享对象是保存字符串值的字符串对象那么验证操作的复杂度是O(N)如果共享对象是包含了多个值的对象比如列表对象、哈希对象、集合对象时验证操作的复杂度是O(N2)
对象空转时长
redis对象结构中还有lru字段用于表示该对象最后一个被访问的时间。通过当前时间和lru记录时间可以计算出对象的空转时长。 当服务器占用的内存数超过了maxmemory的设置时空转时长较高的键将会被优先释放进行内存回收。