redis 为啥这么快?
1,redis所有的数据是在内存中,所有的操作都是内存级别的运算。
2,redis是单线程,避免了多线程的切换和加锁消耗。
3,redis使用epoll作为非阻塞I/O多路复用,多路复用监听多个socket,并将socket放入队列中,每次从队列取一个socket交给事件分配器,事件分配器再把socket交给事件处理器,事件处理器的所有操作都是内存级别的,处理一个事件只需要几微妙。
I/O多路复用
fd_set 数组是0和1 的位数组,fd是文件描述符
select:它维护了一个数组结构 fd_set,调用 select 函数时,会从用户空间拷贝 fd_set 到内核空间,并监听是否有事件触发,有就通过无差别轮询的方式遍历找到事件触发的位置,然后执行相关的读或写操作。轮询的时间复杂度为 O(n)。
缺点:内核对被监控的 fd_set 集合做了大小限制,最大为 1024 ;每次调用 select,都需要把 fd_set 集合从用户态拷贝到内核态,都需要在内核遍历 传递进来的所有 fd_set ,效率很低。
poll:与 select 类似,区别是它采用的是 poll_fd 数据结构实现了一个可变长的数组,没有了最大文件描述符数量的限制。
epoll:epoll 与 select 的不同之处在于,epoll 监听事件是否触发时,还设置了回调函数,如果事件触发,就执行回调函数,并将准备就绪的 fd 放到 readyList 中,而不需要轮询遍历所有的 fd_set 。并且 epoll 没有最大文件描述符数量的限制。在高并发情况下 epoll 能支持更多的连接。