java 基数树,Redis面试--数据结构

Redis数据结构

为什么用Redis

缓存,在内存中,IO多路复用,单线程

Redis有什么用

分布式锁,延迟队列,位图,hyperloglog记录UV,布隆过滤器,限流,GeoHash地理位置计算附近的人。

项目中用到了什么

验证码

Key Value 型

String

底层

ArrayList类似,是字节数组,动态分配长度,字符串长度最大为512M,超过1M会每次增加1M

Simple Dynamic String,支持append操作

SDS

struct SDS {

int8 capacity; // 1byte

int8 len; // 1byte

int8 flags; // 1byte

byte[] content; // 内联数组,长度为 capacity

}

存储类型:emb vs raw

长度小于44 —因为要分配64个空间,那么一个SDS占用19字节,只剩下45字节选择emb ,大于选择raw。

emb为连续存储空间,raw为不连续

set get del

expire setnx

incr 累加 max为u long

List

底层

LinkedList QuickList–是一个连续空间的链表ziplist

插入快,查询慢

rpush x x1 x2

llen 长度

lpop rpop 左出 右出 队列和栈

慢操作

lindex 获得index所在为止 因为需要遍历链表,所以操作慢

Hash字典

Hash

底层,数组+链表,与hashmap相似,只能保存字符串

rehash不一样,采用了渐进式rehash,保留新旧两个 hash 结构,在空闲时间逐渐rehash

当hash移除了最后一个元素,该数据结构被删除

缺点:结构存储消耗高于单个字符串

hset x key value

hgetall x

hlen x

hget x key

hmset k1 v1 k2 v2 批量增加

底层原理

struct RedisDb {

dict* dict; // all keys key=>value

dict* expires; // all expired keys key=>long(timestamp)

}

struct zset {

dict *dict; // all values value=>score

zskiplist *zsl;

}

内部有两个hashtable --和java的hashmap一样

edis 的字典默认的 hash 函数是siphash,重复性低

hash元素个数大于2倍时考虑扩容,大于5倍时强制扩容。

Set

sadd x key

smembers x 获得x中所有元素

sismember x key 查询是否存在, return 1 0

spop x 弹出一个

scard x 获取x长度

Zset 有序set 底层是链表,所以不能二分查找定位

zadd zrange zcard zrem删除

跳跃列表

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-K0T3GHUK-1593086673887)(Untitled.assets/image-20200607211941308.png)]

层级式,类似于B+树

探索 四个列表

压缩列表 ziplist

struct ziplist{

int32 zlbytes; // 整个压缩列表占用字节数

int32 zltail_offset; // 最后一个元素距离压缩列表起始位置的偏移量,用于快速定位到最后一个

节点

int16 zllength; // 元素个数

T[] entries; // 元素内容列表,挨个挨个紧凑存储

int8 zlend; // 标志压缩列表的结束,值恒为 0xFF

}

支持双向遍历 有 zltail_offset

扩容,可能重新分配一块内存,可能在原有的扩张

intset小整数zipset

set 集合在数量很小的时候不使用 ziplist 来存储

快速列表 quickset

Redis 的跳跃表共有 64 层,意味着最多可以容纳 2^64 次方个元素

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NeEiCnQT-1593086673897)(Untitled.assets/image-20200607212653612.png)]

跳跃列表 skiplist

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Va3bNhos-1593086673899)(Untitled.assets/image-20200607212930241.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1ubwHiMH-1593086673902)(Untitled.assets/image-20200607213021733.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rM7zIh9H-1593086673903)(Untitled.assets/image-20200607213032170.png)]

紧凑列表listpack

Redis 5.0 又引入了一个新的数据结构 listpack,它是对 ziplist 结构的改进

struct listpack{

int32 total_bytes; // 占用的总字节数

int16 size; // 元素个数

T[] entries; // 紧凑排列的元素列表

int8 end; // 同 zlend 一样,恒为 0xFF

}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2P4lhceB-1593086673905)(Untitled.assets/image-20200607213622391.png)]

不同的是长度字段放在了元素的尾部,而且存储的不是上一个元素的长度,是当前元素的长度。正是因为长度放在了尾部,所以可以省去了 zltail_offset 字段来标记最后一个元素的位置,这个位置可以通过total_bytes 字段和最后一个元素的长度字段计算出来

探索「 「 基数树」 」

Rax 是 Redis 内部比较特殊的一个数据结构,它是一个有序字典树 (基数树 Radix

Tree),按照 key 的字典序排列,支持快速地定位、插入和删除操作。Redis 五大基础数据结

构里面,能作为字典使用的有 hash 和 zset。hash 不具备排序功能,zset 则是按照 score 进

行排序的。rax 跟 zset 的不同在于它是按照 key 进行排序的

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TEHphKW0-1593086673906)(Untitled.assets/image-20200607215448353.png)]

struct raxNode {

int<1> isKey; // 是否没有 key,没有 key 的是根节点

int<1> isNull; // 是否没有对应的 value,无意义的中间节点

int<1> isCompressed; // 是否压缩存储,这个压缩的概念比较特别

int<29> size; // 子节点的数量或者是压缩字符串的长度 (isCompressed)

byte[] data; // 路由键、子节点指针、value 都在这里

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值