Redis非阻塞io多路复用线程模型
参考文章:https://www.cnblogs.com/hellohell/p/13817469.html
Redis是基于内存的高效存取的k-v数据库内存的响应时间大约是100纳秒,保证了Redis每秒万亿级别访问;Redis工作线程是单线程,后来的版本在持久化和删除过期键使用另外的线程,关于单线程如何高效的处理并发的网络请求,redis使用的是基于react模式(反应器模式,当检测到一个新的事件,将其发送给相应的Handler去处理)开发的网络事件处理器被称为文件事件处理器。组成结构:多个套接字、IO多路复用程序、文件事件分派器、事件处理器。
Redis客户端对服务端的调用分为发送命令,执行命令,返回结果三个过程,
文件事件处理器使用I/O多路复用(multiplexing)程序来同时监听多个套接字,并根据套接字目前执行的任务来为套接字关联不同的事件处理器。当被监听的套接字准备好执行连接应答(accept)、读取(read)、写入(write)、关闭(close)等操作时, 与操作相对应的文件事件就会产生, 这时文件事件处理器就会调用套接字之前关联好的事件处理器来处理这些事件。尽管多个文件事件可能会并发地出现,但I/O多路复用程序总是会将所有产生事件的套接字都推到一个队列里面,然后通过这个队列,以有序(sequentially)、同步(synchronously)、每次一个套接字的方式向文件事件分派器传送套接字:当上一个套接字产生的事件被处理完毕之后(该套接字为事件所关联的事件处理器执行完毕), I/O多路复用程序才会继续向文件事件分派器传送下一个套接字。
多路复用IO的实现是通过包装select、epoll、evport和kqueue这些I/O多路复用函数库来实现的,每个I/O多路复用函数库在Redis源码中都对应一个单独的文件,比如ae_select.c、ae_epoll.c、ae_kqueue.c等,Redis为每个I/O多路复用函数库都实现了相同的API,所以I/O多路复用程序的底层实现是可以互换的
文件事件的类型分为可读事件(connect read close)和可写事件(write),如果一个套接字同时产生了这两种事件,那么服务器将先读套接字,后写套接字。
Redis为文件事件编写了多个处理器,分别为socket关联连接、命令请求、命令回复处理器等。
总结如下:
问:redis是单线程的,为什么效率还那么高?
答:
1.纯内存访问
数据存放在内存中,内存的响应时间大概是100纳秒,这是redis每秒万亿级别访问的重要基础
2.非阻塞I/O多路复用机制
redis采用epoll实现的I/O多路复用,加上redis自身的事件处理模型,将epoll中的连接、读写、关闭转换为了事件,
避免了在I/O上浪费时间
3.单线程避免了线程的切换和竞争产生的消耗