1 Star 0 Fork 131

wangtao0571/marion-notes

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
贡献代码
同步代码
取消
提示: 由于 Git 不支持空文件夾,创建文件夹后会生成空的 .keep 文件
Loading...
README

《Redis从入门到精通学习路线》

一、视频资料

【尚硅谷】Redis 6 入门到精通 超详细 教程

网盘课件资料: https://pan.baidu.com/s/12qUYKb0Sui4_3pKcvBH6UA

提取码: ceqv

二、电子书籍

【Redis设计与实现】

三、博客文章

Redis框架从入门到学精(全)

四、实战项目

  1. Java项目《谷粒商城》Java架构师 | 微服务 | 大型电商项目

五、常用网站

  1. redis官网
  2. Redis 命令参考
  3. Spring Data Redis
  4. Redisson分布式锁

【Redis设计与实现】

第1章 引言

1.1 Redis版本说明

1.2 章节编排

1.3 推荐的阅读方法

1.4 行文规则

1.5 配套网站

第一部分

第2章 简单动态字符串

  • 面试题

      1. Redis中set命令存储的字符串是普通字符串吗?
      1. Redis中SDS与C字符串区别?
      1. Redis中为什么要设计SDS字符串?
  • 2.1 SDS的定义

      1. 一个SDS示例
      • ❑free属性的值为0,表示这个SDS没有分配任何未使用空间。
      • ❑len属性的值为5,表示这个SDS保存了一个五字节长的字符串。
      • ❑buf属性是一个char类型的数组,数组的前五个字节分别保存了'R'、'e'、'd'、'i'、's'五个字符,而最后一个字节则保存了空字符'\0'。
  • 2.2 SDS与C字符串的区别

    • 2.2.1 常数复杂度获取字符串长度

      • C字符串O(N)
      • SDS字符串O(1)
    • 2.2.2 杜绝缓冲区溢出

    • 2.2.3 减少修改字符串时带来的内存重分配次数

      • 因为C字符串的长度和底层数组的长度之间存在着这种关联性,所以每次增长或者缩短一个C字符串,程序都总要对保存这个C字符串的数组进行一次内存重分配操作:

        • ❑如果程序执行的是增长字符串的操作,比如拼接操作(append),那么在执行这个操作之前,程序需要先通过内存重分配来扩展底层数组的空间大小——如果忘了这一步就会产生缓冲区溢出。
        • ❑如果程序执行的是缩短字符串的操作,比如截断操作(trim),那么在执行这个操作之后,程序需要通过内存重分配来释放字符串不再使用的那部分空间——如果忘了这一步就会产生内存泄漏。
    • 2.2.4 二进制安全

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

      • 这些API总会将SDS保存的数据的末尾设置为空字符,并且总会在为buf数组分配空间时多分配一个字节来容纳这个空字符,这是为了让那些保存文本数据的SDS可以重用一部分<string.h>库定义的函数。
  • 2.3 SDS API

  • 2.4 重点回顾

    • ❑Redis只会使用C字符串作为字面量,在大多数情况下,Redis使用SDS(Simple DynamicString,简单动态字符串)作为字符串表示。

    • ❑比起C字符串,SDS具有以下优点:

      • 1)常数复杂度获取字符串长度。
      • 2)杜绝缓冲区溢出。
      • 3)减少修改字符串长度时所需的内存重分配次数。
      • 4)二进制安全。
      • 5)兼容部分C字符串函数。
  • 2.5 参考资料

第3章 链表

  • 3.1 链表和链表节点的实现

  • 3.2 链表和链表节点的API

  • 3.3 重点回顾

    • ❑链表被广泛用于实现Redis的各种功能,比如列表键、发布与订阅、慢查询、监视器等。
    • ❑每个链表节点由一个listNode结构来表示,每个节点都有一个指向前置节点和后置节点的指针,所以Redis的链表实现是双端链表。
    • ❑每个链表使用一个list结构来表示,这个结构带有表头节点指针、表尾节点指针,以及链表长度等信息。
    • ❑因为链表表头节点的前置节点和表尾节点的后置节点都指向NULL,所以Redis的链表实现是无环链表。
    • ❑通过为链表设置不同的类型特定函数,Redis的链表可以用于保存各种不同类型的值。

第4章 字典

  • 4.1 字典的实现

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

    • 4.1.1 哈希表
    • 4.1.2 哈希表节点
    • 4.1.3 字典
  • 4.2 哈希算法

    • 当要将一个新的键值对添加到字典里面时,程序需要先根据键值对的键计算出哈希值和索引值,然后再根据索引值,将包含新键值对的哈希表节点放到哈希表数组的指定索引上面。
    • 当字典被用作数据库的底层实现,或者哈希键的底层实现时,Redis使用MurmurHash2算法来计算键的哈希值。
  • 4.3 解决键冲突

    • Redis的哈希表使用链地址法(separate chaining)来解决键冲突,每个哈希表节点都有一个next指针,多个哈希表节点可以用next指针构成一个单向链表,被分配到同一个索引上的多个节点可以用这个单向链表连接起来,这就解决了键冲突的问题。
  • 4.4 rehash

      1. 随着操作的不断执行,哈希表保存的键值对会逐渐地增多或者减少,为了让哈希表的负载因子(loadfactor)维持在一个合理的范围之内,当哈希表保存的键值对数量太多或者太少时,程序需要对哈希表的大小进行相应的扩展或者收缩。
      1. Redis对字典的哈希表执行rehash的步骤
      • 1)为字典的ht[1]哈希表分配空间
      • 2)将保存在ht[0]中的所有键值对rehash到ht[1]上面
      • 3)当ht[0]包含的所有键值对都迁移到了ht[1]之后(ht[0]变为空表),释放ht[0],将ht[1]设置为ht[0],并在ht[1]新创建一个空白哈希表,为下一次rehash做准备。
      1. 哈希表的扩展与收缩
      • 1)服务器目前没有在执行BGSAVE命令或者BGREWRITEAOF命令,并且哈希表的负载因子大于等于1。
      • 2)服务器目前正在执行BGSAVE命令或者BGREWRITEAOF命令,并且哈希表的负载因子大于等于5。
      • 根据BGSAVE命令或BGREWRITEAOF命令是否正在执行,服务器执行扩展操作所需的负载因子并不相同,这是因为在执行BGSAVE命令或BGREWRITEAOF命令的过程中,Redis需要创建当前服务器进程的子进程,而大多数操作系统都采用写时复制(copy-on-write)技术来优化子进程的使用效率,所以在子进程存在期间,服务器会提高执行扩展操作所需的负载因子,从而尽可能地避免在子进程存在期间进行哈希表扩展操作,这可以避免不必要的内存写入操作,最大限度地节约内存。
  • 4.5 渐进式rehash

      1. 这个rehash动作并不是一次性、集中式地完成的,而是分多次、渐进式地完成的。
      1. 哈希表渐进式rehash的详细步骤
      • 1)为ht[1]分配空间,让字典同时持有ht[0]和ht[1]两个哈希表。
      • 2)在字典中维持一个索引计数器变量rehashidx,并将它的值设置为0,表示rehash工作正式开始。
      • 3)在rehash进行期间,每次对字典执行添加、删除、查找或者更新操作时,程序除了执行指定的操作以外,还会顺带将ht[0]哈希表在rehashidx索引上的所有键值对rehash到ht[1],当rehash工作完成之后,程序将rehashidx属性的值增一。
      • 4)随着字典操作的不断执行,最终在某个时间点上,ht[0]的所有键值对都会被rehash至ht[1],这时程序将rehashidx属性的值设为-1,表示rehash操作已完成。
      • 渐进式rehash的好处在于它采取分而治之的方式,将rehash键值对所需的计算工作均摊到对字典的每个添加、删除、查找和更新操作上,从而避免了集中式rehash而带来的庞大计算量。
      1. 渐进式rehash执行期间的哈希表操作
      • 因为在进行渐进式rehash的过程中,字典会同时使用ht[0]和ht[1]两个哈希表,所以在渐进式rehash进行期间,字典的删除(delete)、查找(find)、更新(update)等操作会在两个哈希表上进行。
      • 另外,在渐进式rehash执行期间,新添加到字典的键值对一律会被保存到ht[1]里面,而ht[0]则不再进行任何添加操作,这一措施保证了ht[0]包含的键值对数量会只减不增,并随着rehash操作的执行而最终变成空表。
  • 4.6 字典API

  • 4.7 重点回顾

    • ❑字典被广泛用于实现Redis的各种功能,其中包括数据库和哈希键。
    • ❑Redis中的字典使用哈希表作为底层实现,每个字典带有两个哈希表,一个平时使用,另一个仅在进行rehash时使用。
    • ❑当字典被用作数据库的底层实现,或者哈希键的底层实现时,Redis使用MurmurHash2算法来计算键的哈希值。
    • ❑哈希表使用链地址法来解决键冲突,被分配到同一个索引上的多个键值对会连接成一个单向链表。
    • ❑在对哈希表进行扩展或者收缩操作时,程序需要将现有哈希表包含的所有键值对rehash到新哈希表里面,并且这个rehash过程并不是一次性地完成的,而是渐进式地完成的。

第5章 跳跃表

  • 5.1 跳跃表的实现
  • 5.2 跳跃表API
  • 5.3 重点回顾

第6章 整数集合

  • 6.1 整数集合的实现
  • 6.2 升级
  • 6.3 升级的好处
  • 6.4 降级
  • 6.5 整数集合API
  • 6.6 重点回顾

第7章 压缩列表

  • 7.1 压缩列表的构成
  • 7.2 压缩列表节点的构成
  • 7.3 连锁更新
  • 7.4 压缩列表API
  • 7.5 重点回顾

第8章 对象

  • 8.1 对象的类型与编码
  • 8.2 字符串对象
  • 8.3 列表对象
  • 8.4 哈希对象
  • 8.5 集合对象
  • 8.6 有序集合对象
  • 8.7 类型检查与命令多态
  • 8.8 内存回收
  • 8.9 对象共享
  • 8.10 对象的空转时长
  • 8.11 重点回顾

第二部分

第9章 数据库

  • 9.1 服务器中的数据库
  • 9.2 切换数据库
  • 9.3 数据库键空间
  • 9.4 设置键的生存时间或过期时间
  • 9.5 过期键删除策略
  • 9.6 Redis的过期键删除策略
  • 9.7 AOF、RDB和复制功能对过期键的处理
  • 9.8 数据库通知
  • 9.9 重点回顾

第10章 RDB持久化

  • 10.1 RDB文件的创建与载入
  • 10.2 自动间隔性保存
  • 10.3 RDB文件结构
  • 10.4 分析RDB文件
  • 10.5 重点回顾
  • 10.6 参考资料

第11章 AOF持久化

  • 11.1 AOF持久化的实现
  • 11.2 AOF文件的载入与数据还原
  • 11.3 AOF重写
  • 11.4 重点回顾

第12章 事件

  • 12.1 文件事件
  • 12.2 时间事件
  • 12.3 事件的调度与执行
  • 12.4 重点回顾
  • 12.5 参考资料

第13章 客户端

  • 13.1 客户端属性
  • 13.2 客户端的创建与关闭
  • 13.3 重点回顾

第14章 服务器

  • 14.1 命令请求的执行过程
  • 14.2 serverCron函数
  • 14.3 初始化服务器
  • 14.4 重点回顾

第三部分

第15章 复制

  • 15.1 旧版复制功能的实现
  • 15.2 旧版复制功能的缺陷
  • 15.3 新版复制功能的实现
  • 15.4 部分重同步的实现
  • 15.5 PSYNC命令的实现
  • 15.6 复制的实现
  • 15.7 心跳检测
  • 15.8 重点回顾

第16章 Sentinel

  • 16.1 启动并初始化Sentinel
  • 16.2 获取主服务器信息
  • 16.3 获取从服务器信息
  • 16.4 向主服务器和从服务器发送信息
  • 16.5 接收来自主服务器和从服务器的频道信息
  • 16.6 检测主观下线状态
  • 16.7 检查客观下线状态
  • 16.8 选举领头Sentinel
  • 16.9 故障转移
  • 16.10 重点回顾
  • 16.11 参考资料

第17章 集群

  • 17.1 节点
  • 17.2 槽指派
  • 17.3 在集群中执行命令
  • 17.4 重新分片
  • 17.5 ASK错误
  • 17.6 复制与故障转移
  • 17.7 消息
  • 17.8 重点回顾

第四部分

第18章 发布与订阅

  • 18.1 频道的订阅与退订
  • 18.2 模式的订阅与退订
  • 18.3 发送消息
  • 18.4 查看订阅信息
  • 18.5 重点回顾
  • 18.6 参考资料

第19章 事务

  • 19.1 事务的实现
  • 19.2 WATCH命令的实现
  • 19.3 事务的ACID性质
  • 19.4 重点回顾
  • 19.5 参考资料

第20章 Lua脚本

  • 20.1 创建并修改Lua环境
  • 20.2 Lua环境协作组件
  • 20.3 EVAL命令的实现
  • 20.4 EVALSHA命令的实现
  • 20.5 脚本管理命令的实现
  • 20.6 脚本复制
  • 20.7 重点回顾
  • 20.8 参考资料

第21章 排序

  • 21.1 SORT<key>命令的实现
  • 21.2 ALPHA选项的实现
  • 21.3 ASC选项和DESC选项的实现
  • 21.4 BY选项的实现
  • 21.5 带有ALPHA选项的BY选项的实现
  • 21.6 LIMIT选项的实现
  • 21.7 GET选项的实现
  • 21.8 STORE选项的实现
  • 21.9 多个选项的执行顺序
  • 21.10 重点回顾

第22章 二进制位数组

  • 22.1 位数组的表示
  • 22.2 GETBIT命令的实现
  • 22.3 SETBIT命令的实现
  • 22.4 BITCOUNT命令的实现
  • 22.5 BITOP命令的实现
  • 22.6 重点回顾
  • 22.7 参考资料

第23章 慢查询日志

  • 23.1 慢查询记录的保存
  • 23.2 慢查询日志的阅览和删除
  • 23.3 添加新日志
  • 23.4 重点回顾

第24章 监视器

  • 24.1 成为监视器
  • 24.2 向监视器发送命令信息
  • 24.3 重点回顾

XMind - Trial Version

马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
Java
1
https://gitee.com/wangtao0571/marion-notes.git
git@gitee.com:wangtao0571/marion-notes.git
wangtao0571
marion-notes
marion-notes
master

搜索帮助