问:Redis为什么是单线程的

Redis为什么是单线程的?(允许你重新组织语言,好好说)

M大: 能不能解释一下Redis为什么是单线程的?

Me:主要可以从两个方面来解释。

  • 一是和多线程对比,虽然多线程可以充分利用cpu资源,但是线程间上下文切换也是一笔开销,另外一旦引入多线程就要考虑数据一致性问题,会增加实现的复杂度。其次Redis是基于内存的缓存系统,单机每秒可处理10w+的请求操作,cpu不是它的瓶颈。
  • 另一个方面是Redis采用了相对高效的多路复用IO模型。(解释一下什么是IO多路复用吧)

M大: 解释一下什么是IO多路复用吧?

Me:这里需要对比一下阻塞式和非阻塞式IO模型。

  • 客户端和操作系统内核建立连接时会创建文件描述符,服务端程序会监听FD的IO事件
  • 阻塞式IO的模型下,进程通过recvfrom函数调用内核阻塞等待数据返回。如果要处理多个客户端的请求,可以使用多线程单独处理,但是随着客户端连接数的变大,创建线程也是很大一笔开销。
  • 非阻塞式IO模型下,进程可以通过调用read函数立即返回结果,如果没有IO请求会直接返回error,可以通过不断轮询方式异步处理,一旦有就可以从内核获取数据。还是存在大量内核调用
  • IO多路复用通过多种方式譬如epoll、select、poll等实现了一次函数调用获取到有效FD的操作,之后再根据有效的FD获取数据。(是不是要问一下这几种实现的区别呢)

M大: 可以描述一下select、poll、epoll之间的区别吗?

Me: 好的

  • select函数将非阻塞式IO搬到了内核之中,通过调用函数可以获取到目前活跃fd,然后对活跃的fd调用read函数就可以获取到数据。内核中还是会轮询所有fds,且有连接数限制
  • poll函数使用链表解决了连接数限制的问题。
  • epoll通过三个函数调完成。epoll_create创建一个event_poll数据结构体,里面维护一个红黑树和双向链表。通过调用epoll_ctl注册一个文件描述符加入红黑树之中,一旦有文件描述符就绪就会将其引用放入双向链表之中并产生回调。最后调用epoll_wait函数等待通知。这里利用mmap技术省掉了文件描述符在内核和用户态之间来回调用的开销。redis默认是使用的epoll

M大: Redis在6.0之中引入了多线程版本,你知道吗?

Me:恩,有了解过

  • 这个多线程指的是IO多线程,是对之前的一部分优化,其实在处理真正的指令的时候还是单线程的。
  • 我们知道执行命令前后都会有解析命令IO,action操作,回写结果 IO 。如果有多个指令同时到达,用多个线程来处理指令解析和结果回写的IO操作

 

相关推荐