03 | 高性能IO模型:为什么单线程Redis能那么快?
该思维导图由 AI 生成,仅供参考
Redis 为什么用单线程?
多线程的开销
- 深入了解
- 翻译
- 解释
- 总结
Redis作为单线程高性能的特点,得益于其精巧的设计和多路复用机制。文章首先解释了Redis采用单线程模型的原因,指出多线程开发中的共享资源并发访问控制问题会带来额外开销,降低系统吞吐率,而采用多线程还会降低系统代码的易调试性和可维护性,因此Redis直接采用了单线程模式。然后,文章详细介绍了Redis采用单线程模型如何实现高性能,主要包括大部分操作在内存上完成、采用高效的数据结构和多路复用机制。在多路复用机制方面,文章重点介绍了基本IO模型与阻塞点,以及非阻塞模式的设置,以保证Redis线程不会在阻塞点一直等待,也不会导致Redis无法处理实际到达的连接请求或数据。文章内容深入浅出,为读者解释了Redis单线程高性能的原因,使读者能够快速了解Redis的技术特点。 文章还提到了Redis 6.0中提出了多线程模型,这可能引入复杂的并发控制问题,而关于这些问题,作者承诺在后续课程中进行详细介绍。整体而言,本文通过对Redis单线程模型和多路复用机制的解释,为读者提供了对Redis高性能特点的深入理解。
《Redis 核心技术与实战》,新⼈⾸单¥68
全部留言(139)
- 最新
- 精选
- 柳磊作者您好,引用文中一段话“我们知道了,Redis 单线程是指它对网络 IO 和数据读写的操作采用了一个线程”,我有个疑问,redis为什么要网络IO与业务处理(读写)用一个线程?而不用Netty中常见的Reactor线程模型,把io线程(netty中的boss线程)与业务处理线程(netty中的work线程)分开,业务处理线程只开启一个线程,也不会有共享资源竞争的问题。
作者回复: 在Redis 6.0版本前,Redis用一个线程实现网络请求的解析和读写处理,我个人觉得主要还是这种线程模型实现简单。 不过随着网络硬件越来越快后,网络请求收发更快了,所以从Redis 6.0开始,网络请求解析也是由专门的线程处理,从而支持快速网络读写。而读写处理仍然由单个主线程执行,这是为了避免多线程协调的开销。
2020-12-15356 - zhou老师分析的 redis io 模型中,redis 线程是循环处理每个事件的。如果其中一个事件比较耗时,会影响后面事件的及时处理。
作者回复: 是的,所以如果有慢操作的话,就会影响其他操作了。
2020-08-1413 - 竹真作者您好,读完您的文章还有点疑惑,Redis读取客户端数据和读内存是一个线程?
作者回复: Redis 6.0前的版本是用一个线程来读取网络请求并进行解析,并根据请求的具体命令操作进行数据读写的。Redis 6.0开始,网络请求的解析可以用多线程来执行,但是读写内存还是一个线程。
2020-11-06312 - spoofer还有的性能瓶颈:即使io复用已经很牛叉了,但是redis线程始终是用户线程,要读取或者写入网络数据,还是要进行read和write的系统调用的,而系统调用是一个耗时的操作。so~~ 为什么6.0要引入多线程?一个原因就是要找些小弟来处理这个耗时的数据读写啊~~~
作者回复: 耗时的系统调用,这个对高性能系统来说是个潜在瓶颈。
2020-11-059 - BrightLoongRedis 单线程是指它对网络 IO 和数据读写的操作采用了一个线程 对这句话不是很理解,总觉得是处理网络IO是一个线程,然后把事件放入队列;读写操作又是一个线程,从队列中处理请求。求解答
作者回复: 在Redis 6.0前,网络请求的解析和数据读写都是由主线程来完成的,这也是我们称之为单线程的原因。 从Redis 6.0开始,网络请求的解析是由其他线程完成,然后把解析后的请求交由主线程进行实际的内存读写。
2020-11-1277 - 滴流乱转小胖儿老师你好,单线程的处理事件队列中的事件,这样还是会遇到性能瓶颈吧?
作者回复: 如果这个事件处理本身很耗时,例如对一个大集合的key进行全量操作(比如SMEMBERS, HGETALL),这也是会引起性能瓶颈的。
2020-08-104 - 华仔Redis在Linux上应该是单进程,不能说是单线程,main函数完成初始化后就进入事件循环处理,快照的时候也是直接fork一个新进程,而不是pthread_create一个新线程,请老师确认一下
作者回复: 称为单线程的进程可能更合适些,进程中处理读写操作的就是一个线程。也可以看下第10讲常见问题答疑中的第二个问题。 快照时是用的fork,创建新的子进程。
2020-11-2922 - LovePeace请问文章提到的套接字是指socket吗?
作者回复: 是的,就是指socket。
2020-10-161 - 0bug操作大key的时候,IO是性能瓶颈
作者回复: 没错,bigkey是一直要关注的问题,再和单线程模型一叠加,容易出事。
2020-08-1021 - KaitoRedis单线程处理IO请求性能瓶颈主要包括2个方面: 1、任意一个请求在server中一旦发生耗时,都会影响整个server的性能,也就是说后面的请求都要等前面这个耗时请求处理完成,自己才能被处理到。耗时的操作包括以下几种: a、操作bigkey:写入一个bigkey在分配内存时需要消耗更多的时间,同样,删除bigkey释放内存同样会产生耗时; b、使用复杂度过高的命令:例如SORT/SUNION/ZUNIONSTORE,或者O(N)命令,但是N很大,例如lrange key 0 -1一次查询全量数据; c、大量key集中过期:Redis的过期机制也是在主线程中执行的,大量key集中过期会导致处理一个请求时,耗时都在删除过期key,耗时变长; d、淘汰策略:淘汰策略也是在主线程执行的,当内存超过Redis内存上限后,每次写入都需要淘汰一些key,也会造成耗时变长; e、AOF刷盘开启always机制:每次写入都需要把这个操作刷到磁盘,写磁盘的速度远比写内存慢,会拖慢Redis的性能; f、主从全量同步生成RDB:虽然采用fork子进程生成数据快照,但fork这一瞬间也是会阻塞整个线程的,实例越大,阻塞时间越久; 2、并发量非常大时,单线程读写客户端IO数据存在性能瓶颈,虽然采用IO多路复用机制,但是读写客户端数据依旧是同步IO,只能单线程依次读取客户端的数据,无法利用到CPU多核。 针对问题1,一方面需要业务人员去规避,一方面Redis在4.0推出了lazy-free机制,把bigkey释放内存的耗时操作放在了异步线程中执行,降低对主线程的影响。 针对问题2,Redis在6.0推出了多线程,可以在高并发场景下利用CPU多核多线程读写客户端数据,进一步提升server性能,当然,只是针对客户端的读写是并行的,每个命令的真正操作依旧是单线程的。2020-08-10821367