Redis是单线程还是多线程?
1)如果只是针对于Redis的核心业务部分(命令处理),答案是单线程
2)如果是说整个redis,那么就是多线程
在Redis的版本迭代过程中,在两个非常重要的时间节点上引入了对多线程的支持:
1)在Redis4.0版本中,引入多线程异步处理一些耗时比较长的任务,例如说异步删除命令unlink,对于一些BigKey如果直接进行删除的话,可能会导致主线程阻塞,那么就会耗时非常的久,这是往往会采取一种一部删除的策略,先标记成删除状态,后台再慢慢开启一个线程删除;
2)再Redis6.0版本中,在核心网络模型中引入了多线程进一步提高了对于多核CPU的利用率
3)redis是单线程的原因在于redis用单个CPU绑定一块内存的数据,然后针对这块内存的数据进行多次读写的时候,都是在一个CPU上完成的
Redis为什么要选择单线程?
1)抛开持久化来说,Redis是纯内存操作,执行速度非常快,它的性能是网络延迟而不是执行速度,因此多线程并不能带来比较大的性能提升;
2)多线程会导致频繁的上下文切换,带来比不要的开销;
3)引入多线程会带来线程安全问题,必然要引入多线程锁这样的安全手段,实现起来复杂度高,而且性能也会大大下降;
Redis的网络模型:
Redis通过IO多路复用来提升网络性能,并且支持不同类型的多路复用实现,并且将这些实现进行了封装,提供了统一的高性能事件库AE
1)首先在main函数里面启动初始化服务,调用initserver()函数,首先会调用aeCreateEventLoop函数,在这个函数里面会调用awApiCreate(eventLoop),eventLoop就是epoll实例,在操作系统内核里面红黑树和链表都已经准备好了
2)接下来会调用listenToPort方法,监听TCP端口和Ip地址,创建ServerSocket,并得到了ServerSocket对应的FD,IP地址和端口号都是配置文件里面指定的;
3)接下来redis会继续调用createSocketAcceptHandler函数,注册连接处理器,内部会调用aeApiAddEvent(&server,ipfd)来将ServerSocket对应的fd挂到红黑树上面并监听ServerSocket对应的FD,相当于是epoll_ctl函数了,因为监听ServerSocket要等待fd就绪,就意味着有客户端Socket连接上来了,就需要接受客户端的Socket,Socket接受的处理器就是AcceptTcpHandler,这个处理器的作用就是处理SeverSocket上面的事件的,这个处理器至少要做两件事情:
3.1)监听ServerSocket;
3.2)提前配置好,一旦ServerSocket发生事件,及时做处理;
4)所以说进行预测这个处理器做的工作应该是一旦ssfd就绪了,那么直接处理器调用accept函数和客户端Socket进行建立连接,把这个客户端对应的FD实例注册到epoll实例上;
5)最后调用了一个aeSetBeforeSleepProc函数,按照道理来讲,在监听已经注册好了以后,下一步就需要调用这个wait即可,一旦没有fd就绪,那么主线程就会直接休眠等待fd就绪,一旦fd就绪,主线程就会被唤醒