字符串
redis里的字符串和java中的不同,是以key value的形式,相当于java中给字符串赋值给个变量,通过变量获取字符串的值。redis的字符串是使用SDS实现的,里面保存了字符串的长度,内部编码分为int、embstr、raw三种。
为什么不适用c中的字符串
直接看c中字符串和SDS的区别
c字符串 | SDS |
---|---|
获取字符串长度的复杂度为O(N) | 获取字符串长度的复杂度为O(1) |
API是不安全的, 可能会造成缓冲区溢出 | API是安全的,不会造成缓冲区溢出 |
修改字符串长度N次必然需要N次内存重分配 | 修改字符串长度N次最多需要执行N次内存分配 |
只能保存文本数据 | 可以保存文本或者二进制数据 |
可以使用所有<string.h>库中的函数 | 可以使用一部分<string.h>库中的函数 |
通过上面的比较,可以看出redis在安全、数据保存格式、扩容优化等方面对字符串进行处理。
列表
redis中list,操作大多是先进先出或者先进后出,相当于队列或者栈的结构。redis中的列表与java中的列表的内部结构不同,redis 中的列表编码格式是quicklist,是一种ziplist与linkedlist的混合体, 列表内部结构.png每个ziplist存多少元素
quicklist内部默认单个ziplist长度为8k字节,超出就会新起一个新的ziplist,ziplist的长度由配置参数list-max-ziplist-size决定。
压缩深度
quicklist默认的压缩深度是0,也就是不压缩。压缩的实际深度由配置参数list-compress-depth决定。为了支持快速的push/pop操作,配置n个,quicklist的首尾n个ziplist不压缩。
hash 字典
hash与java的HashMap也是有区别的,redis中字典的值必须是字符串,而且redis对rehash也进行了优化,避免rehash阻塞服务。
hash的rehash策略
redis的hash在rehash时采用渐进策略
rehash.png
也就是用空间换时间,在rehash阶段查询时,会同时查询新旧两个结构,然后在后续的定时任务中以及hash的子命令中,循序渐进将旧的hash的内容一点点迁移到新的hash结构中。当hash移除了最后一个元素之后,该数据结构自动被删除,内存被回收。
set 集合
类似于java中hashset,不可重复的无序结合。可用作去重处理。
zset 有序列表
这个结构比较独特,类似java中的SortedSet和HashMap的结合体。一方面是个set,保证内部value的唯一性。另一方面可以给value设置double类型score,通过score进行排序。
zset在最后一个value被移除后,数据机构自动删除,内存被回收。
zset每部使用跳跃列表的数据结构。这个结构面试中会经常被问道,将在后面的文章中进行详细描述。
容器数据结构通用规则
list/set/hash/zset这四种数据机构是容器数据结构,它们共享下面两条通用规则:
- create if not exists:如果容器不存在就创建。
- drop if no elements:如果容器里元素没有了,就立即删除元素,释放内存。
过期时间
redis所有数据结构都能设置过期时间,这个过期时间是针对对象的。
但是需要注意,如果设置过期时间的对象调用了set方法修改了它,这个过期时间会消失。
127.0.0.1:6379> set test1 a
OK
127.0.0.1:6379> EXPIRE test1 400
(integer) 1
127.0.0.1:6379> ttl test1
(integer) 397
127.0.0.1:6379> set test1 b
OK
127.0.0.1:6379> ttl test1
(integer) -1
127.0.0.1:6379> get test1
"b"
这里通过阅读《Redis深度历险:核心原理和应用实践》,比较清晰的了解了基本数据结构,并总结了一下,希望对看到的人有帮助。
网友评论