1、对象共享:如果redis中已经set了一个字符串或数字,再set同样值,这时会实现对象引用共享。值对象的refcount会出现变化,增加。
redis> SET A 100
OK
redis> SET B 100
redis> OBJECT REFCOUNT A
(integer) 2
OBJECT REFCOUNT 键名可以查看共享引用的数量
当服务器考虑将一个共享对象设置为键的值对象时, 程序需要先检查给定的共享对象和键想创建的目标对象是否完全相同, 只有在共享对象和目标对象完全相同的情况下, 程序才会将共享对象用作键的值对象, 而一个共享对象保存的值越复杂, 验证共享对象和目标对象是否相同所需的复杂度就会越高, 消耗的 CPU 时间也会越多:
- 如果共享对象是保存整数值的字符串对象, 那么验证操作的复杂度为 ;
- 如果共享对象是保存字符串值的字符串对象, 那么验证操作的复杂度为 ;
- 如果共享对象是包含了多个值(或者对象的)对象, 比如列表对象或者哈希对象, 那么验证操作的复杂度将会是 。
因此, 尽管共享更复杂的对象可以节约更多的内存, 但受到 CPU 时间的限制, Redis 只对包含整数值的字符串对象进行共享。
2、哈希对象
哈希对象的编码可以是 ziplist
或者 hashtable
。
ziplist
编码的哈希对象使用压缩列表作为底层实现, 每当有新的键值对要加入到哈希对象时, 程序会先将保存了键的压缩列表节点推入到压缩列表表尾, 然后再将保存了值的压缩列表节点推入到压缩列表表尾, 因此:
不能满足这两个条件的哈希对象需要使用 hashtable
编码。
注意
这两个条件的上限值是可以修改的, 具体请看配置文件中关于 hash-max-ziplist-value
选项和 hash-max-ziplist-entries
选项的说明。
对于使用 ziplist
编码的列表对象来说, 当使用 ziplist
编码所需的两个条件的任意一个不能被满足时, 对象的编码转换操作就会被执行: 原本保存在压缩列表里的所有键值对都会被转移并保存到字典里面, 对象的编码也会从 ziplist
变为 hashtable
3、集合类型
- 保存了同一键值对的两个节点总是紧挨在一起, 保存键的节点在前, 保存值的节点在后;
- 先添加到哈希对象中的键值对会被放在压缩列表的表头方向, 而后来添加到哈希对象中的键值对会被放在压缩列表的表尾方向。
编码转换
当哈希对象可以同时满足以下两个条件时, 哈希对象使用 ziplist
编码:
- 哈希对象保存的所有键值对的键和值的字符串长度都小于
64
字节; - 哈希对象保存的键值对数量小于
512
个;
编码的转换
当集合对象可以同时满足以下两个条件时, 对象使用 intset
编码:
集合对象保存的所有元素都是整数值; 集合对象保存的元素数量不超过 512
个;
对于使用 intset
编码的集合对象来说, 当使用 intset
编码所需的两个条件的任意一个不能被满足时, 对象的编码转换操作就会被执行: 原本保存在整数集合中的所有元素都会被转移并保存到字典里面, 并且对象的编码也会从 intset
变为 hashtable
。
不能满足这两个条件的集合对象需要使用 hashtable
编码。
注意
第二个条件的上限值是可以修改的, 具体请看配置文件中关于 set-max-intset-entries
选项的说明。