字符串类型分别使用 REDIS_ENCODING_INT 和 REDIS_ENCODING_RAW 两种编码:
换句话来说, 在 Redis 中, 只有能表示为 long 类型的值, 才会以整数的形式保存, 其他类型的整数、小数和字符串, 都是用 sdshdr 结构来保存。 [外链图片转存失败(img-XhnK28s8-1567048898164)(https://redisbook.readthedocs.io/en/latest/_images/graphviz-bb7ecaf3be8e729365b5a9241cdcb04aa5a709d1.svg)] 新创建的字符串默认使用 REDIS_ENCODING_RAW 编码, 在将字符串作为键或者值保存进数据库时, 程序会尝试将字符串转为 REDIS_ENCODING_INT 编码
REDIS_HASH (哈希表)是 HSET 、 HLEN 等命令的操作对象, 它使用 REDIS_ENCODING_ZIPLIST 和 REDIS_ENCODING_HT 两种编码方式:
[外链图片转存失败(img-MKi6CDzh-1567048898168)(https://redisbook.readthedocs.io/en/latest/_images/graphviz-145365a458984496cfecacd67b29f5d42c39a401.svg)]
创建空白哈希表时, 程序默认使用 REDIS_ENCODING_ZIPLIST 编码, 当以下任何一个条件被满足时, 程序将编码从 REDIS_ENCODING_ZIPLIST 切换为 REDIS_ENCODING_HT : 哈希表中某个键或某个值的长度大于 server.hash_max_ziplist_value (默认值为 64 )。 压缩列表中的节点数量大于 server.hash_max_ziplist_entries (默认值为 512 )
REDIS_LIST (列表)是 LPUSH 、 LRANGE 等命令的操作对象, 它使用 REDIS_ENCODING_ZIPLIST 和 REDIS_ENCODING_LINKEDLIST 这两种方式编码: [外链图片转存失败(img-gytpHpeq-1567048898172)(https://redisbook.readthedocs.io/en/latest/_images/graphviz-9d1b937227cf948b8a9bfb3137570475e5407d2c.svg)]
创建新列表时 Redis 默认使用 REDIS_ENCODING_ZIPLIST 编码, 当以下任意一个条件被满足时, 列表会被转换成 REDIS_ENCODING_LINKEDLIST 编码:
阻塞原语并不是一定会造成客户端阻塞:
当一个阻塞原语的处理目标为空键时, 执行该阻塞原语的客户端就会被阻塞。
阻塞一个客户端需要执行以下步骤:
当客户端被阻塞之后,脱离阻塞状态有以下三种方法:
通过将新元素推入造成客户端阻塞的某个键中, 可以让相应的客户端从阻塞状态中脱离出来 (取消阻塞的客户端数量取决于推入元素的数量)。
LPUSH 、 RPUSH 和 LINSERT 这三个添加新元素到列表的命令, 在底层都由一个 pushGenericCommand 的函数实现, 这个函数的运作流程如下图: [外链图片转存失败(img-TbnHSUQy-1567048898188)(https://redisbook.readthedocs.io/en/latest/_images/graphviz-be4975476661a3e683475377d30b659d70bee64c.svg)] 当向一个空键推入新元素时, pushGenericCommand 函数执行以下两件事:
REDIS_SET (集合)是 SADD 、 SRANDMEMBER 等命令的操作对象, 它使用 REDIS_ENCODING_INTSET 和 REDIS_ENCODING_HT 两种方式编码: [外链图片转存失败(img-5ykAMOkm-1567048898193)(https://redisbook.readthedocs.io/en/latest/_images/graphviz-2f54a5b62b3507f0e6d579358e426c78b0dfbd5c.svg)]
第一个添加到集合的元素, 决定了创建集合时所使用的编码:
如果一个集合使用 REDIS_ENCODING_INTSET 编码, 那么当以下任何一个条件被满足时, 这个集合会被转换成 REDIS_ENCODING_HT 编码:
intset底层实现方式是数组,这个数组以有序、无重复的方式保存集合元素,并且根据新添加的整数元素类型来进行自动升级,例如从int16_t升级到int32_t; 它具有灵活性+节省内存的优点; 在集合类型只有整数元素并且元素不是很大的时候选择intset是比较好的一个选择;
当使用 REDIS_ENCODING_HT 编码时, 集合将元素保存到字典的键里面, 而字典的值则统一设为 NULL 。
作为例子, 以下图片展示了一个以 REDIS_ENCODING_HT 编码表示的集合, 集合的成员为 elem1 、 elem2 和 elem3 : [外链图片转存失败(img-gVLWNUdF-1567048898198)(https://redisbook.readthedocs.io/en/latest/_images/graphviz-3b62c50ed475dc6c91adbb8079f0e0104f644931.svg)]
REDIS_ZSET (有序集)是 ZADD 、 ZCOUNT 等命令的操作对象, 它使用 REDIS_ENCODING_ZIPLIST 和 REDIS_ENCODING_SKIPLIST 两种方式编码: [外链图片转存失败(img-Ua7tWSuy-1567048898206)(https://redisbook.readthedocs.io/en/latest/_images/graphviz-4d10098056ec25ed0e239f64bbcac524bce31bc8.svg)]
在通过 ZADD 命令添加第一个元素到空 key 时, 程序通过检查输入的第一个元素来决定该创建什么编码的有序集。
如果第一个元素符合以下条件的话, 就创建一个 REDIS_ENCODING_ZIPLIST 编码的有序集:
对于一个 REDIS_ENCODING_ZIPLIST 编码的有序集, 只要满足以下任一条件, 就将它转换为 REDIS_ENCODING_SKIPLIST 编码: