前言
我们总能看到也总能遇到这些问题
Redis是单线程的吗?
为什么单线程的Redis会这么快?
首先我们要厘清一个事实,Redis的单线程,指的是网络IO和键值对读写是由一个线程来完成的,但其他功能如持久化,集群等都是额外线程执行的
为什么Redis使用单线程
在吹redis单线程的优势前我们需要了解多线程的优势
- 在多核处理系统上,将要执行的任务分割成多个可并行执行线程,可以提高执行速率(我们知道一个CPU在一个时间点只能执行一个任务)
- 单处理器上的多线程只能并发执行而不是并行执行,并发原理,其实就是cpu的快速来回切换达到在特定时间执行特点的某一个任务
- 当你的机器是多核时,多线程能通过提高CPU的利用率来提高效率。数据库访问、磁盘IO等操作的速度比CPU执行代码速度慢很多,单线程环境下,这些操作会阻塞程序执行,导致CPU空转,因此对于会产生这些阻塞的程序来说,使用多线程可以避免在等待期间CPU的空转,提高CPU利用率
并发和并行的区别
你明天要去和多个女孩约会
并发:约完一个之后马上去和下一个见面(CPU来回切换执行任务)
并行: 你会分身术,制造多个分身去和不同女孩约会
多线程虽然充分利用了CPU的执行率,但也存在缺点,比如常常存在一个资源被多个线程同时访问的情况,通常的做法是,为保证资源的正确性在访问时为该资源加锁,因为这个机制会带来额外的开销,所以常常会出现因为设计的不合理而达不到增加线程数来提高系统吞吐率的结果。
假设有一个队列list,Redis为修改键值多线程操作,线程1要对list做LPUSH操作,线程2要对list做LPOP操作。为保证队列的正确性我们就要让两者串行操作,否则就会得到错误的长度(只要有并发处理,就一定有性能开销)
因此使用单线程对键值对操作,能达到无锁无竞争的结果,Redis的单线程消费模式保证了这些开销统统都是不存在的
另一方面在网络上Redis采用了多路复用机制
IO多路复用机制允许内核,同时监听多个套接字和已经连接的套接字,打个比方:
1.你(单线程)要帮多个同学去用热水壶打热水,接热水要去学校统一的地方,且烧好要等时间,你将多个热水壶放在水龙头下(监听套接字),哪个水龙头有热水(请求来了)了你就打开哪个接水(处理网络请求)
2.一家医院只有你一个医生(单线程),每个病人(等于请求)都需要分诊、测温、登记等,这些工作如果全由你完成那么效率会很低。医院设立了分诊台,分诊台会一直处理这些诊断前的工作(类似Linux内核监听请求),再把病人给你做诊断
Redis6.0在网络中的多线程,只是在网络通信层面增加了多线程,核心消费请求模块仍是单线程处理
redis采取这种模式,无非是想解决网络的性能瓶颈,毕竟一百个malloc操作也比不上一次网络IO的时间长,事实上网络IO读写才占去整个操作时间的大头
总结
单线程的Redis之所以那么快是因为一方面,操作基于内存,提供了高效的数据结构,另一方面用单线程避免了多线程并发控制的开销,使用多路复用的IO模型处理网络请求,避免了套接字执行accept()/send()/recv()潜在的网络IO操作阻塞点
网友评论