当前位置: 首页 > 科技观察

为什么Redis在6.0之前没有使用多线程?

时间:2023-03-13 16:19:35 科技观察

Redis6.0在5.2这个美好的日子悄然发布。这个版本在IT圈犹如晴天霹雳,因为这是Redis最大的一次改版,首次加入了多线程。作者Antirez在发布RC1版本时在他的博客上写道:迄今为止最“企业”的Redis版本//迄今为止最大的Redis版本//参与人数最多的版本//这个参与人数最多的变化,性能提升很快~先贴出新版本和旧版本的性能图:从上面可以看出GET/SET命令的性能对比单线程时4个线程IOThreads几乎翻倍。另外,这些数据只是为了简单验证多线程IO是否真的带来了性能优化,并没有针对严格的延迟控制和不同的并发场景进行压力测试。数据仅供验证参考,不能作为线上指标,也只是当前unstble分支的表现。不排除后面发布的正式版性能会更好。Redis6.0之前的版本真的是单线程的吗?Redis基于Reactor模型开发了网络事件处理器,称为文件事件处理器。它由4部分组成:多套接字、IO多路复用程序、文件事件派发器、事件处理器。因为文件事件调度队列的消费是单线程的,所以Redis被称为单线程模型。一般来说,Redis的瓶颈不是CPU,而是内存和网络。如果要使用CPU多核,可以搭建多个Redis实例来解决。事实上,Redis4.0就从多线程的概念开始,比如Redis通过多线程在后台删除对象,通过Redis模块实现的阻塞命令。为什么Redis在6.0之前没有使用多线程?使用单线程后,可维护性高。多线程模型虽然在某些方面表现良好,但引入了程序执行顺序的不确定性,带来了读写并发的一系列问题,增加了系统的复杂度,并且可能有线程切换甚至加锁导致的性能损失解锁和死锁。Redis通过AE事件模型和IO多路复用技术具有非常高的处理性能,所以不需要使用多线程。单线程机制大大降低了Redis内部实现的复杂度,Hash的惰性Rehash、Lpush等“线程不安全”命令可以无锁执行。为什么Redis6.0引入多线程?上一段提到,Redis的瓶颈不是CPU,而是内存和网络。内存不够可以加内存或者做数据结构优化等优化,但是网络的性能优化才是大头。Redis整个执行过程中,网络IO的读写占用了大部分的CPU时间。如果网络把这部分处理做成多线程的处理方式,那么整个Redis的性能会有很大的提升。优化方向:提升网络IO性能,典型实现如使用DPDK替换内核网络栈。使用多线程充分利用多核,典型的实现如Memcached。所以总结一下,Redis之所以支持多线程,主要有两个原因:可以充分利用服务器CPU资源,目前主线程只能使用一个核。多线程任务可以分担Redis同步IO的读写负载。Redis6.0是否默认开启多线程?不行,在conf文件里配置。6个线程,线程数一定要小于机器核数,尽量不要超过8个Redis6.0多线程的实现机制?流程简述如下:主线程负责接收连接建立请求,获取Socket并放入全局等待读处理队列。主线程处理完read事件后,通过RR(RoundRobin)将这些连接分配给这些IO线程。主线程阻塞等待IO线程读完Socket。主线程以单线程的方式执行请求命令,读取并解析请求数据,但不执行。主线程阻塞等待IO线程将数据写回Socket。解除绑定并清空等待队列。这种设计有以下特点:IO线程要么在同一时间对Socket进行读或写,而不会同时读或写。IO线程只负责读写Socket解析命令,不负责命令处理。开启多线程后,会不会有线程并发安全问题?不是,Redis的多线程部分只是用来处理网络数据读写和协议解析,执行命令还是按照单线程的顺序执行。IO多路复用在Redis线程中经常被提及。你怎么理解的?这是一种IO模型,即经典的Reactor设计模式,有时也称为异步阻塞IO。多路复用是指多个Socket连接,多路复用是指多路复用一个线程。多路复用主要有三种技术:Select、Poll和Epoll。Epoll是目前最新最好的多路复用技术。使用多I/O多路复用技术,可以让单个线程高效处理多个连接请求(最大限度地减少网络IO的时间消耗),Redis在内存中操作数据的速度非常快(内存操作不会成为这里的性能瓶颈),主要以上两点使得Redis具有很高的吞吐量。暂时就这些吧,部分数据来源于网络,仅供参考。作者:南墙Kitty来源:https://www.cnblogs.com/gz666666/p/12901507.html