Redis—九种数据类型及底层数据结构

一、九种数据类型

▪ String:二进制安全、可以包含任何数据,(常规计数,分布式锁,共享session信息)

▪ List:简单的字符串列表,按照插⼊顺序排序(最新回复,消息队列)

▪ Hash:键值对集合(缓存对象、购物车)

▪ Set:无序的去重集合(共同好友、共同关注,点赞,抽奖活动)

▪ SortedSet:可排序版的set(排行榜,电话和姓名排序)

▪ Bitmap:位图,⼀个以位为单位的数据(二值状态统计的场景:签到,判断登录状态等)

▪ Hyperloglog:统计基数,有误差(海量数据基数统计的场景)

▪ Geospatial:地理位置信息(打车定位,滴滴打车)

▪ Stream:为消息队列设计的数据类型

二、底层数据结构

▪ SDS:

• 记录长度,可以o(1)时间获得长度

• ⼆进制格式,能存储任意数据类型

• 多种数据类型,int、raw和 embstr,节省内存空间

• 二进制安全,不会发生缓冲区溢出

链表(双向链表)

• 双向链表、有头尾指针、有链表长度

• void*保存节点值,链表节点内容多样性

▪ 哈希表

• 链式哈希解决冲突

• rehash:redis使⽤两个哈希表,数据增多需要扩容的时候,搬移数据到ht[1]上,然后 交换

• 渐进式rehash:新增、更新、删除、更新操作时候,都会迁移到ht[1]上,最终都搬到 ht[1]的时候上,完成rehash(查询时候如果ht[0]没有查到会去ht[1]上查找)

• 渐进式条件:

        ◦ 负载因子 = 哈希表保存节点数 / 哈希表大小 

        ◦ 负载因子 >= 1,没有执行RDB和AOF时候rehash

        ◦ 负载因子 >= 5,不管有⽆RDB和AOF操作都会强制rehash

▪ 压缩链表

• 根据数据类型和大小进行分配,节省空间

• 连锁更新问题:前⼀个节点长度⼤于254字节,当前节点prevlen⻓度为1字节(2^8) 变为5字节保存

▪ 整数集合:

• ⼀个数组

• 升级操作:节省空间,不能降级

▪ 跳表:

• 单纯性能,跳表和红⿊树性能相差不大,并发环境下,更新数据时,跳跃表需要更新的部分更少,锁的东西比较少,竞争锁的代价也更小(链表加多级索引,二分思想) 

• Redis选用跳表的原因

        ◦ 内存占用:平衡树每个节点还需要保存两个左右指针,跳表每个节点包含的指针数目平均为 1/(1-p),Redis中平均使⽤1.33个指针        

        ◦ 遍历操作:平衡树拿到节点后进⾏中序遍历很困难,跳表有前后指针

        ◦ 实现难度:跳表实现更简单

▪ quicklist:

• 对链表的更新,把每个节点换成了压缩列表 双向链表 + 压缩列表

        ◦ 对双向链表的优势:压缩列表是内存连续的,比每个节点都离散的存法,更能利用缓存都读到缓存里

        ◦ 对压缩列表的优势:把⼀整个压缩列表切分成了多个节点,连锁更新影响

• 当前节点的压缩列表不能容纳时候,再创建下⼀个节点

▪ listpack

• quicklist中每个压缩列表还是存在连锁更新的问题

• 压缩链表不再记录前⼀个节点的⻓度,记录当前节点的长度,避免连锁更新

你可能感兴趣的:(数据结构,redis,链表)