本文主要介绍redis单线程到多线程的发展历程。
redis诞生第一版
redis的第一版0.091,整个服务程序都是单线程的,从接收客户端请求,解析请求,执行请求,响应请求,都是一个线程一条龙服务。没有多线程的上下文切换,没有多线程因资源竞争而导致的加锁操作,以及使用非阻塞的io多路复用模型,整个操作都是在内存里操作(排除持久化),整个服务架构在第一版就已经成型,优秀的设计,高效的性能。

redis的第一个多线程版本
redis在2.0.0中引入了swap功能,即在内存不足的情况下,将内存中的对象序列化到磁盘上,腾出内存空间为其他对象使用;当需要被序列化到磁盘上的对象时,又将内存中最久未使用的对象序列化到磁盘上,并反序列化磁盘上的对象,加载到内存中。因磁盘io操作是非常耗时的,所以将写磁盘的工作交给了线程去处理。

redis的第一个线程子系统版本
redis在2.4.0中引入了background io system(BIO), 当时只是用来在后台处理系统调用close, 后续版本将扩展到其他的操作。BIO在初始化时创建了多个线程,每个线程处理一种类型的任务(简单),每个线程有自己独立的任务队列(不用竞争,实现简单,易维护)。

redis在4.0.0中引入了懒释放(LAZY_FREE),当需要删除key时,不是立刻删除,而是将删除任务发送给各个bio线程进行处理,减少主线程的阻塞。比如在同时大量的key过期(TTL到期),主线程将去进行删除,导致主线程阻塞无法响应客户端的请求。所以在开发时,对于需要设置大量的key并且都有固定的TTL时,可以在此基础上增加一个随机数,减少过期时服务器的压力。
redis的第一个网络io线程池
随着技术的发展,内存大,cpu快,网络带宽大等,大部分的性能都消耗在了网络io上,并且现在都是多核时代,redis的单线程无法充分利用多核(可以多实例),因此在redis6.0.0中引入了网络io线程池。
虽然使用多线程,但是多线程只用于网络io,即只用于网络的读取和写入,命令的执行还是主线程。

网络io线程同时只能处理读或者写,读写完成后,将执行权交给主线程。
总结:
redis之所以说它是单线程的,只是因为它是单线程执行命令,其实从正式发布的版本开始一直都是多线程。
本文介绍了Redis从单线程到多线程的演进过程,包括2.0.0版引入的磁盘IO线程处理序列化操作,2.4.0版的BIO线程系统,以及4.0.0版的懒释放机制。在6.0.0版,Redis引入了网络IO线程池,但仍保持命令执行的单线程特性。
908

被折叠的 条评论
为什么被折叠?



