redis只使用一个线程,处理所有的命令请求,但不代表redis服务器进程内部就只有一个线程,在处理网络IO下是使用单线程。
多个客服端,同时操作一个redis服务器
两个客服端并发的发送对counter+1操作的请求,在多线程中,两个线程同时对一个变量进行自增存在线程不安全问题,而在单线程下可以保证多个请求是串行执行的。多个请求同时到达redis服务器,需要在队列中排队,等待redis服务器一个一个的取出里面的命令。
redis能够使用单线程模型,主要是redis的核心业务逻辑,都是短平快,不太消耗cpu资源。因此redis要特别小心,如果某个操作占用时间过长,就会阻塞其他命令的执行(如keys *)
redis虽然是单线程模型,为什么效率那么高?速度这么快?
- redis访问内存,数据库则是访问硬盘
- redis核心功能,比数据库的核心功能简单(数据库中有各种约束)
- 单线程模型,避免了不必要的线程竞争开销
- 处理网络IO的时候,使用IO多路复用机制
- IO多路复用:一个服务器服务多个客服端,针对TCP来说,服务器每次服务一个客服端,都需要给每个客服端安排一个socket,所以需要多个socket。但是在很多情况下,每个客服端和服务端之间的通信并没有非常频繁,socket大部分时间都是静默的,上面并没有数据传输,也就是同一时刻,只有少数socket是活跃的。因此我们就可以让一个线程,管理多个socket。
举个例子:晚上我爸要吃炒饭,我妈要吃煎饺,我要吃手抓饼。如果各买各的就是三个线程同时工作,系统开销大。所以我自己去买这三个东西(单线程)如果我先买炒饭,等炒饭好了,再去买煎饺,等煎饺好了,再去买手抓饼,这个过程效率低下。反之,我在等炒饭的时候,去买煎饺,又在等煎饺的时候,去买手抓饼。哪个先做好,对应的老板就会喊我去拿。这个过程就让一个线程同时做了三件事,当然能完成这三件事的前提是这三件事交互不频繁,大部分时间都在等待,这就是IO多路复用。而老板完成后喊我去拿就是C++的epoll的事件通知机制。