Redis6 新特性多线程解析

众所周知,Redis 之前的版本一直都是典型的单线程模型(注意:这里不是指 Redis 单实例中只有一个线程,而是表示 核心操作模块由单线程完成,当然另外还有一些 辅助线程 从旁协助,比如 LRU 的淘汰过程),为什么不使用多线程呢,其实原因很简单(官方解释)

Redis6 新特性多线程解析_第1张图片

简单说来就是:

  • 根据以往的场景,普通 KV 存储 瓶颈压根不在 CPU,而往往可能受到 内存 和 网络I/O 的制约
  • Redis 中有各种类型的数据操作,甚至包括一些事务处理,如果采用多线程,则会被多线程产生的切换问题而困扰,也可能因为加锁导致系统架构变的异常复杂,更有可能会因为加锁解锁甚至死锁造成的性能损耗

当然,单线程也会有 不能充分利用多核资源 弊端,这是一个权衡;而通常 Redis(包括 Redis cluster) 的性能已经足够我们使用,如果有想了解具体 Redis 如何实现如此高性能 的同学,请看 渐进式解析 Redis 源码 - 事件 ae

引入多线程

上面提到,瓶颈往往在 内存 和 网络I/O

内存方面毋容置疑,加就是了,虽然需要注意 NUMA陷阱(请自行 Google),但是也不是不能解决;

那么能不能对 网络I/O 进行进一步优化从而减少消耗呢,通常做法是: - 采用 DPDK 从内核层对网络处理流程模块进行优化(因为需要特殊支持,所以显得不那么大众) - 利用多核优势

于是 Redis 开发组的各位大佬们就想到 能不能通过 支持多线程 这一简单惠民的方式进行解决(这里也体现了大佬们对性能的极限追求),于是就有了 下面的架构(以 Read 为例):

Redis6 新特性多线程解析_第2张图片

根据上方结构简图可以看到,Redis 6 中的多线程 主要在处理 网络 I/O 方面,对网络事件进行监听,分发给 work thread 进行处理,处理完以后将主动权交还给 主线程,进行 执行操作,当然后续还会有,执行后依然交由 work thread 进行响应数据的 socket write 操作

与 Memcached 多线程模型对比

那么 Redis 6 中的 多线程模型 与 Memcached 这一及其经典的多线程网络编程案例中的模型 对比起来有哪些异同呢

首先,我们先来复习一下 Memcached 的线程机制:

Redis6 新特性多线程解析_第3张图片

Memcached 服务器采用 master-woker 模式进行工作,后再辅以 辅助线程。

服务端采用 socket 与客户端通讯,主线程、工作线程 采用 pipe管道进行通讯。

主线程采用 libevent 监听 listen、accept 的读事件,事件响应后 将连接信息的数据结构封装起来 根据算法 选择合适的工作线程,将 连接任务携带连接信息 分发出去,相应的线程利用连接描述符 建立与 客户端的socket连接 并进行后续的存取数据操作。

主线程和工作线程 处理事件流都采用状态机进行事件转移。

那么显而易见,他们的 线程模型 对比起来: - 相同点:都采用了 master-worker 这一经典思路 - 不同点:Memcached 执行主逻辑也是在 worker 线程里,模型更加简单,不过这也归功于 Memcached 简易数据操作的特性产生的天然隔离;而 Redis 把处理逻辑还 交还给 master 线程,虽然一定程度上增加了模型复杂度,但是如果把处理逻辑放在 worker 线程,也很难保证隔离性

 

你可能感兴趣的:(数据库技术,后端技术,redis6,redis,新特性,redis,多线程模型)