当前位置: 首页 > news >正文

01_Redis单线程与多线程

01——Redis单线程与多线程

一、Redis是单线程还是多线程

在谈Redis的单线程或多线程时,需要根据版本来区分。

  1. 在redis 3.x之前,redis是单线程的
  2. 从redis 4.x开始,redis引入多线程。处理客户端请求时,使用单线程;在异步删除等操作时,使用多线程
  3. 在2020年发布的6.x以及2022年发布的7.x版本,使用全新的多线程来解决问题。

Redis重要里程碑:

  1. Redis 2.6 支持lua脚本
  2. Redis 3.0 支持集群
  3. Redis 4.0 混合持久化、多线程异步删除
  4. Redis 5.0 核心代码重构
  5. Redis 6.0 多线程IO

image-20230305184649796

二、Redis为什么选择单线程

Redis单线程

定义:主要是指Redis的网络IO和键值对读写是由一个线程来完成的,Redis在处理客户端的请求时(包括获取(Socket读)、解析、执行、内容返回(Socket写)),都是由一个顺序串的主线程处理,这就是所谓的“单线程”。这也是Redis对外提供键值存储服务的主要流程。

image-20230305185732100

但是Redis的其他功能,比如持久化RBD、AOF、异步删除、集群数据同步等,其实是由额外的线程执行的。

Redis命令工作线程是单线程的,但是,对整个Redis来说,是多线程的。

Redis在3.x版本时,性能依旧很快的主要原因:

  1. 基于内存操作: Redis的所有数据都存在内存中,因此所有的运算都是内存级别的
  2. 数据结构简单: Redis的数据结构是专门设计的,而这些简单的数据结构的查找和操作时间复杂度都是O(1)
  3. 多路复用和非阻塞IO: Redis使用IO多路复用功能来监听多个socket连接客户端,这样就可以使用一个线程连接来处理多个请求,减少线程切换带来的开销,同时也避免了IO阻塞操作
  4. 避免上下文切换: 因为是单线程模型,因此就避免了不必要的线程上下文切换和多线程竞争,省去了多线程切换带来的时间和性能上的消耗

在多CPU时代,Redis如何使用多个CPU?

官网:Redis是基于内存操作的,因此Redis的瓶颈可能是机器的内存或网络带宽而非CPU。既然CPU不是瓶颈,那么自然采用单线程。但是在Redis4.0中开始支持多线程了,例如:后台删除、备份等功能。

三、为什么Redis加入了多线程特性

单线程的痛点: 正常情况下,使用del删除数据很快,但是删除一个非常大的key,则会导致Redis主线程卡顿。

解决方案:使用惰性删除,把删除数据的工作交给后台的其他线程来完成。

  1. unlink key
  2. flushdb async
  3. flushall async

本质上来说,就是将耗时的操作从主线程剥离,交给BIO子线程来处理,减少主线程阻塞时间,从而减少因为耗时操作导致的性能和稳定性问题。

四、Redis多线程特性和IO多路复用

Redis性能影响因素:

  1. CPU,官网文档说明,CPU不大可能是Redis的性能瓶颈
  2. 内存,在当下的开发环境中,内存越来越便宜,因此内存也不性能瓶颈
  3. 网络IO:因为Redis从网络IO处理到实际的读写命令处理,都是由单个线程完成的,所以网络IO可能会成为Redis的性能瓶颈。

单个线程处理网络请求的速度,有可能跟不上底层网络硬件的速度。为了应对这个问题,Redis6、7采用多个IO线程来处理网络请求,提高网络请求处理的并行度。

Redis只是使用多线程来处理网络IO操作,此操作可以提升实例的整体处理性能。执行命令操作还是单线程,这就不用开发多线程的互斥枷锁机制。因此,Redis线程模型的实现就很简单。

主线程和IO线程是怎么协作完成请求处理的:

  1. 阶段一:服务端和客户端建立Socket连接,并分配处理线程

    首先,主线程负责接收建立连接的请求。当有客户端请求和实例建立Socket连接时,主线程会创建和客户端的连接,并把Socket放入全局等待队列中。紧接着,主线程通过轮训方法把Socket连接分配给IO线程。

  2. 阶段二:IO线程读取并解析请求

    主线程一旦把Socket分配给IO线程,就会进入阻塞状态,等待IO线程完成客户端请求(读取和解析)。因为有多个IO线程在并行处理,所以,这个过程很快就可以完成。

  3. 阶段三:主线程执行请求操作

    等到IO线程解析完请求,主线程还是会以单线程的方式执行这些命令操作。

  4. IO线程回写Socket和主线程清空全局队列

    当主线程执行完请求操作后,会把需要返回的结果写入缓冲区。然后,主线程阻塞等待,IO线程把结果写回到Socket中,并返回给客户端。和IO线程读取解析一样,IO线程回写Socket时,也是多个线程并发执行,所以速度很快。等到IO线程回写Socket完毕,主线程会清空全局队列,等待客户端的后续请求。

image-20230305200247468

image-20230305200405160

Unix网络编程中的五种IO模型:

  1. Blocking IO:阻塞IO

  2. NoneBlocking IO:非阻塞IO

  3. IO multiplexing:IO多路复用

    1. Linux世界:一切皆文件

      文件描述符,简称FD、句柄

      image-20230305201118910

    2. IO多路复用是什么

      一种同步的IO模型,实现一个线程监视多个文件句柄,一旦某个文件句柄就绪,就能通知到对应的应用程序进行相应的读写操作,没有文件句柄就绪时,就会阻塞应用程序,从而释放CPU资源。

      1. IO:网络IO,在操作系统层面,指数据在内核态和用户态之间的读写操作
      2. 多路:多个客户端连接(连接就是套接字描述符,即socket或者channel)
      3. 复用:复用一个或几个线程
      4. IO多路复用:也就是说一个或一组线程处理多个TCP连接,使用单进程就能够实现同时处理多个客户端的连接,无需创建或者维护过多的进程、线程
      5. 实现IO多路复用的模型有三种:select、poll、epoll
    3. epoll

      image-20230305202006354

      image-20230305202219213

    4. 总结

      image-20230305202318018

    5. Redis问什么这么快

      IO多路复用+epoll函数,才是redis为什么这么快的直接原因,而不是单线程命令+redis安装在内存中。

      image-20230305202714218

      image-20230305202849547

      image-20230305202930956

  4. signal driven IO:信号驱动IO

  5. asynchronous IO:异步IO

五、Redis7是否默认开启多线程

如果在实际应用中,发现redis CPU开销不大但吞吐量却没有提升,可以考虑使用redis7的多线程机制,加速网络处理,进而提升实例的吞吐量。

Redis7讲所有的数据放在内存中,内存的响应时长大约是100纳秒,对于小的数据包,Redis服务器可以处理8w到10w的QPS,这也是Redis处理的极限,对于大多数业务来说,单线程Redis已经足够使用了。

在redis6、7中,多线程机制默认是关闭的,如果需要使用redis多线程功能,需要修改redis.conf配置文件:

# 启用多线程
io-thread-do-reads yes
# 设置线程个数。官方建议:4核cpu,线程数设置为2或3;8核cpu,设置为6。线程数一定要小于机器核数,线程数并不是越大越好
io-threads 6

六、总结

image-20230305221648688

相关文章:

01_Redis单线程与多线程

01——Redis单线程与多线程 一、Redis是单线程还是多线程 在谈Redis的单线程或多线程时,需要根据版本来区分。 在redis 3.x之前,redis是单线程的从redis 4.x开始,redis引入多线程。处理客户端请求时,使用单线程;在异…...

机器学习——随机森林【手动代码】

随机森林这个内容,是目前来说。。。最最最简单,最好理解,应该也是最好实现的了!!! 先挖坑,慢慢填 随机森林,这个名字取得,果然深得该算法的核心精髓,既随机&a…...

Vue 2 处理边界情况

访问元素和组件 通过Vue 2 组件基础一文的学习,我们知道组件之间可以通过传递props或事件来进行通信。 但在一些情况下,我们使用下面的方法将更有用。 1.访问根实例 根实例可通过this.$root获取。 我们在所有子组件中都可以像上面那样访问根实例&…...

写一个mysql 正则表达式,每三个img标签图片后面添加<hr>

你可以使用MySQL的REGEXP_REPLACE函数来实现这个需求。下面是一个示例的正则表达式和SQL语句&#xff1a; sql UPDATE your_table SET your_column REGEXP_REPLACE(your_column, (<img[^>]*>){3}, $0<hr>) WHERE your_column REGEXP (<img[^>]*>){3}…...

Spring MVC异常处理

Spring MVC异常处理 Spring MVC异常处理机制HandlerExceptionResolver的实现类DefaultHandlerExceptionResolver实现类DefaultHandlerExceptionResolver 在Controller的请求处理方法中手动使用try…catch块捕捉异常&#xff0c;当捕捉到指定的异常时&#xff0c;系统返回对应的…...

Centos7安装docker后默认开启docker0的网卡|卸载默认网卡

docker实战(一):centos7 yum安装docker docker实战(二):基础命令篇 docker实战(三):docker网络模式(超详细) docker实战(四):docker架构原理 docker实战(五):docker镜像及仓库配置 docker实战(六):docker 网络及数据卷设置 docker实战(七):docker 性质及版本选择 认知升…...

04_Redis与mysql数据双写一致性案例

04——redis与mysql数据双写一致性 一、canal 是什么 canal[ka’nel,中文翻译为水道/管道/沟渠/运河&#xff0c;主要用途是用于MySQL数据库增量日志数据的订阅、消费和解析&#xff0c;是阿里巴巴开发并开源的,采用Java语言开发&#xff1b; 历史背景是早期阿里巴巴因为杭州和…...

vue的开发者工具下载『保姆级别』

1.先进官网 极简插件_Chrome扩展插件商店_优质crx应用下载 (zzzmh.cn) 2.搜索vue devtools&#xff0c;点击进去 3.下载插件 4.下载到文件下你自己的文件下&#xff1a;我的是下载到E盘下。 5.压缩到当前目录下 6.电脑进入拓展程序&#xff08;不同的浏览器操作不同&#xff…...

vue的scrollTop手机环境设置值失效,本地正常可以赋值

获取div盒子ref或者document获取都行 监听方法 一定要加this.$nexttick,在本地测试只用nexttick是没有问题的&#xff0c;但是到手机测试就不行了&#xff0c;原因是因为手机渲染比本地更快&#xff0c;所以结合setTimeout使用 如果有更好的处理方法&#xff0c;恳请大佬指点一…...

[前端系列第7弹]Vue:一个渐进式的 JavaScript 框架

Vue 是一个用于构建用户界面的 JavaScript 框架&#xff0c;它具有以下特点&#xff1a; 渐进式&#xff1a;Vue 可以根据不同的使用场景&#xff0c;灵活地选择使用库或者框架的方式&#xff0c;从而实现渐进式的开发。响应式&#xff1a;Vue 通过数据绑定和虚拟 DOM 技术&am…...

C#键盘按键对应Keys类大全

...

SpringBoot 学习(03): 弱语言的注解和SpringBoot注解的异同

弱语言代表&#xff1a;Hyperf&#xff0c;一个基于 PHP Swoole 扩展的常驻内存框架 注解概念的举例说明&#xff1b; 说白了就是&#xff0c;你当领导&#xff0c;破烂事让秘书帮你去安排&#xff0c;你只需要批注一下&#xff0c;例如下周要举办一场活动&#xff0c;秘书将方…...

CloudQuery:更好地管理你的 OceanBase 数据库

前言&#xff1a;作为 OceanBase 的生态合作伙伴&#xff0c;CloudQuery&#xff08;简称“CQ”&#xff09; 最新发布的社区版 2.2.0 新增了 OceanBase 数据库&#xff0c;为企业使用 OceanBase 数据库提供全面的支持。包括连接与认证、查询与分析、数据安全与权限管理&#x…...

php的password_verify 和 password_hash密码验证

password_hash() 使用足够强度的单向散列算法创建密码的散列(hash)。 当前支持的算法&#xff1a; PASSWORD_DEFAULT - 使用 bcrypt 算法 (PHP 5.5.0 默认)。 注意&#xff0c;该常量会随着 PHP 加入更新更高强度的算法而改变。 所以&#xff0c;使用此常量生成结果的长度将在未…...

JAVA免杀学习与实验

1 认识Webshell 创建一个JSP文件&#xff1a; <% page import"java.io.InputStream" %> <% page import"java.io.BufferedReader" %> <% page import"java.io.InputStreamReader" %> <% page language"java" p…...

Apche Kafka + Spring的消息监听容器

目录 一、消息的接收1.1、消息监听器 二、消息监听容器2.1、 实现方法2.1.1、KafkaMessageListenerContainer2.1.1.1、 基本概念2.1.1.2、如何使用 KafkaMessageListenerContainer 2.1.2、ConcurrentMessageListenerContainer 三、偏移 四、监听器容器自动启动 一、消息的接收 …...

[JavaWeb]【五】web后端开发-Tomcat SpringBoot解析

目录 一 介绍Tomcat 二 基本使用 2.1 解压绿色版 2.2 启动TOMCAT 2.3 关闭TOMCAT 2.4 常见问题 2.5 修改端口号 2.6 部署应用程序 三 SpringBootWeb入门程序解析 前言&#xff1a;tomcat与SpringBoot解析 一 介绍Tomcat 二 基本使用 2.1 解压绿色版 2.2 启动TOMCAT 2…...

css 用过渡实现,鼠标离开li时,背景色缓慢消息的样式

要实现鼠标悬停时背景颜色变为黄色&#xff0c;鼠标离开时背景颜色慢慢消失并变回白色的效果&#xff0c; 可以使用CSS的过渡&#xff08;transition&#xff09;属性 li {background: #fff;color: #000;transition: background 0.5s ease-out; }li:hover {background: #fbb31…...

pytorch 线性层Linear详解

线性层就是全连接层&#xff0c;以一个输入特征数为2&#xff0c;输出特征数为3的线性层为例&#xff0c;其网络结构如下图所示&#xff1a; 输入输出数据的关系如下&#xff1a; 写成矩阵的形式就是&#xff1a; 下面通过代码进行验证&#xff1a; import torch.nn as nn …...

LeetCode 833. 字符串中的查找与替换

2235. 两整数相加 添加链接描述 给你两个整数 num1 和 num2&#xff0c;返回这两个整数的和。 示例 1&#xff1a; 输入&#xff1a;num1 12, num2 5 输出&#xff1a;17 解释&#xff1a;num1 是 12&#xff0c;num2 是 5 &#xff0c;它们的和是 12 5 17 &#xff0c;…...

React19源码系列之 事件插件系统

事件类别 事件类型 定义 文档 Event Event 接口表示在 EventTarget 上出现的事件。 Event - Web API | MDN UIEvent UIEvent 接口表示简单的用户界面事件。 UIEvent - Web API | MDN KeyboardEvent KeyboardEvent 对象描述了用户与键盘的交互。 KeyboardEvent - Web…...

大数据学习(132)-HIve数据分析

​​​​&#x1f34b;&#x1f34b;大数据学习&#x1f34b;&#x1f34b; &#x1f525;系列专栏&#xff1a; &#x1f451;哲学语录: 用力所能及&#xff0c;改变世界。 &#x1f496;如果觉得博主的文章还不错的话&#xff0c;请点赞&#x1f44d;收藏⭐️留言&#x1f4…...

Java求职者面试指南:计算机基础与源码原理深度解析

Java求职者面试指南&#xff1a;计算机基础与源码原理深度解析 第一轮提问&#xff1a;基础概念问题 1. 请解释什么是进程和线程的区别&#xff1f; 面试官&#xff1a;进程是程序的一次执行过程&#xff0c;是系统进行资源分配和调度的基本单位&#xff1b;而线程是进程中的…...

scikit-learn机器学习

# 同时添加如下代码, 这样每次环境(kernel)启动的时候只要运行下方代码即可: # Also add the following code, # so that every time the environment (kernel) starts, # just run the following code: import sys sys.path.append(/home/aistudio/external-libraries)机…...

Golang——6、指针和结构体

指针和结构体 1、指针1.1、指针地址和指针类型1.2、指针取值1.3、new和make 2、结构体2.1、type关键字的使用2.2、结构体的定义和初始化2.3、结构体方法和接收者2.4、给任意类型添加方法2.5、结构体的匿名字段2.6、嵌套结构体2.7、嵌套匿名结构体2.8、结构体的继承 3、结构体与…...

C语言中提供的第三方库之哈希表实现

一. 简介 前面一篇文章简单学习了C语言中第三方库&#xff08;uthash库&#xff09;提供对哈希表的操作&#xff0c;文章如下&#xff1a; C语言中提供的第三方库uthash常用接口-CSDN博客 本文简单学习一下第三方库 uthash库对哈希表的操作。 二. uthash库哈希表操作示例 u…...

es6+和css3新增的特性有哪些

一&#xff1a;ECMAScript 新特性&#xff08;ES6&#xff09; ES6 (2015) - 革命性更新 1&#xff0c;记住的方法&#xff0c;从一个方法里面用到了哪些技术 1&#xff0c;let /const块级作用域声明2&#xff0c;**默认参数**&#xff1a;函数参数可以设置默认值。3&#x…...

表单设计器拖拽对象时添加属性

背景&#xff1a;因为项目需要。自写设计器。遇到的坑在此记录 使用的拖拽组件时vuedraggable。下面放上局部示例截图。 坑1。draggable标签在拖拽时可以获取到被拖拽的对象属性定义 要使用 :clone, 而不是clone。我想应该是因为draggable标签比较特。另外在使用**:clone时要将…...

MLP实战二:MLP 实现图像数字多分类

任务 实战&#xff08;二&#xff09;&#xff1a;MLP 实现图像多分类 基于 mnist 数据集&#xff0c;建立 mlp 模型&#xff0c;实现 0-9 数字的十分类 task: 1、实现 mnist 数据载入&#xff0c;可视化图形数字&#xff1b; 2、完成数据预处理&#xff1a;图像数据维度转换与…...

项目研究:使用 LangGraph 构建智能客服代理

概述 本教程展示了如何使用 LangGraph 构建一个智能客服代理。LangGraph 是一个强大的工具&#xff0c;可用于构建复杂的语言模型工作流。该代理可以自动分类用户问题、分析情绪&#xff0c;并根据需要生成回应或升级处理。 背景动机 在当今节奏飞快的商业环境中&#xff0c…...