前言
- 今天偶然看到Redis是单线程的,因此就产生了一系列疑问,之前看《Redis设计与实现》的时候,只关注了Redis相关数据结构的设计,没有注意到单线程。
Redis和I/O多路复用
- 为什么 Redis 中要使用 I/O 多路复用这种技术呢?
首先,Redis 是跑在单线程中的,所有的操作都是按照顺序线性执行的,但是由于读写操作等待用户输入或输出都是阻塞的,所以 I/O 操作在一般情况下往往不能直接返回,这会导致某一文件的 I/O 阻塞导致整个进程无法对其它客户提供服务,而 I/O 多路复用就是为了解决这个问题而出现的。
关于Redis单线程
-
1、Redis采用单线程进行设计,显然Redis server不会有线程安全的问题,同时避免了引入多线程的复杂性和各种锁带来的性能问题,间接降低了Redis编码的复杂性,保证了代码的整洁与低bug。
-
2、Redis作为数据库,显然会有大量的IO,单线程显然不适合IO密集型场景。Redis采用I/O多路复用缓解这种问题。在并发编程中,我们都知道应该根据业务场景,选择合适的并发线程数,最大化利用CPU资源。 在Java中可以通过
Runtime.getRuntime().availableProcessors()
获取可用的线程数。- IO密集型:设置的线程数通常会大于服务器的核心线程数(2倍或根据实际情况进行调整)。
- 计算密集型:设置的线程数通常不会大于服务器的核心线程数。
-
3、Redis提供了阻塞队列的API,例如
BLPOP...
,显然Redis的阻塞队列阻塞的其实是Client,否则,这对于单线程的Redis来说是致命的。 -
4、Redis显然不适合计算密集型场景,例如求set交集等命令。就一个线程,如果一个命令计算较长一段事件,这显然会很大程度降低Redis的并发量,这往往是不可接受的。
-
5、随着摩尔定律的失效,现代CPU的核心数是越来越多,单线程自然无法充分利用CPU资源,唯一的解决办法就是多开几个Redis实例。
网友评论