前面我们提到过,redis是单线程的,这期我们详细介绍一下redis的单线程模型
1. redis单线程模型
redis只使用一个线程处理所有的请求,并不是redis服务器进程内部只有一个线程,其实也存在多个线程,只不过多个线程是在处理网络IO
假设有多个客户端同时操作一个redis服务器:
incr 作用是把key对应的value进行 + 1操作,在多线程中,这样的两个线程对一个变量进行写操作会导致线程安全问题,但是redis并不会,redis只会使用一个线程来指向这个两个命令,也就是这两个命令会串行执行。
因为redis的核心业务逻辑都是平短快的,所以使用单线程也能很好的工作,同时这里也提醒我们慎重使用操作时间长的操作,例如keys *
2. redis为什么快
有的人可能会疑惑,为什么redis使用单线程确还很快(面试题)
注意这里的快是相对于使用硬盘存储的数据库来说
1. redis 访问内存,数据库则是访问硬盘
2. redis 核心功能是要比数据库更简单的,数据库对数据的插入删除查询都有更复杂的功能支持
3. redis每个基本操作对cpu的消耗都不大,单线程也能很好的进行工作
4. redis处理IO的时候使用了IO多路复用机制
3. IO多路复用
IO多路复用就是使用一个线程管理多个连接
例举一个场景:
小明寝室有三个人要出去买午饭,小明想吃蛋炒饭,室友A想吃饺子,室友B想吃炒面,但是这几家店不在同一个位置,现在有几种买饭的方案:
- 只派一个人去买,先买蛋炒饭,等蛋炒饭做好了再去买饺子,最后去买炒面(传统的单线程,顺序执行)
- 三个人一起去买,各买各的(多线程)
- 只派一个人去买,先去买蛋炒饭,这里不等老板做好直接去买饺子,同理,然后去买炒面,哪个先做好先去拿哪个(IO多路复用)
可以看出,传统的单线程效率最慢,而多线程的话开销又太大,所以有了IO多路复用就可以让一个线程,在一个连接阻塞时去处理另一个连接,不过要注意IO多路复用适用于连接和服务器的交互不频繁,大部分时间都在等待的场景,如果交互过于频繁还是使用多线程更合理。
IO多路复用机制是操作系统提供的API实现的,Linux上主要提供了三种API:select,poll,epoll
效率最高的是epoll(事件通知/回调机制) 即连接退出阻塞时操作系统通知线程。