Redis高性能IO模型

为什么Redis采用单线程
#0.单线程Redis主要是指Redis的网络IO和键值对读写是由一个线程来完成的,这也是Redis对外提供键值存储服务的主要流程,但Redis的其他功能,如:持久化、异步删除、集群数据等,其实是由额外的线程执行

#1.Redis为什么用单线程?
(1)使用多线程可以增加系统吞吐率,或者可以增加系统扩展性,再有合理的资源分配情况下,可以增加系统中处理请求操作的资源实体,进而提升系统能够同时处理的请求数,即吞吐率
注意:通常情况,在没有良好的系统设计情况下,刚开始增加线程数时,体统吞吐率会增加,但是再进一步增加线程时,系统吞吐率增长迟缓甚至下降

(2)瓶颈点:系统中通常会存在被多线程同时访问的共享资源,当多个资源要修改这个共享资源时,就会面临多线程编程模式面临的共享资源的并发访问控制的问题,为了保证共享资源的正确性,就需要额外的机制进行保证,就会带来额外的开销。

(3)并发访问控制,如果没有精细的设计,只是简单的采用一个粗粒度互斥锁,就会出现,即使增加了线程,大部分线程也在等待获取访问共享资源的互斥锁,并行变串行,系统的吞吐率并没有随着线程的增加而增加,而且采用多线程开发一般会引入同步原语来保护共享资源的并发访问,会降低系统代码的易调试性和可维护性,为了避免这些问题,Redis直接采用了单线程模式
单线程Redis为什么那么快
(1)Redis大部分操作在内存上完成,加上它采用了高效的数据结构,例如哈希表和跳表,这是它实现高性能的一个重要原因
(2)Redis采用了多路复用机制,使其在网络IO中能并发处理大量的客户端请求,实现高吞吐率
Reids的多路复用机制
#0.基本IO模型与阻塞点
socker网络模型的非阻塞模式设置,主要体现在三个关键的函数调用上,不同操作调用后会返回不同的套接字类型,Socket()方法会返回主动套接字,然后调用listen()方法,将主动套接字转化为监听套接字,用于监听来自客户端的链接请求,最后调用accept()方法,接收到达的客户端连接,并返回已连接的套接字

#1.基于多路复用的高性能I/O模型
Linux中的IO多路复用机制是指一个线程处理多个IO流,就是select/epoll机制
在Redis只运行单线程的情况下,该机制允许内核中,同时存在多个监听套接字和已连接套接字,内核会一直监听这些套接字上的链接请求或数据请求,一旦有请求到达,就会交给Redis处理,实现了一个Redis线程处理多个IO流的效果。

#2.Redis基于事件的回调机制
针对不同事件的发生,文件对象的被监控的事件(accept, read, write),一旦某个文件对象的监控事件被触发(读或者写或者请求就绪),满足条件,这个事件就会被放到事件队列进行处理,处理的过程就是调用对应的回调函数,redis无需一直轮询是否有请求实际发生,这就可以避免造成CPU资源浪费,同时Redis在对事件队列中的事件进行处理时,会调用相应的处理函数,这就实现了基于事件的回调,因为Redis一直对事件队列进行处理,所以能及时相应客户端请求,提升Redis的响应性能
小结
#0.redis单线程是指它对网络IO和数据读写的操作采用了一个线程,而采用单线程的一个核心原因是避免多线程开发的并发控制问题,单线程的Redis也能获得高性能,跟多路复用的IO模型密切相关,因为这避免了accpet()和send()/recv()潜在的网络IO操作阻塞点。


#1.redis单线程处理IO请求性能瓶颈主要包含两个方面:
#问题(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性能,当然,只是针对客户端的读写是并行的,每个命令的真正操作依然是单线程的


#问题3
Redis基本IO模型中海油哪些潜在的性能瓶颈
在Redis基本IO模型中,主要是主线程在执行操作,任何耗时的操作,例如bigkey,全量返回等操作,都是潜在的性能瓶颈
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值