redis五大数据结构:string,hash,list,set,zset(有序集合)

redis底层数据结构:简单动态字符串(SDS),链表,字典,跳表,整数集合,压缩列表

底层数据结构详解:

1.简单动态字符串:类似于c的结构体,但是SDS拥有记录已用长度(len)与剩余空间长度(free),当空间不足时会进行扩容。SDS最后会保存一个空字符

所以SDS获取字符串长度的时间复杂度为o(1),SDS自动扩容也不会像C一样产生溢出

利用未使用空间,SDS拥有空间预分配和惰性空间释放两种优化方法。

空间预分配:

修改SDS之后之后,如果len<1MB,将free修改为和len一样的长度,如果len>=1MB,将free修改为1MB。

例如:str = "redis"

如果拼接str与"cluster",那么修改之后len为5+6=11,11+11+1=23,len/free值都是11,加上最后一个空字符,总长为23。

要是str修改之后大小为20MB,那扩容之后就是20MB+1MB+1byte

将扩容需要的次数从最多n次变为至多n次。

惰性空间释放:

不会真正释放内存大小,例如删除redis中的字符e与d,那么str就变为ris,但是free=2。

这样减少释放空间的操作,将来扩容也会减少操作。

tips:SDS有专门的api可以真正释放空间,不用担心惰性释放带来空间的浪费。

二进制安全

C字符串中的字符必须符合某种编码(比如ASCII),并且除了字符串的末尾之外,字符串里面不能包含空字符,否则最先被程序读入的空字符将被误认为是字符串结尾,这些限制使得C字符串只能保存文本数据,而不能保存像图片、音频、视频、压缩文件这样的二进制数据。

因此,为了确保Redis可以适用于各种不同的使用场景,SDS的API都是二进制安全的。

SDS和c的区别:

2.链表

应用:列表键的底层实现之一就是链表。当一个列表键包含了数量比较多的元素,又或者列表中包含的元素都是比较长的字符串时,Redis就会使用链表作为列表键的底层实现。

除了链表键之外,发布与订阅、慢查询、监视器等功能也用到了链表,Redis服务器本身还使用链表来保存多个客户端的状态信息,以及使用链表来构建客户端输出缓冲区。

一个链表结点:

链表:

3.字典(key-value)

字典在Redis中的应用相当广泛,比如Redis的数据库就是使用字典来作为底层实现的,对数据库的增、删、查、改操作也是构建在对字典的操作之上的。

字典还是哈希键的底层实现之一,当一个哈希键包含的键值对比较多,又或者键值对中的元素都是比较长的字符串时,Redis就会使用字典作为哈希键的底层实现。

Redis的字典使用哈希表作为底层实现,而每个哈希表节点就保存了字典中的一个键值对。

字典所用的哈希表结构:

每个dictEntry结构保存着一个键值对

dictEntry结构:

字典结构:

type属性是一个指向dictType结构的指针,每个dictType结构保存了一簇用于操作特定类型键值对的函数,Redis会为用途不同的字典设置不同的类型特定函数。

privdata属性则保存了需要传给那些类型特定函数的可选参数。

Redis的哈希表使用链地址法来解决键冲突。

扩展和收缩哈希表的工作可以通过执行rehash(重新散列)操作来完成。

Redis Bgsave 命令用于在后台异步保存当前数据库的数据到磁盘。

对哈希表进行扩展:1.正在执行bgsave,负载因子>=5      2.没有执行bgsave,负载因子>=1

对哈希表进行收缩:负载因子<0.1

渐进式hash:rehash动作并不是一次性、集中式地完成的,而是分多次、渐进式地完成的。

原因:如果哈希表里保存的键值对数量千万甚至亿个键值对,那么要一次性将这些键值对全部rehash的话,庞大的计算量可能会导致服务器在一段时间内停止服务。

所以rehash期间,更新,删除,查找在两个表里进行,旧表查找不到的话去新表查找。

而插入就直接在新表进行,所以旧表只减不增。

字典使用哈希表作为底层实现,每个字典带有两个哈希表,一个平时使用,另一个仅在进行rehash时使用。

4.跳跃表

Redis使用跳跃表作为有序集合键的底层实现之一,如果一个有序集合包含的元素数量比较多,又或者有序集合中元素的成员是比较长的字符串时,Redis就会使用跳跃表来作为有序集合键的底层实现。

Redis只在两个地方用到了跳跃表,一个是实现有序集合键,另一个是在集群节点中用作内部数据结构。

每个节点都有向前,向后的指针,向后的可能有多个(看有多少层有这个数据),向前的只有一个。

插入方法:从底层开始,每一层选择插入或者不插入,插入一层的话就停止。

所以第一层的插入概率1/2,第二次1/4...

5.整数集合

整数集合是集合键的底层实现之一。

整数集合的结构:

contents数组各个项在数组中按值的大小从小到大有序地排列,并且数组中不包含任何重复项。contents数组的真正类型取决于encoding属性的值。

升级:

每当我们要将一个新元素添加到整数集合里面,并且新元素的类型比整数集合现有所有元素的类型都要长时,整数集合需要先进行升级,然后才能将新元素添加到整数集合里面。

升级步骤:1.根据新数据类型,扩展底层数组大小 2.将其他数据设置为新数据类型 3.新元素添加到底层数组

升级好处:一个是提升整数集合的灵活性,另一个是尽可能地节约内存。

节约内存:有int_16,int_32,int_64三种类型,整数集合现在的做法既可以让集合能同时保存三种不同类型的值,又可以确保升级操作只会在有需要的时候进行,这可以尽量节省内存。

没有降级操作。

6.压缩列表

压缩列表是列表键和哈希键的底层实现之一。

一个列表键只包含少量列表项,并且每个列表项要么就是小整数值,要么就是长度比较短的字符串,就会用压缩列表。

读《redis设计与实现》笔记--redis数据结构相关推荐

  1. Redis设计与实现笔记2

    文章目录 1.主从复制 主从复制的作用 实现 同步 命令传播 心跳检测 2.Sentinel 3.集群 节点 槽指派 重新分片 ASK错误 故障检测和故障转移 参考<Redis设计与实现> ...

  2. Redis设计与实现-笔记(一)

    文章目录 缓存理解 带来问题 本地缓存解决方案 分布式缓存 缓存读写模式/更新策略 正文 第一部分 数据结构与对象 第2章 简单动态字符串 2.1 SDS的定义 2.2 SDS与C字符串的区别 2.2 ...

  3. 结合redis设计与实现的redis源码学习-2-SDS(简单动态字符串)

    上一次我们学习了redis的内存分配方式,今天我们来学习redis最基本的数据结构SDS,在redis的数据库里,包含字符产值的简直对在底层都是由SDS实现的. SDS的基本数据结构是sdshdr结构 ...

  4. Redis设计与实现 笔记 第十七章 集群 cluster

    集群 Redis 集群是 Redis 提供的分布式数据库方案,集群通过分片来进行数据共享,并提供复制和故障转移功能 17.1 节点 一个 Redis 集群通常由多个节点组成,在刚开始的时候,每个节点都 ...

  5. [redis设计与实现][7]基本数据结构——对象

    Redis对基础数据类型进行了封装,构建出上层的对象系统,这个系统包含:字符串对象.列表对象.哈希对象.集合对象和有序集合对象. Redis对象结构: [cce lang="c"] ...

  6. redis设计与实现 笔记(一)

    Redis简单动态字符串 Redis 没有直接使用 C 语言传统的字符串表示(以空字符结尾的字符数组,以下简称 C 字符串), 而是自己构建了一种名为简单动态字符串(simple dynamic st ...

  7. Redis设计与实现笔记

    第一部分:数据结构与对象     简单动态字符串     链表     字典     跳跃表     整数集合     压缩列表     对象 第二部分:单机数据库的实现     数据库     RD ...

  8. [redis设计与实现][5]基本数据结构——整数集合

    整数集合(intset)用于集合键.当一个集合只包含整数值元素,并且数量不多的时候,会使用整数集合作为集合键的底层实现.相对于直接保存字符串,整数集合能够很好地节约内存,但是由于是数组保存,需要特别关 ...

  9. python redis订阅_Python 学习笔记 - Redis

    Redis 和Memcached类似 也是一个开源的内存存储系统,存储格式也是通过键值对的方式.不过和memcached比起来,memcached的value只支持字符串,而redis支持字符串,列表 ...

  10. 结合redis设计与实现的redis源码学习-8.2-t_string(字符串键)

    t_string.c中定义了字符串键的实现过程. #include "server.h" #include <math.h> /* isnan(), isinf() * ...

最新文章

  1. SQL Server数据类型
  2. cad批量选择相同块_CAD如何批量重命名图块或样式
  3. 字节跳动内部学习资料泄露!mysql的安装与配置
  4. scrapy爬虫值Items
  5. MySQL For RedHat Linux(源码安装,附安装包)
  6. MYSQL 入门全套
  7. MySQL/InnoDB中,乐观锁、悲观锁、共享锁、排它锁、行锁、表锁、死锁概念的理解...
  8. 利用JS+Ajax实现下拉列表无刷联动,及其相关
  9. cocos2d-x将背景色改为白色
  10. dts双轨制会员积分系统,直销系统,分销系统
  11. 数据结构算法书籍推荐
  12. 请问 土壤粒径的多重分形维数怎么计算?有matlab计算代码吗?
  13. 路由器猫服务器未响应,怎么通过猫判断网络连接是否有问题
  14. Revit打印工具 RevitPrinter
  15. 苹果cms漫画小说模板
  16. python将汉字转为拼音字母_科学网—[转载]python中文汉字转拼音 - 陈明杰的博文...
  17. python sys stdout_Python-如何将sys.stdout复制到日志文件?
  18. 云原生周刊 | 使用 ChatGPT 协助解决 Prometheus 告警
  19. 基于多二维码识别的无人机运动真值获取
  20. Java-Eclipse折叠代码插件 code folding 使用方法

热门文章

  1. LeetCode 1151. 最少交换次数来组合所有的 1(滑动窗口)
  2. LeetCode 1120. 子树的最大平均值(DFS自底向上)
  3. LeetCode 921. 使括号有效的最少添加(栈)
  4. unity python_Unity引擎内嵌python
  5. java 工厂模式的写法_java工厂模式三种详解
  6. vue 图片拖动加载 类似于地图_前端性能优化之图片懒加载(附vue自定义指令)...
  7. python导入gif_Python之GIF图倒放,沙雕快乐源泉!我已经笑了一天了!
  8. Facebook提出生成式实体链接、文档检索,大幅刷新SOTA!
  9. Java多线程系列(五):线程池的实现原理、优点与风险、以及四种线程池实现
  10. 最强Java面试题全部合集,涵盖BAT大厂面试必考的9大技术!-强烈建议收藏