Redis为什么快?
1.Redis所有数据都在内存中存储,所以所有运算都是内存级别的运算。正因为避免了从磁盘中获取数据,Redis才会如此的快。
2.还有一点就是因为Redis是单线程程序(需要注意的是,io多路复用器是单线程执行,事件处理器也是单线程执行,两个线程不一样。只是不同的模块都用的单线程实现。),从而避免了无意义上下文切换的消耗。但也因为如此,时间复杂度高(O(n))的指令如keys 可能会导致Redis卡住。
多路复用
事件轮询也就是多路复用,是用来解决非阻塞IO的线程通知问题——当数据准备好,线程如何得到通知;缓冲区被写满,数据写不进去,剩下的数据该何时被写入,线程又如何得到通知。
事件轮询API,操作系统提供的select函数就是解决问题的关键。
输入为读写描述符列表read_fds&write_fds,输出为对应的可读写事件。
拿到事件后,线程可以继续处理相应事件,处理完了过来轮询。
read_event, write_event = select(read_fds, write_fds, timeout);//如果没有时间,则等待timeout的值的时间,线程阻塞
for(Event event:read_event){
handle_read(event.fd)
}
for(Event event:write_event){
handle_write(event.fd)
}
do_others();
最后,现代操作系统用epoll和kqueue来替代select函数同时处理多个通道描述符的读写事件,因为select系统调用的性能在描述符多的时候会变差。
指令队列
Redis将每个客户端套接字关联到一个指令队列,客户端的指令通过队列顺序处理(FIFO)
响应队列
Redis同时为每个客户端套接字关联到一个响应队列,Redis服务器通过响应队列将指令的返回结果回复给客户端。
定时任务
Redis的定时任务记录在最小堆中。每个循环周期中,Redis会对最小堆里已经到时间点的任务进行处理。