前言
在读这篇文章之前需要意识到redis线程安全,是IO多路复用+单线程处理命令工作的,redis是事件驱动程序。
redis一个命令请求过程
一、建立连接
IO多路复用技术
1、redis服务器采用IO多路复用技术,那么到底什么是IO多路复用技术,这里以netty举例,使用一个Boss线程处理accept,建立连接。建立连接后,把连接绑定给一个Work线程处理,work线程不断做select系统调用轮询,如果有read事件,利用分排器,分派文件事件。有人可能说了,redis不是单线程吗,那来的这么多线程。这里需要说明,多路复用技术是妥妥的多线程,redis 单线程的意思也不是它完全单线程。
2、Io多路复用如何保证消息顺序。对于一个客户端与服务器建立的单个tcp连接,io多路复用保证,只有一个work线程能够处理,这样TCP本身就保证有序性+单个线程处理一个socket的所有请求。保证了消息的顺序。
redis连接池
1、redis连接池,redis客户端也采用了连接池化的技术。为什么redis采用池化技术,就是因为,网络io的速度远慢于redis服务器处理命令的速度。所以需要多个socket连接去并发访问redis服务器,redis服务器又支持Io多路复用技术,可以通过多个线程分派多个socket的命令。
2、客户端使用了redis连接池,还能保证请求命令的顺序吗?显然是不能的。那么问题来了
像这样两行代码,难道第二行的代码可能会比第一行代码产生的redis命令先执行吗,当然是不可能的,redis客户端是同步执行的,第一行代码执行,没有收到redis服务器的执行成功或者失败回复会一直阻塞。
二、发送命令
接受命令并分派文件事件
1、当IO多路复用机制通过轮询发现了accept,read,write事件之后。就会调用先关联的处理器进行处理
2、例如,IO多路复用程序发现有read事件,触发read事件关联的文件事件进行处理
文件事件
1、什么是文件事件
2、文件事件如何保证线程安全
这里说明了,文件事件可能同时有很多个,但是都会被放入到队列中,由redis的单线程去消费队列里的事件。是由单线程执行的,因此是线程安全的。
3、文件事件如何处理命令
1)按照redis的协议从命令请求,并保存到相应客户端的缓冲区中
2) 对请求进行解析,提取出命令以及命令参数,例如
3)调用命令执行器,执行指定的命令调用对应命令的函数,被调用函数处理请求并产生响应的回复,对客户端的回复会被写入输出缓冲区中。最后由回复处理器将命令返回给客户端。
每次写命令后都会被写到aof缓冲区,至于何时刷到磁盘,由配置决定。
三、redis定时任务
时间事件
redis启动后,就使用单线程一直在不断的执行文件事件和时间事件,文件事件由io触发,时间事件由redis本身设置延时时间执行或者周期执行。
时间事件实例:serverCron函数
时间事件和文件事件怎么由一个单线程执行
由此可以看出,文件事件和时间事件都是同步,有序,原子执行的,因此redis 的过期任务,在redis运行期间删除数据也不会导致线程安全问题。