Redis 官方在 2020 年 5 月正式推出 6.0 版本,提供很多振奋人心的新特性,所以备受关注。

主要特性如下:

  1. 多线程处理网络 IO;
  2. 客户端缓存;
  3. 细粒度权限控制(ACL);
  4. RESP3 协议的使用;
  5. 用于复制的 RDB 文件不在有用,将立刻被删除;
  6. RDB 文件加载速度更快;

其中备受关注的就是「多线程模型 + 客户端缓存」,我们只有掌握了新特性原理,才能判断什么时候使用 6.0 版本,如何用的更好更快,不踩坑。

本篇先从 Redis 多线程模型开始,至于客户端缓存、等且听下回分解。

Redis 6.0 之前为什么不使用多线程?

官方答复:

  • 使用 Redis 时,几乎不存在 CPU 成为瓶颈的情况, Redis 主要受限于内存和网络。

  • 在一个普通的 Linux 系统上,Redis 通过使用pipelining 每秒可以处理 100 万个请求,所以如果应用程序主要使用 O(N) 或O(log(N)) 的命令,它几乎不会占用太多 CPU。

  • 使用了单线程后,可维护性高。多线程模型虽然在某些方面表现优异,但是它却引入了程序执行顺序的不确定性,带来了并发读写的一系列问题,增加了系统复杂度、同时可能存在线程切换、甚至加锁解锁、死锁造成的性能损耗。

Redis 通过 AE 事件模型以及 IO 多路复用等技术,处理性能非常高,因此没有必要使用多线程。

单线程机制让 Redis 内部实现的复杂度大大降低,Hash 的惰性 Rehash、Lpush 等等『线程不安全』的命令都可以无锁进行

Redis 6.0 之前单线程指的是 Redis 只有一个线程干活么?

非也,Redis 在处理客户端的请求时,包括获取 (socket 读)、解析、执行、内容返回 (socket 写) 等都由一个顺序串行的主线程处理,这就是所谓的「单线程」

其中执行命令阶段,由于 Redis 是单线程来处理命令的,所有每一条到达服务端的命令不会立刻执行,所有的命令都会进入一个 Socket 队列中,当 socket 可读则交给单线程事件分发器逐个被执行。

此外,有些命令操作可以用后台线程或子进程执行(比如数据删除、快照生成、AOF 重写)。

❝Redis 6.0 为啥要引入多线程呀?

随着硬件性能提升,Redis 的性能瓶颈可能出现网络 IO 的读写,也就是:单个线程处理网络读写的速度跟不上底层网络硬件的速度

读写网络的 read/write 系统调用占用了Redis 执行期间大部分CPU 时间,瓶颈主要在于网络的 IO 消耗, 优化主要有两个方向:

  • 提高网络 IO 性能,典型的实现比如使用 DPDK来替代内核网络栈的方式。
  • 使用多线程充分利用多核,提高网络请求读写的并行度,典型的实现比如 Memcached

添加对用户态网络协议栈的支持,需要修改 Redis 源码中和网络相关的部分(例如修改所有的网络收发请求函数),这会带来很多开发工作量。

而且新增代码还可能引入新 Bug,导致系统不稳定。

所以,Redis 采用多个 IO 线程来处理网络请求,提高网络请求处理的并行度。

需要注意的是,Redis 多 IO 线程模型只用来处理网络读写请求,对于 Redis 的读写命令,依然是单线程处理

这是因为,网络处理经常是瓶颈,通过多线程并行处理可提高性能。

而继续使用单线程执行读写命令,不需要为了保证 Lua 脚本、事务、等开发多线程安全机制,实现更简单。

架构图如下

❝主线程与 IO 多线程是如何实现协作呢?

如下图:

Redis多线程与IO线程

主要流程

  1. 主线程负责接收建立连接请求,获取 socket 放入全局等待读处理队列;
  2. 主线程通过轮询将可读 socket 分配给 IO 线程;
  3. 主线程阻塞等待 IO 线程读取 socket 完成;
  4. 主线程执行 IO 线程读取和解析出来的 Redis 请求命令;
  5. 主线程阻塞等待 IO 线程将指令执行结果回写回 socket完毕;
  6. 主线程清空全局队列,等待客户端后续的请求。

思路:将主线程 IO 读写任务拆分出来给一组独立的线程处理,使得多个 socket 读写可以并行化,但是 Redis 命令还是主线程串行执行。

❝如何开启多线程呢?

Redis 6.0 的多线程默认是禁用的,只使用主线程。如需开启需要修改 redis.conf 配置文件:io-threads-do-reads yes

❝线程数是不是越多越好?

当然不是,关于线程数的设置,官方有一个建议:4 核的机器建议设置为 2 或 3 个线程,8核的建议设置为 6 个线程,线程数一定要小于机器核数。

线程数并不是越大越好,官方认为超过了 8 个基本就没什么意义了。

另外,开启多线程后,还需要设置线程数,否则是不生效的

io-threads 4

总结与思考

随着互联网的飞速发展,互联网业务系统所要处理的线上流量越来越大,Redis 的单线程模式会导致系统消耗很多 CPU 时间在网络 I/O 上从而降低吞吐量,要提升 Redis 的性能有两个方向:

  • 优化网络 I/O 模块
  • 提高机器内存读写的速度

后者依赖于硬件的发展,暂时无解。所以只能从前者下手,网络 I/O 的优化又可以分为两个方向:

  • 零拷贝技术或者 DPDK 技术
  • 利用多核优势

模型缺陷

Redis 的多线程网络模型实际上并不是一个标准的 Multi-Reactors/Master-Workers模型。

Redis 的多线程方案中,I/O 线程任务仅仅是通过 socket 读取客户端请求命令并解析,却没有真正去执行命令。

所有客户端命令最后还需要回到主线程去执行,因此对多核的利用率并不算高,而且每次主线程都必须在分配完任务之后忙轮询等待所有 I/O 线程完成任务之后才能继续执行其他逻辑。

Redis 目前的多线程方案更像是一个折中的选择:既保持了原系统的兼容性,又能利用多核提升 I/O 性能。

Redis 新特性:多线程模型解读的更多相关文章

  1. Redis 6.0 新特性-多线程连环13问!

    Redis 6.0 来了 在全国一片祥和IT民工欢度五一节假日的时候,Redis 6.0不声不响地于5 月 2 日正式发布了,吓得我赶紧从床上爬起来,学无止境!学无止境! 对于6.0版本,Redis之 ...

  2. redis新特性

    摘自<redis 4.xcookbook> 从实例重启同步] 故障切换同步] 4.0之前从实例主键过期bug redis4新特性 Memory Command Lazy Free PSYN ...

  3. HTML5新特性-多线程(Worker SharedWorker)

    There is no doubt that JavaScript是没有多线程之说的,他只能一件事一件事的做,做完一件事再做下一件事,假如你的js要花一段比较长的时间做一件事的话,那么浏览器将会卡顿一 ...

  4. Redis 新特性---pipeline(管道)

    转载自http://weipengfei.blog.51cto.com/1511707/1215042 Redis本身是一个cs模式的tcp server, client可以通过一个socket连续发 ...

  5. Redis 6.0 新特性:带你 100% 掌握多线程模型

    Redis 官方在 2020 年 5 月正式推出 6.0 版本,提供很多振奋人心的新特性,所以备受关注. 码老湿,提供了啥特性呀?知道了我能加薪么? 主要特性如下: 多线程处理网络 IO: 客户端缓存 ...

  6. [翻译] C# 8.0 新特性 Redis基本使用及百亿数据量中的使用技巧分享(附视频地址及观看指南) 【由浅至深】redis 实现发布订阅的几种方式 .NET Core开发者的福音之玩转Redis的又一傻瓜式神器推荐

    [翻译] C# 8.0 新特性 2018-11-13 17:04 by Rwing, 1179 阅读, 24 评论, 收藏, 编辑 原文: Building C# 8.0[译注:原文主标题如此,但内容 ...

  7. 微软架构师解读Windows Server 2008 R2新特性

    目前众多企业都开始为自己寻找一个更加适合自身发展的服务器操作平台.微软的Windows Server 2008 R2就是可以为大家解决服务器平台问题.微软最新的服务器平台Windows Server ...

  8. 【redis】redis5.0的一些新特性

    redis5.0总共增加了12项新特性,如下: 1.新增加的Stream(流)数据类型,这样redis就有了6大数据类型,另外五种是String(字符串),Hash(哈希),List(列表),Set( ...

  9. Spring Boot 2.0正式发布,新特性解读

    作者|翟永超 Spring Boot 2.0 来啦,有哪些新特性?升级吗? 写在前面 北京时间 3 月 1 日,经过漫长的等待之后,Spring Boot 2.0 正式发布.作为 Spring 生态中 ...

随机推荐

  1. android TextView属性详解

    RelativeLayout用到的一些重要的属性: 第一类:属性值为true或false     android:layout_centerHrizontal  水平居中      android:l ...

  2. Linux基础入门笔记

    今天带来Linux入门的一些基础的笔记,科班出身的同学们,Linux已经成为了必修课了,下面我带来关于Linux的相关入门知识以及Linux简单的介绍! Linux内核最初只是由芬兰人林纳斯·托瓦兹( ...

  3. 4、Linux基础--系统目录

    笔记 1.晨考 1.移动文件的命令 mv 2.删除文件的命令及其参数 rm 参数: -r : 递归删除 -f : 不提示删除 -i : 提示删除 3.复制文件的命令及其参数 cp 参数: -r : 递 ...

  4. Solution -「Gym 102798K」Tree Tweaking

    \(\mathcal{Description}\)   Link.   给定排列 \(\{p_n\}\),求任意重排 \(p_{l..r}\) 的元素后,将 \(\{p_n\}\) 依次插入二叉搜索树 ...

  5. Solution -「多校联训」查拉图斯特拉如是说

    \(\mathcal{Description}\)   Link.   给定 \(n\) 和 \(m\) 次多项式 \(f(x)\),求 \[\sum_{i=0}^n\binom{n}{i}f(i)\ ...

  6. Solution -「UOJ #87」mx 的仙人掌

    \(\mathcal{Description}\)   Link.   给出含 \(n\) 个结点 \(m\) 条边的仙人掌图.\(q\) 次询问,每次询问给出一个点集 \(S\),求 \(S\) 内 ...

  7. 让数据可视化变得简单 – JavaScript 图形库

    作者 | 董叶 公司决策层会围绕着数据来制定相应的策略,数据的重要性与日俱增,政府.金融机构.互联网大厂正在以前所未有的速度收集数据,面对扑面而来的数据,没有抽象.视觉层的帮助,我们很难快速理解掌握其 ...

  8. Python面向对象之 - 继承

    情况一:  子类完全继承父类所有的属性和方法, 自己没有一点更改. class Person(): def __init__(self, name, age): self.name = name se ...

  9. 关于WebStorm-React-Native 代码提示安装方法

    声明 本方法 为网上好心人提供  我提供整理 插件名称:Webstrom live template 安装方法一:1.打开终端输入 git clone https://github.com/virto ...

  10. 快速搭建一套k8s集群环境

    参考官网 kubeadm是官方提供的快速搭建k8s集群的开源工具,对于非运维人员学习k8s,kubeadm方式安装相对更简单. kubeadm创建一个集群:https://kubernetes.io/ ...