redis 6.0 多线程机制

    redis一直以来都是单线程模式,优点是简单不用考虑数据竞争。这次引入了多线程,从命名上来看,也能看出只是针对IO操作,即收发来自socket的数据。至于执行命令,从内存中增删改查,仍然还是单个线程来操作。这样就不必考虑内存中多线程数据竞争问题。而各个端口自己数据的收发,因为是独立的,所以不存在数据冲突的可能。

   redis的IO线程设计的功能很有限,而且执行过程也被主线程严格控制。具体是主线程每次给IO线程分配好任务,当然主线程自己也接受任务。主线程完成自己任务后,一定等待辅助线程完成各自的任务,然后再进行后续执行命令的操作。redis并没有设计成主线程轮询各个子线程任务,如果某个任务先完成了,就先执行这个任务的后续操作,可能是从任务的顺序执行方面进行考虑的。同时多数情况下,各个任务的处理时间大体接近,主线程自己也有任务,等主线程完成操作后,基本上各个线程也完成差不多了。在每个客户端命令执行后,会形成应答信息,就需要再多线程发送出去,即是写的过程,流程与前面读取过程类似。整体过程是主线程先控制读取,然后再控制发送。每次完成一个流程再下一步。主线程不仅仅是个任务分发器,更像是一个带头大哥,时时刻刻在引领着整个队伍。

    值得注意的是这些IO线程被设计成忙等状态。轮询一个标志变量(atomic类型),等标志置位了,才去获取对应的队列。这里使用了基于原子变量无锁并发的一个技巧,主线程先写入队列,然后设置原子的标志。这样就可以确保辅助线程读取到标志位时队列一定是可见的,而且不会与主线程出现冲突。忙等可能会消耗CPU,当然如果任务队列时刻被占满就是另外一回事了。事实上redis设置了只有任务很重情况下才会开启多线程,平时这些线程就阻塞在各自的锁下,redis会根据发送任务数量与线程数比值来决定是否开启或者关闭多线程。所以如果发现使能了多线程模式,那么CPU必然会飙升也不奇怪了,当然这时候任务也必然是十分繁重了。redis的多线程设计哲学是平时能不用就不用,一旦发现负载大,马上开启,全力解决问题,一旦负载降下来,下一个定时周期就关闭。

  那么redis的主线程与辅助线程在处理连接的客户端时,是否会有冲突?毕竟需要对连接的客户端做一些操作,比如判断是否空闲超时?这个操作在主线程的cron中进行,会去扫描一个链表。而redis保证主线程运行cron时候,辅助线程必定不在访问这个链表(线程只是读取或者写入IO, 而且主线程会等待这个过程),故而不存在冲突。

 

你可能感兴趣的:(c语言)