入门到精通,理论到实战!这份Redis宝典不愧为“史诗巨作”
前言
Redis如今已经成为Web开发社区中最火热的内存数据库之一,而它的诞生距现在不过才4年。随着Web 2.0的蓬勃发展,网站数据快速增长,对高性能读写的需求也越来越多,再加上半结构化的数据比重逐渐变大,人们对早已被铺天盖地地运用着的关系数据库能否适应现今的存储需求产生了疑问。而Redis的迅猛发展,为这个领域注入了全新的思维。
Redis凭借其全面的功能得到越来越多的公司的青睐,从初创企业到新浪微博这样拥有着几百台Redis服务器的大公司,都能看到Redis的身影。Redis也是一个名副其实的多面手, 无论是存储、队列还是缓存系统,都有它的用武之地。
它扮演着多样的角色,发挥了重要的作用。架构师的职责之一就是技术选型,了解redis的原理、特点、优势和不足,是成为架构师必不可少的一环。
第一份笔记:Redis核心原理和应用实践
目录
应用篇
- 分布式锁
- 延时队列
- 位图
- HyperLogLog
- 布隆过滤器
- 简单限流
- 漏斗限流
- GeoHash
- Scan
分布式锁
分布式应用进行逻辑处理时经常会遇到并发问题。
比如一个操作要修改用户的状态,修改状态需要先读出用户的状态,在内存里进行修改,改完了再存回去。如果这样的操作同时进行了,就会出现并发问题,因为读取和保存状态这两个操作不是原子的。(Wiki 解释:所谓原子操作是指不会被线程调度机制打断的操作;这种操作一旦开始, 就一直运行到结束,中间不会有任何context switch线程切换。)
分布式锁本质上要实现的目标就是在Redis里面占一个“茅坑”,当别的进程也要来占时,发现已经有人蹲在那里了,就只好放弃或者稍后再试。
位图
位图不是特殊的数据结构,它的内容其实就是普通的字符串,也就是byte 数组。我们可以使用普通的get/set 直接获取和设置整个位图的内容,也可以使用位图操作getbit/setbit等将byte 数组看成「 位数组」来处理。
HyperLogLog实现原理
知识点比较多,代码就略过了............Σ( ° △ °|||)︴
布隆过滤器
上一节我们学会了使用HyperLogLog 数据结构来进行估数,它非常有价值,可以解决很多精确度不高的统计需求。
但是如果我们想知道某一个值是不是已经在HyperLogLog 结构里面了,它就无能为力了,它只提供了pfadd 和pfcount 方法,没有提供pfcontains 这种方法。
漏斗限流
漏斗限流是最常用的限流方法之一,顾名思义,这个算法的灵感源于漏斗( funnel)的结构。
原理篇
- 线程IO模型
- 通信协议
- 持久化
- 管道
- 事务
- PubSub
- 小对象压缩
- 主从同步
事件轮询(多路复用)
非阻塞IO有个问题,那就是线程要读数据,结果读了一部分就返回了,线程如何知道何时才应该继续读。也就是当数据到来时,线程如何得到通知。写也是一样,如果缓冲区满了,写不完,剩下的数据何时才应该继续写,线程也应该得到通知。
Redis 4.0混合持久化
重启Redis 时,我们很少使用rdb来恢复内存状态,因为会丢失大量数据。我们通常使用AOF日志重放,但是重放AOF日志性能相对rdb 来说要慢很多,这样在Redis 实例很大的情况下,启动需要花费很长的时间。
Redis的消息交互
当我们使用客户端对Redis 进行一次操作时,如下图所示,客户端将请求传送给服务器,服务器处理完毕后,再将响应回复给客户端。这要花费一个网络数据包来回的时间。
深入理解管道本质
接下来我们深入分析一个请求交互的流程,真实的情况是它很复杂,因为要经过网络协议栈,这个就得深入内核了。
CAP原理
CAP原理就好比分布式领域的牛顿定律,它是分布式存储的理论基石。自打CAP的论文发表之后,分布式存储中间件犹如雨后春笋般一个-个涌现出来。理解这个原理其实很简单,本节我们首先对这个原理进行一些简单的讲解。
- C - Consistent,一致性
- A- Availability , 可用性
- P - Partition tolerance,分区容忍性
集群篇
- Sentinel
- Codi
- Cluster
MGET指令的操作过程
Codis的后台管理
后台管理的界面非常友好,使用了最新的BootStrap 前端框架。比较酷炫的是可以看到实时的QPS波动曲线。
同时还支持服务器集群管理功能,可以增加分组、增加节点、执行自动均衡等指令,还可以直接查看所有slot 的状态,每个slot 被分配到哪个Redis实例。
迁移
Redis Cluster提供了工具redis-trib 可以让运维人员手动调整槽位的分配情况,它使用Ruby语言进行开发,通过组合各种原生的Redis Cluster指令来实现。这点Codis 做的更加人性化,它不但提供了UI 界面可以让我们方便的迁移,还提供了自动化平衡槽位工具,无需人工干预就可以均衡集群负载。不过Redis 官方向来的策略就是提供最小可用的工具,其它都交由社区完成。
拓展篇
- Stream
- Info指令
- 再谈分布式锁
- 过期策略
- LRU
- 懒惰删除
- 优雅地使用Jedis
- 保护Redis
- Redis安全通信
创建消费组
Redis每秒执行多少次指令?
异步队列
主线程将对象的引用从「大树」中摘除后,会将这个key的内存回收操作包装成-一个任务,塞进异步任务队列,后台线程会从这个异步队列中取任务。任务队列被主线程和异步线程同时操作,所以必须是一个线程安全的队列。
spiped原理
让我们放大细节,仔细观察spiped 实现原理。spiped 会在客户端和服务器各启动一个spiped进程。
源码篇
- 探索「字符串」内部结构
- 探索 [字典」内部
- 探索「压缩列表」内部
- 探索「快速列表」内部
- 探索「跳跃列表」内部结构
- 探索「紧凑列表」内部
- 探索「基数树」内部
dict内部结构
压缩深度
基本结构
应用
你可以将一本英语字 典看成一棵radix tree,,它所有的单词都是按照字典序进行排列,每个词汇都会附带一个解释, 这个解释就是key 对应的value。 有了这棵树,你就可以快速地检索单词,还可以查询以某个前缀开头的单词有哪些。
第二份笔记:Redis设计与实现
目录大纲
章节过多就不一一详记了,笔记完整版在文末,可供大家参考
第一部分、数据结构与对象
- 第2章简单动态字符串
- 第3章链表
- 第4章字典
- 第5章跳跃表
- 第6章整数集合
- 第7章压缩列表
- 第8章对象
SDS与C字符串的区别
SDS API
链表和链表节点的实现
哈希算法
当要将一个新的键值对添加到字典里面时,程序需要先根据键值对的键计算出哈希值和索引值,然后再根据索引值,将包含新键值对的哈希表节点放到哈希表数组的指定索引上面。
跳跃表的实现
Redis的跳跃表由redis.h/zskiplistNode和redis.h/zskiplist两个结构定义,其中zskiplistNode结 构用于表示跳跃表节点,而zskiplist结 构则用于保存跳跃表节点的相关信息,比如节点的数量,以及指向表头节点和表尾节点的指针等等。
编码和底层实现
字符串对象
哈希对象
第二部分、单机数据库的实现
- 第9章数据库
- 第10章RDB持久化
- 第11章AOF持久化
- 第12章事件
- 第13章客户端
- 第14章服务器
RDB文件结构
在本章之前的内容中,我们介绍了Redis服务器保存和载入RDB文件的方法,在这一节,我们将对RDB文件本身进行介绍,并详细说明文件各个部分的结构和意义。
AOF持久化
除了RDB持久化功能之外,Redis还提供了AOF (Append OnlyFile)持久化功能。与RDB持久化通过保存数据库中的键值对来记录数据库状态不同,AOF持 久化是通过保存Redis服务器所执行的写命令来记录数据库状态的,如图11-1所示。
文件事件处理器的构成
图12-1展示了文件事件处理器的四个组成部分,它们分别是套接字、I/O多路复用程序、文件事件分派器(dispatcher) ,以及事件处理器。
I/O多路复用程序的实现
Redis的I/O多路复用程序的所有功能都是通过包装常见的select、epoll、evport 和kqueue这些I/O多路复用函数库来实现的,每个I/O多路复用函数库在Redis源码中都对应-个单独的文件,比如ae_select.c、ae_ epoll.c、ae_ kqueue.c, 诸如此类。
第三部分、多机数据库的实现
- 第15章复制
- 第16章Sentinel
- 第17章集群
客户端的创建与关闭
服务器使用不同的方式来创建和关闭不同类型的客户端,本节将介绍服务器创建和关闭客户端的方法。
发送命令请求
Redis服务器的命令请求来自Redis客户端,当用户在客户端中键入一个命 令请求时,客户端会将这个命令请求转换成协议格式,然后通过连接到服务器的套接字,将协议格式的命令请求发送给服务器,如图14-1所示。
Sentinel
Sentinel (哨岗、哨兵)是Redis的高可用性(high availability)解决方案:由一个或多个Sentinel实例( instance)组成的Sentinel 系统(system)可以监视任意多个主服务器,以及这些主服务器属下的所有从服务器,并在被监视的主服务器进入下线状态时,自动将下线主服务器属下的某个从服务器升级为新的主服务器,然后由新的主服务器代替已下线的主服务器继续处理命令请求。
获取主服务器信息
Sentinel默认会以每十秒-次的频率,通过命令连接向被监视的主服务器发送INFO命令,并通过分析INFO命令的回复来获取主服务器的当前信息。
复制与故障转移
Redis集群中的节点分为主节点(master) 和从节点(slave) ,其中主节点用于处理槽,而从节点则用于复制某个主节点,并在被复制的主节点下线时,代替下线主节点继续处理命令请求。
故障转移
当一个从节点发现自己正在复制的主节点进入了已下线状态时,从节点将开始对下线主节点进行故障转移,以下是故障转移的执行步骤:
- 复制下线主节点的所有从节点里面,会有一个从节点被选中。
- 被选中的从节点会执行SLAVEOF no one命令,成为新的主节点。
- 新的主节点会撤销所有对已下线主节点的槽指派,并将这些槽全部指派给自己。
- 新的主节点向集群广播一条PONG消息,这条PONG消息可以让集群中的其他节点立即知道这个节点已经由从节点变成了主节点,并且这个主节点已经接管了原本由己下线节点负责处理的槽。
- 新的主节点开始接收和自己负责处理的槽有关的命令请求,故障转移完成。
消息
集群中的各个节点通过发送和接收消息(message) 来进行通信,我们称发送消息的节点为发送者(sender) ,接收消息的节点为接收者( receiver),如图17-40所示。
第四部分、独立功能的实现
- 第18章发布与订阅
- 第19章事务
- 第20章Lua脚本
- 第21章排序
- 第22章二进制位数组
- 第23章慢查询日志
- 第24章监视器
事务的实现
一个事务从开始到结束通常会经历以下三个阶段:
- 1)事务开始。
- 2)命令入队。
- 3)事务执行。
本节接下来的内容将对这三个阶段进行介绍,说明一个事务从开始到结束的整个过程。
EVAL命令的实现
EVAL命令的执行过程可以分为以下三个步骤:
- 根据客户端给定的Lua脚本,在Lua环境中定义一个Lua函数。
- 将客户端给定的脚本保存到lua_scripts字典,等待将来进一步使用。
- 执行刚刚在Lua环境中定义的函数,以此来执行客户端给定的Lua脚本。
向监视器发送命令信息
这两份【Redis核心原理和应用实践】【Redis设计与实现】文档分别为226页、849页,需要完整版的朋友,可以点赞此文关注小编,【见下图】即可获取!!
当然,单单有文档看是远远不够的,还有视频和相匹配的课件进行学习提升,努力把Redis这一块儿给搞明白,相信一定会有不凡的人生!!
架构师必备——Redis学习视频
Redis视频课件分享
Redis视频和课件获取,点赞关注小编,【见下图】获取!
好了,今天就分享到这里了,希望大家能够好好学习,把Redis这一块儿给提升上来,也希望本文能够得到大家的喜欢!!