赞
踩
Redis 内部使用文件事件处理器 file event handler
,这个文件事件处理器是单线程的,所以 Redis 才叫做单线程的模型。它采用 IO 多路复用机制同时监听多个 Socket,根据 Socket 上的事件来选择对应的事件处理器进行处理。
多个 Socket 可能会并发产生不同的操作,每个操作对应不同的文件事件,但是 IO 多路复用程序会监听多个 socket,会将 socket 产生的事件放入队列中排队,事件分派器每次从队列中取出一个事件,把该事件交给对应的事件处理器进行处理。
除了利用IO多路复用模型外,redis还有以下几个方面可以提高效率:
多线程
Redis 一直被大家熟知的就是它的单线程架构,虽然有些命令操作可以用后台线程或子进程执行(比如数据删除、快照生成、AOF 重写),但是,从网络 IO 处理到实际的读写命令处理,都是由单个线程完成的。
随着网络硬件的性能提升,Redis 的性能瓶颈有时会出现在网络 IO 的处理上,也就是说,
单个主线程处理网络请求的速度跟不上底层网络硬件的速度。
为了解决这个问题,Redis采用多个 IO 线程来处理网络请求,提高网络请求处理的并行度。
但Redis 的多 IO 线程只是用来处理网络请求的,对于读写命令,Redis 仍然使用单线
程来处理。这是因为,Redis 处理请求时,网络处理经常是瓶颈,通过多个 IO 线程并行处
理网络操作,可以提升实例的整体处理性能。而继续使用单线程执行命令操作,就不用为
了保证 Lua 脚本、事务的原子性,额外开发多线程互斥机制了。这样一来,Redis 线程模
型实现就简单了。
在 Redis 6.0 中,主线程和 IO 线程具体是怎么协作完成请求处理的?
阶段一:服务端和客户端建立 Socket 连接,并分配处理线程
首先,主线程负责接收建立连接请求。当有客户端请求和实例建立 Socket 连接时,主线程
会创建和客户端的连接,并把 Socket 放入全局等待队列中。紧接着,主线程通过轮询方法
把 Socket 连接分配给 IO 线程。
阶段二:IO 线程读取并解析请求
主线程一旦把 Socket 分配给 IO 线程,就会进入阻塞状态,等待 IO 线程完成客户端请求
读取和解析。因为有多个 IO 线程在并行处理,所以,这个过程很快就可以完成。
阶段三:主线程执行请求操作
等到 IO 线程解析完请求,主线程还是会以单线程的方式执行这些命令操作。下面这张图显
示了刚才介绍的这三个阶段
阶段四:IO 线程回写 Socket 和主线程清空全局队列
当主线程执行完请求操作后,会把需要返回的结果写入缓冲区,然后,主线程会阻塞等待
IO 线程把这些结果回写到 Socket 中,并返回给客户端。
和 IO 线程读取和解析请求一样,IO 线程回写 Socket 时,也是有多个线程在并发执行,
所以回写 Socket 的速度也很快。等到 IO 线程回写 Socket 完毕,主线程会清空全局队
列,等待客户端的后续请求。
其他新增特性总结如下:
缓存穿透是指缓存和数据库中都没有的数据,而用户不断发起请求,造成数据库的压力倍增的情况
例:发起为id值为 -1 的数据或 id 为特别大不存在的数据
解决方案:
缓存服务器宕机或者大量缓存集中某个时间段失效,导致请求全部去到数据库,造成数据库压力倍增的情况,这个是针对多个key而言
造成缓存雪崩的原因主要有两个
针对这个原因,可以有两个解决方案:
此时有下面解决方法:
redis过期后的一瞬间,有大量用户请求同一个缓存数据,导致这些请求都去请求数据库,造成数据库压力倍增的情,针对一个key而言
缓存击穿与缓存雪崩的区别是这里针对的是某一热门key缓存,而雪崩针对的是大量缓存集中失效
解决方案
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。