单线程
- 对于每个Redis实例,在内部是使用单线程来处理所有命令请求的,即所有命令在该线程中排队执行。同时需要注意的是单个Redis实例的16个数据库的操作也都是共享这个单线程的,所以在设计时,如果16个数据库或者多个都要存放数据并且读写较频繁,则推荐采用独立的Redis实例来保存各个数据库的数据,即使用不同的端口来启动多个Redis实例,每个使用0号数据库。
单线程的实现基础
- Redis实例作为一个服务器可以处理很多的Redis客户端的连接和请求,采用单线程来实现连接管理和请求处理主要是基于IO多路复用技术来实现的。
- IO多路复用在Linux中是基于Linux提供的selector或epoll机制来实现的。将连接注册到内核中,内核监听这些连接是否存在IO事件过来,如果存在,则通知应用线程来处理这些IO事件。
使用单线程的原因
- Redis的所有数据都是保存在内存中,相当于Java中的HashMap,故操作速度非常快,所以单线程不会影响性能。同时使用单线程可以避免了线程上下文切换,因为线程上下文切换涉及到内核用户态和内核态的切换,会影响应用程序性能,所以单线程也进一步提高了性能。其次使用单线程由于所有操作都在该线程执行,则避免了多线程中加锁来进行线程同步的问题,保证了线程安全性。
使用单线程存在的问题
- 由于所有操作都在同一个线程中排队执行,所以如果某个操作需要较长时间,则会阻塞后面排队的操作的执行,如使用keys命令会阻塞其他命令的执行,