Redis单线程为何可以处理大量请求?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Redis单线程为何可以处理大量请求?相关的知识,希望对你有一定的参考价值。
参考技术A 这得益于linux的IO多路复用应用层可以把多个socket连接注册给操作系统,让操作系统帮忙盯着这些socket有没有数据过来(可读/可写)。
注册完成之后,应用层就可以去干别的事了。当socket有数据过来时,操作系统会通知应用层,应用层再去处理。这样的优势在于应用层1个线程,就可以服务多个网络请求,即 IO 多路复用。
IO多路复用的具体实现模型有 select/poll/epoll,目前epoll是性能最好的。
一个网络程序,客户端A给服务端B发数据,A编写socket程序,调用write API向这个socket fd写数据。
写完之后,数据怎么发给B呢?
是需要经过操作系统、网卡、网线发过去的。
A的操作系统把数据按照网络协议包装好,通过网卡发出去,经过网络线路,最终都到B了。
B谁先来处理?肯定是操作系统先拿到这些数据,它会先放在内核态,然后通知上层的应用,你的数据来了,你来读取吧。
epoll是操作系统提供的API,应用层把socket提前注册给操作系统,先调epoll的注册方法,这就托管给操作系统了。
然后应用层再调用epoll的 wait 方法,有fd有数据过来/可写,就返回,返回指的就是wait方法return了,应用层就拿到这个fd可以操作了。不返回说明,注册的这些fd都不能读写,那应用层就阻塞在wait上等着,除非wait方法传了个timeout参数,那就到了timeout也给应用层返回。
这是读的情况。除了读,还有写。写对应的是发数据,fd可以写了,就通知应用层,应用就写这个fd。
还是拿刚才A->B传输数据来说。刚才说的是读,是B要读A的数据。现在看A这一侧,A要写这个fd给B发数据。
一开始写,fd对应的是操作系统的缓冲区,A写fd,会先写到操作系统的缓冲区里,然后由操作系统把缓冲区的数据发给B。
但如果A一直写一直写,B那边读的慢,那A这边的缓冲区就会满了,满了之后应用层还在调write,肯定就不可以写了,那啥时再可以写?A操作系统能知道B那边有没有把缓冲区的数据读走,如果读走了,缓冲区空出来了,那A的操作系统就通知应用层说,缓冲区空出来了,你继续可以写了。
fd是操作系统封装的数据结构,但凡一个应用层要做网络交互,必须经过操作系统,所以操作系统就提供了很多高效的办法,比如缓冲区和这些通知机制。
说白了就是,操作系统是一个大管家,其目的就是为了更好地服务上层应用,所以它做了很多事,这些IO多路复用,都是操作系统在帮应用层干活。
redis单线程问题
1.redis的单线程指的是什么单线程?
同一个时间点只处理一个客户端的连接,也就是redis网络模块的单线程。
2.redis为什么设计成单线程
具体作者怎么想的,我不知道,我说一下我的理解
(1)redis用的是非阻塞IO,非阻塞I/O本身就可以是单线程处理多个请求
(2)如果用多线程,就要考虑线程的上下文切换,和锁的请求和释放,这些操作也比较耗时,锁等待更容易把业务线程池占满
(3)在我看来,Redis的设计理念就是短平快,在保证完全内存计算的情况下,能串行的地方就串行,在处理socket请求这块采用了非阻塞IO,并且是纯内存操作,一个event loop(请求事件)下来,几乎没有等待点
3.redis是单线程为什么这么快
(1) 纯内存操作
(2) 异步非阻塞 I/O
(3) 单线程,避免了上下文切换和线程锁
4.服务性能三大杀手
(1) 大量线程导致的线程切换开销
(2) 请求和释放锁
(3) 非必要的内存拷贝
以上是关于Redis单线程为何可以处理大量请求?的主要内容,如果未能解决你的问题,请参考以下文章
Redis单线程已经很快,为何6.0要引入多线程?有啥优势?