思维导图:
引言
本文是对于Redis原理的初步介绍,涉及到 5个方面,分别是线程IO模型,通信协议,事务,管道和持久化。
一.线程IO模型
Rdies是个单线程程序,这是Reids速度快的一个原因,因为没有线程切换的开销,缺点则是当执行时间复杂度较高的操作或者指令时,可能会导致Reids的卡顿。与此同时,Redis还善于处理多并发客户端连接,而这得益于Redis的IO模型。
Redis使用了非阻塞IO模型。即当需要读取数据的时候能读多少读多少,而不是一直阻塞,直到读取所需要的全部数据,在写的时候,能写多少写多少,而非一直阻塞,直到写入所有需要写入的数据。使用非阻塞IO可以保证Redis不会因为读写数据二阻塞。因为使用了非阻塞IO,所以存在一个问题,如果读了一半甚至更少就返回或者当写缓存已满却没有写入所有数据时,因为使用了非阻塞IO,此时读写操作就返回了。这个问题的解决,就需要使用到事件轮询机制或者多路复用。

事件轮询API是系统提供给用户的功能函数,输入读写描述符read_fds & write_fds以及超时时间timeout,输出则是相应的读写事件。Redis会不停的调用事件轮询API已获取事件,然后进行处理。当通过此select系统处理多个同道描述符时,这类系统调用也就称为多路复用。

Redis服务器会为每个客户端关联一个请求队,先到先处理。Redis服务器也会为每个客户端关联一个响应队列,以此将结果返回客户端。
Redis的所有定时任务会被放置在一个最小堆中,每次循环都会处理最小堆中已到时间点的定时任务,然后会记录到下一个定时任务所需要的时间,然后将此时间设置为下一次事件轮询的timeout参数,这样就保证了定时任务不会因为阻塞而执行不了。
二.通讯协议
Reids的通讯协议名为RESP(Redis Sserialization Protocol),这是一种文本协议,实现相当简单。他将数据结构分为以下五种基本单元,并在单元结束时统一加上回车换行符\r\n。
- 单行字符串:以 + 开头,+hello world\r\n
- 多行字符串:以 $ 和字符串长度开头, $11\rnhello world\r\n
- 整数:以:开头,:100\r\n
- 数组:以 * 和数组长度开头:例如数组【1,2,3】,*3\r\n:1\r\n:2\r\n:3\r\n
- 错误:以-开头,-错误描述
客户端发送到服务器的都是多行字符串,而服务器响应客户端的则是5种数据单元的组合使用。
三.持久化
Redis的持久化分为两种,一种是快照,快照是一次全量备份,另一种则是AOF,AOP是一种增量备份。
3.1 快照
快照就是像拍照一样将Redis在某一瞬间的所有数据利用文件IO写入到本地文件之上。但是快照是一个相当耗时的操作,而Redis又是单线程的,如何保证Redis在进行快照的同时还可以对客户端提供服务并且不会将快照后的增量数据写入快照文件呢?
Redis利用了多进程COW(copy on write)来实现快照的持久化。其原理是Redis会调用glibc的fork函数产生一个子进程用于进行持久化,父进程则继续为客户端提供服务。此子进程会和父进程共享内存中的所有数据(数据由多个数据段组成)。父进程在对客户端提供服务的同时不可避免的会添加或者修改内存中的数据,为了避免子进程将这部分增量数据持久化,父进程会对相应的数据段进行复制,然后在复制的数据段上进行增量操作。这样就不会影响到子进程的持久化了。
3.2 AOF
AOF的原理是存储对内存进行修改的指令序列到日志中去。加入有一个AOF日志存储Redis自创建以来的所有修改指令,便可以通过执行AOF日志中的所有指令来恢复Redis的状态,毫无疑问这是一个非常耗时的操作。
3.3混合持久化
混合持久化即是同时利用了快照和AOF,在进行了快照以后,在进行AOF,并将AOF日志放在快照文件之后,以此达到快速重启Reids的目的

四.事务
Redis的事务机制是以 multi 开始,此后的指令会被缓存在一个事务队列中,使用 exec 开始执行所有指令,或者使用 discard 丢弃事务队列中的指令。如果某一个指令执行失败了,事务队列中的指令也会继续执行。
所以,Redis的事务和普通数据库事务的不同点在于 Redis的事务不具备原子性,而只有隔离性。只是实现了当前执行的事务不会被其他事务打断的功能。
五.管道
管道Pipeline本身并不是Redis服务器提供的技术,其本质是客户端提供的指令重排功能。
举例,现在需要进行两次读写操作,所以,共需要4个指令 write read write read。如果指令顺序是write read write read,那么就需要进行4次网络数据的传输,如果将执行顺序修改为write write read read ,那么,通过2次数据传输便可以了。
所以,读写缓存中的指令越多,使用管道的效果也就越好,可以节省大量的IO时间。


本文深入探讨Redis的基本原理,包括单线程的非阻塞IO模型、简单易用的RESP通讯协议、快照与AOF持久化策略,以及事务和管道技术。Redis利用多进程COW实现快照持久化,通过AOF记录修改指令,确保数据安全性。
1139

被折叠的 条评论
为什么被折叠?



