redis5-高级数据结构
2022-09-20 14:38:57 0 举报
redis5-高级数据结构
作者其他创作
大纲/内容
prev
next
count
entry
quicklistNode
type
5
列表特性:部分操作支持阻塞和非阻塞:重点看阻塞——当所有给定的key中不存在,或者key中包含的是空列表,那么 BLPOP 或 BLPOP 命令将会被阻塞连接,直到另一个client对这些key中执行 [LR]PUSH 命令将一个新数据出现在任意key的列表中,那么这个命令会解除调用BLPOP 或 BLPOP 命令的client的阻塞状态。
listpack
refcount
quicklist
node
zi
intset使用整数集合作为底层实现,集合对象包含所有元素都被保存在整数集合里面
基本字段详解
2
字符串分3种
int
hash-max-ziplist-entries 512hash-max-ziplist-value 64
共享对象池。对应于命令object refcount
需要均衡listpack和链表的大小
1
使用场景:常见数据结构1、lpush+lpop=stack(栈)2、lpush+rpop=queue(队列)3、lpush+ltrim=有限集合4、lpush+brpop=message queue(消息队列)文章列表
raw
head
tail
len
fill
compress
1、fill:16bit,控制着ziplist大小,存放list-max-ziplist-size参数的值;2、compress: 16bit,节点压缩深度设置,存放list-compress-depth参数的值;由于当数据很多时,最容易被访问的很可能是两端数据,中间的数据被访问的频率比较低(访问起来性能也很低)。如果应用场景符合这个特点,那么list还提供了一个选项,能够把中间的数据节点进行压缩,从而进一步节省内存空间
集合(set)
哈希(hash)
redis内存超过maxmemory指定的值时,redis会优先选择空转时间最长的对象进行释放。
使用场景:1、缓存功能:mysql存储,redis做缓存;2、计数器:如点赞次数,视频播放器;3、限流
集合对象存在非整数
打开maxmemory && 内存回收算法是volatile-lru 或者allkeys-lru ?
对应于命令type主要存储redis的对象类型
LFU是淘汰一段时间内,使用次数最少
ptr
使用场景:1、优先队列;2、排行榜系统:主要是视频网站需要对用户上传的视频做排行榜,榜单的维度可能是多个方面的:按照时间、按照播放数量、按照获得的赞数。a)添加用户赞数 zadd user:ranking:2016_03_15 3 mikeb)有人点赞 zincrby user:ranking:2016_03_15 1 mikec) 取消点赞 zrem user:ranking:2016_03_15 miked)展示获取赞数最多的十个用户 zrevrange user:ranking:2016_03_15 0 9e)展示用户信息以及用户分数和排名 hgetall user:info:tom zscore user:ranking:2016_03_15 mike zrank user:ranking:2016_03_15 mike
lfu算法
注意点:1、由intset转dict的操作是不可逆的;2、set是不允许重复的;3、支持交并补;4、参数【set-max-intset-entries】可在配置文件中进行修改;5、dict作为底层对象时,value值为null;6、intset作为底层对象时,其查找的时间复杂度为O(logN)
quicklist结构整合了链表和数组:1、双向链表,插入和删除效率高,对内存不友好;2、数组:插入和删除复杂度高,但是对内存友好3、如果链表长度是1,会退化成listpack;--可能会因为找不到很大连续内存而oom4、如果listpack为1,就退化成双向链表;--大量内存碎片
1、robj和sds非连续;2、可修改
小结:
t_set
说明:1、skiplist和dict共享元素和分值(指针复制)。2、由ziplist转skiplist的操作是不可逆的。3、两个参数【zset-max-ziplist-entries和zset-max-ziplist-value 】可在配置文件中进行修改;4、zset也不允许重复。
skiplist | dict实际上zset对字典和跳跃表进行了封装。(利用的跳表的排序和字典的快速读取)
lru
BLPOP key [key ...] timeout
低8位记录的是对象的访问频率,高16位记录对象访问时间
object idletime命令:通过对比lru时间与当前时间,可以计算某个对象的空转时间,不会改变lru的值。
quicklist大致结构
embstr:长度小于等于44字节的字符串(包括浮点数)。44个字节是主要适应jemalloc分配的64k的arean。
t_hash
还与内存回收相关
dict哈希对象中的每个键值对都是用字典键值对来保存
lru算法 or lfu算法 ?
存储文章示例
1、只分配一次内存空间,因此robj和sds是连续的;2、只读;3、embstr需要修改时,会转成raw,之后一直是raw
4
LRU是淘汰最长时间没有被使用
quicklistLZF
使用object freq命令,可以查看对象的使用次数
序列化字符串:set user:1 serialize(userInfo)优点:简化编程,如果合理利用序列化,可以提高内存的使用率缺点:序列化和反序列化有一定的开销,同时每次更新属性都需要把全部数据都提取出来进行反序列化,更新后在重新序列化
3
lru算法
listpack以追加的方式,先保存key,再保存value
redis对象:共5种
命令查看
encoding
命令
数据类型
使用场景
备注
字符串string
缓存;计数器
简单型
列表list
栈,队列,有限集合,消息队列
阻塞队列,关注列表
哈希hash
对象属性(尤其不定长)
如缓存userinfo
集合set
社交场景
赞/踩,粉丝,共同好友/喜好,推送
有序集合}zset
排行榜;优先队列;缓存相关元数据(比如按照排序挑战)
robj和sds是连续空间
使用场景:1、存储对象;2、原生字符串---------------------优点:简单直观,每个属性都支持单独更新缺点:占用过多的键,内存占用量大,同时用户信息内聚性差,生产环境比较少用
zset-max-ziplist-entries 128zset-max-ziplist-value 64
int:长度小于20(确保在一个长整型范围内,2^64正好是20位),且为数组字符串类型
embstr
列表(quicklist)----双向链表
set-max-intset-entrys 512
字符串
基础对象(redisObject)
dict使用字典作为底层实现,字典的每个键都是一个字符对象,每个字符对象包含一个集合元素,字典的值时null
有序集合(zset)
z_set
记录的是对象最后访问时间
对应于object encoding命令记录对象使用的底层数据结构,不同场景同一对象可能具有不同编码
listpack第一个节点保存元素成员,第二个节点保存元素分值。listpack内的集合元素按分值从小到大排序,分值小的元素放置在表头
1、redis共享的对象都放在结构体sharedObjectsStruct中;2、如常见字符串以及10000个字符串对象,值分别是[0~9999]的整数值;3、当redis需要使用0~9999的字符串对象时,可以直接使用这些共享对象;4、10000这个数字可以通过调整参数REDIS_SHARED_INTEGERS的值进行改变;5、共享对象池与maxmemory+LRU策略冲突;因为共享对象,lru也是共享的。
raw:长度大于44字节的字符串(包括浮点数)
压缩的结构
注意点:1、在skiplist的基础上,还需要创建dict的原因是当需要获取某个元素的score时,skiplist的时间复杂度为O(n),而dict时间复杂度为O(1)。2、需要特别注意的是当底层为ziplist时,该操作依旧为O(n)
注意点1、由ziplist转dict的操作是不可逆的;2、尽可能的使用ziplist来作为hash底层实现。长度尽量控制在1000以内,否则由于存取操作时间复杂度在O(n)到O(n^2)之间,长列表会导致CPU消耗严重。使用1KB以上的对象,hash-ziplist结构控制键数量反而得不偿失;3、两个参数【hash-max-ziplist-entries和hash-max-ziplist-value】可在配置文件中进行修改;4、ziplist作为底层对象时,其查找的时间复杂度为O(n)
是
模拟多态,可以存储任何类型的对象
0 条评论
下一页