Redis为什么这么快
1、完全基于内存,绝大部分请求是纯粹的内存操作,非常快速。数据存在内存中,类似于HashMap,HashMap的优势就是查找和操作的时间复杂度都是O(1);
2、数据结构简单,对数据操作也简单,Redis中的数据结构是专门进行设计的;
3、采用单线程,避免了不必要的上下文切换和竞争条件,也不存在多进程或者多线程导致的切换而消耗 CPU,不用去考虑各种锁的问题,不存在加锁释放锁操作,没有因为可能出现死锁而导致的性能消耗;
4、使用多路I/O复用模型,非阻塞IO;
linux提供select/poll,进程通过将一个或多个fd传递给select或poll系统调用,阻塞在select;这样select/poll可以帮我们侦测许多fd是否就绪。但是select/poll是顺序扫描fd是否就绪,而且支持的fd数量有限。linux还提供了一个epoll系统调用,epoll是基于事件驱动方式,而不是顺序扫描,当有fd就绪时,立即回调函数rollback
多路复用主要解决的是一个线程监控多个socket的问题(https://www.cnblogs.com/Joy-Hu/p/10762239.html)
目前最高效的解决策略是epoll 他是一种基于事件驱动的策略
epoll有3个函数 epoll_create epoll_ctl epoll_wait
当请求到来时 会先执行epoll_create 创建一个eventpoll对象 这个对象内部有 阻塞队列 和就绪链表,
接着调用epoll_ctl注册事件和回调函数,
然后调用epoll_wait 如果就绪队列有数据则直接返回执行socket
如果没有数据 则将当前进程放入eventpoll的阻塞队列,阻塞进程, 当数据到来的时候, 中断程序会将对应的socket放入就绪队列中,同时唤醒阻塞队列中的进程。
epoll高效的原因(https://www.cnblogs.com/setevn/p/8779269.html)
1. select 只是单纯告诉你有socket可以读了 但是没有告诉你哪个socket可以读, 所以要循环检查所有监听的socket
而epoll会返回有哪些socket可以读数据
2.
Select 模式
while true
{
select(streams[]) //这一步死在这里,知道有一个流有I/O事件时,才往下执行
for i in streams[]
{
if i has data
read until unavailable
}
}
Epoll模式
while true
{
active_stream[] = epoll_wait(epollfd)
for i in active_stream[]
{
read or write till
}
}