Redis第二章之键类型
文章目录
普通键类型
字符串
最大不能超过512M
内部编码
- int:8个字节的长整型。
- embstr:小于等于39个字节的字符串。
- raw:大于39个字节的字符串。
Redis会根据当前值的类型和长度决定使用哪种内部编码实现。
哈希
在使用hgetall时,如果哈希元素个数比较多,会存在阻塞Redis的可能。
内部编码
-
ziplist(压缩列表):当哈希类型元素个数小于hash-max-ziplist-entries配置(默认512个)、同时所有值都小于hash-max-ziplist-value配置(默认64字节)时,Redis会使用ziplist作为哈希的内部实现,ziplist使用更加紧凑的结构实现多个元素的连续存储,所以在节省内存方面比hashtable更加优秀。
-
hashtable(哈希表):当哈希类型无法满足ziplist的条件时,Redis会使用hashtable作为哈希的内部实现,因为此时ziplist的读写效率会下降,而hashtable的读写时间复杂度为O(1)。
列表
一个列表最多可以存储2^32-1个元素
内部编码
-
ziplist(压缩列表):当列表的元素个数小于list-max-ziplist-entries配置(默认512个),同时列表中每个元素的值都小于list-max-ziplist-value配置时(默认64字节),Redis会选用ziplist来作为列表的内部实现来减少内存的使用。
-
linkedlist(链表):当列表类型无法满足ziplist的条件时,Redis会使用linkedlist作为列表的内部实现。
集合
内部编码
-
intset(整数集合):当集合中的元素都是整数且元素个数小于set-max-intset-entries配置(默认512个)时,Redis会选用intset来作为集合的内部实现,从而减少内存的使用。
-
hashtable(哈希表):当集合类型无法满足intset的条件时,Redis会使用hashtable作为集合的内部实现。
有序集合
内部编码
- ziplist(压缩列表):当有序集合的元素个数小于zset-max-ziplist-entries配置(默认128个),同时每个元素的值都小于zset-max-ziplist-value配置(默认64字节)时,Redis会用ziplist来作为有序集合的内部实现,ziplist可以有效减少内存的使用。
- skiplist(跳跃表):当ziplist条件不满足时,有序集合会使用skiplist作为内部实现,因为此时ziplist的读写效率会下降。
操作:
参考链接:[附A.键类型操作(nodejs版).note] – 未发布
说明:虽然为nodejs版的,但是与其他客户端操作中关键字、返回类型、参数都一致。
特殊键类型
Bitmaps
Bitmaps本身不是一种数据结构,实际上它就是字符串,但是它可以对字符串的位进行操作。
应用场景:统计某段时间内的大量用户是否活跃或商品(两百万个以上才适合使用)是否被访问,比使用其他类型来判断更省内存。
HyperLogLog
HyperLogLog并不是一种新的数据结构(实际类型为字符串类型),而是一种基数算法,通过HyperLogLog可以利用极小的内存空间完成独立总数的统计。
只为了计算独立总数,不需要获取单条数据。
该算法存在一定的偏差,Redis官方给出的数字是0.81%的失误率。
方法:
-
添加(pfadd key element [element …])
直接支持内部去重,添加多个相同的值,结果还是1。
-
计算一个或多个key的总数(pfcount key [key …])
如果是多个key,取的值是他们之间的去重后的个数。
-
合并(pfmerge destkey sourcekey [sourcekey …])
将多个key的值合并到新的key中,合并后原来的key依旧存在。
应用场景:计算网站或者商品的访问量。(与字符串直接存储总数相比,该算法的优势在于不用在程序中去重)
GEO(地理信息定位)
暂时还没研究 =_=
命令使用注意事项
-
dbsize命令在计算键总数时不会遍历所有键,而是直接获取Redis内置的键总数变量,所以dbsize命令的时间复杂度是O(1)。而keys命令会遍历所有键,所以它的时间复杂度是O(n),当Redis保存了大量键时,线上环境禁止使用。
-
del命令可以支持删除多个键
-
由于Redis的单线程架构,所以需要每个命令能被快速执行完,否则会存在阻塞Redis的可能,理解Redis单线程命令处理机制是开发和运维Redis的核心之一。
-
批量操作(例如mget、mset、hmset等)能够有效提高命令执行的效率,但要注意每次批量操作的个数和字节数。
-
了解每个命令的时间复杂度在开发中至关重要,例如在使用keys、hgetall、smembers、zrange等时间复杂度较高的命令时,需要考虑数据规模对于Redis的影响。
-
persist命令可以删除任意类型键的过期时间,但是set命令也会删除字符串类型键的过期时间,这在开发时容易被忽视。
-
scan命令可以解决keys命令可能带来的阻塞问题,同时Redis还提供了hscan、sscan、zscan渐进式地遍历hash、set、zset。