一. Redis架构
Redis 使用单线程架构和 IO多路复用模型来实现高性能的内存数据库。
单线程为什么这么快?
第一,纯内存访问,内存响应时长的单位是纳秒。
第二,非阻塞I/O, Redis使用epoll作为I/O 多路复用技术实现,Redis自身的事件处理模型将epoll中的连接、读写、关闭都转换为事件,不在网络I/O中浪费事件。
第三,单线程避免了线程切换和竞态产生的消耗。
IO多路复用
IO多路复用实现有如下:
1. select
将文件描述符(fd)放入一个集合中(fd_set,实际上是一个long类型的数组),当调用select时,将fd_set从用户空间拷贝到内核空间,由内核根据IO状态修改fd_set的内容,由此来判断哪个fd对应的socket可读。它的好处时可以在同一线程内同时处理多个IO请求。
select具有以下缺点:
需要维护一个存放大量fd的数据结构,每次将fd_set从用户空间复制到内核空间,开销大。
维持的fd数量有限,一般32位机器默认是1024, 64位机器默认是2048(在linux内核头文件中, 有定义: #define FD_SETSIZE 1024),这是操作系统防止该操作造成系统性能受到太大影响。
对fd采用轮询扫描, 效率低
采用水平触发, 如果报告了fd后, 没有被处理, 那么下次处理时还会通知进程。
2.poll
本质上与select没有差别,仅在fd存储方式有所不同,采用链表的方式存储(pollfd),达到可以维持任意数量的fd。但是select存在的其他缺点,它同样存在。
3. epoll(event poll)
是select和poll的增强版,维持任意数量的fd,epoll是基于系统内核的反射机制,在有活跃的fd时,系统会调用提前设置的回调函数。
单线程如何理解?
结论: 单线程只是针对redis中的模块来说。
比如 接受请求和响应是单线程,处理事件也是单线程 。但是线程不是同一个。同时Redis RDB快照或者AOF时候会fork一个子进程,很显然Redis整体不是一个单独的线程。