线程IO模型
非阻塞IO
非阻塞IO在套接字对象上提供了一个选项Non_Blocking,当这个选项打开时读写不回阻塞,能读多少读多少,能写多少写多少,性能限制取决于内核文佩的读写缓冲区内不数据字节数。
事件轮询(多路复用)
事件轮询API主要是用来解决线程获取通知的问题,如果当缓冲区满了,数据写不完之后 ,剩下的数据何时才应该继续写。
- 事件轮询最简单的事select函数,他是操作系统提供给用户程序的API
- 输入是读写米哦啊叔列表read_fds&write_fds输出是阈值对应的可读可写事件。
- 提供timeout参数,如果没有任何事件到来,那么最多等待timeout的值事件,线程处于阻塞状态。一旦期间有事件到来就会立刻返回,时间过了也没有事件到来也会立刻返回。
- 一件事件处理完毕之后会继续进入轮询状态,于是线程就进入了一个死循环,也叫做事件循环。
指令队列
Redis会对每个客户端套接字关联一个指令队列,先到先服务
响应队列
Redis会给每个客户端提供一个响应队列,如果响应队列是空的,那么久表示不需要去获取写事件。
定时任务
Redis的定时任务会记录一在一个被称为“最小堆”的数据结构中,这个堆中,最快执行的任务排在堆的最上方。在每个循环周期中,redis都会对最小堆里面快到执行事件的任务进行处理,处理完毕之后,将最快执行的任务还需要的时间,设置成timeout。
通信协议
RESP
RESP是Redis序列化协议,他是一种直观的文本协议,优势在于实现过程简单,解析性能好。
Redis协议的5中最小数据类型
单元结束统一增加\r\n
- 单行字符串以“+”符号开头
+hello world\r\n
- 多行字符串以“$”开头
$11 \r\nhello world\r\n
- 整数值以“:”开头
:1024\r\n
- 错误信息以“-”开头
*error\r\n
- 数组以“*”开头
*3 \r\n:1\r\n:2\r\n:3\r\n
持久化
因为Redis操作对象是内存,如果服务器宕机,数据就会丢失所以需要使用持久化。
RDB快照原理
- Redis使用操作系统的多进程COW机制来实现快照持久化,同时进行服务请求的处理。
fork(多进程)
Redis在持久化时会调用glibc的函数fork产生一个子进程(RDB之bgsave),快照持久化完全交给子进程处理。
- 子进程做数据持久化,不回修改现有的内存数据结构,它只是对数据结构进行遍历读取,然后序列化到磁盘中。
AOF原理
- AOF日志存储的事Redis服务器的顺序指令序列,只记录对内存进行修改的指令记录。
- 假设AOP日志记录了Redis实例从创建开始的所有修改指令,那么可以通过对一个空的REdis实例顺序执行所有的指令也就是重放。
- Redis会在收到客户端指令后,进行参数校验、逻辑处理,如果没有问题就会放到AOF日志中,也就是说先执行,后写日志。
AOF重写
主要是对AOF文件进行瘦身,其原理是开辟一个子进程对内存进行遍历,然后转换成一系列Redis命令,序列化到一个薪的AOF文件中,过程中发生的指令以增量的形式添加到AOF文件中。
fsync
指令是指redis修改一次就更新AOF日志,这样可以保证数据不丢失,但是影响效率。
运维
快照是通过开启子进程的方式进行的,它是一个比较消耗性能的操作。
- 遍历整个内存,大块写磁盘会加重系统的负载。
- AOF的fsync是一个耗时的IO操作,它会降低Redis的性能,同时也会增加系统IO负担。
所以通常Redis的主节点不会进行持久化操作,持久化操作主要是从节点负责。
Redis4.0混合持久化
AOF文件太大,RDB容易丢失数据,所以为了解决这个问题Redis提供了混合持久化。
将rdb文件的内容和增量的AOF日志文件存放在一起。AOF文件不在做全量日志,而是做增量日志。
管道
Redis的消息交互
深入理解管道的本质
执行流程
- 客户端进程调用write将消息写到操作系统内核。
- 客户端操作系统将发送缓冲的内容发送到网卡,网卡硬件发送到服务器网卡。
- 服务器操作系统将网卡的数据放到缓冲区。
- 服务器进程调用read从缓冲区接受消息并处理。
- 服务器进程调用write将响应的消息写到缓冲区。
- 服务器操作系统将缓冲区的内容发送到网卡。
- 客户端操作系统将网卡的数据放到缓冲区。
- 客户端调用read从缓冲区中收到的消息返回给上层进行处理。
- 结束
事务
事务的基本用法
- begin事务开始
- commit事务提交
- rollback事务回滚
原子性
指事务要么全部成功,要么全部失败,不存在一部分成功一部分失败。
discard丢弃
用于丢弃事务缓存队列中的所有指令。