Redis6.0多线程的疑惑解答

2024-03-21 01:52

本文主要是介绍Redis6.0多线程的疑惑解答,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1.Redis6.0之前的版本真的是单线程吗?

Redis在处理客户端的请求是,包括获取(socket读)、解析、执行、内容返回(socket 写)等都有一个
顺序串行的主线程处理,这就是所谓的"单线程"。但如果严格来讲并不是单线程,除了主线程外,它
也有后台线程在处理一些较为缓慢的操作,例如清理脏数据、无用连接的释放、大key的删除等等

2.Redis6.0之前为什么一直不使用多线程?

官方曾做过类似问题的回复:使用Redis时,几乎不存在CPU成为瓶颈的情况,Redis主要受限于内存和网络。例如在一个普通的Linux系统上,Redis通过使用pipelining每秒可以处理100w个请求,所以如果
应用程序主要使用O(N)或O(log(N))的命令,它几乎不会占用太多CPU.
使用了单线程后,可维护性高。多线程模型虽然在某些方面表现优异,但是它却引入了程序执行顺序的不确定性,带来了并发读写的一系列问题,增加了系统复杂度、同事还可能存在线程切换、甚至加锁解锁、
死锁造成的性能损耗。Redis通过AE事件模型以及IO多路复用等技术,处理性能非常高,因此没有必要使用多线程。单线程机制使得Redis内部实现的复杂度大大降低,Hash的惰性、Rehash、Lpush等等"线程不安全"
的命令都可以无锁进行

3.Redis6.0为什么要引入多线程呢?

Redis将所有数据放在内存中,内存的响应时长大约为100纳秒,对于小数据包,Redis服务器可以处理8w~10w QPS,这也是Redis处理的极限了,对于80%的公司来说,单线程的Redis已经足够使用了。但随着越来越复杂的业务场景,有些公司动不动就上亿的交易量,因此需要更大的QPS。常见的解决方案是在分布式架构中对数据进行分区并采用多个服务器,
但该方案有非常大的缺点,例如要管理的Redis服务器太多,维护代价大;某些适用于单个Redis服务器的命令不适用于数据
分区;数据分区无法解决热点读/写问题;数据倾斜,重新分配和放大/缩小变得更加复杂等等。

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

  • 1.提高网络IO性能,典型的实现比如使用DPDK来替代内核网络栈的方式
  • 2.使用多线程充分利用多核,典型的实现比如Memcached协议栈优化的这种方式跟Redis关系不大,支持多线程是一种最有效最便捷的操作方式,所以总结起来,Redis支持多线程就是两个原因:
  • 1.可以充分利用服务器的CPU资源,,目前主线程只能利用一个核
  • 2.多线程任务可以分摊Redis同步IO读写负荷

4.Redis6.0默认是否开启了多线程?

Redis6.0的多线程默认是禁用的,只使用主线程。如需开启需要修改redis.conf配置文件

io-threads 4io-threads-do-reads no

开启多线程后,还需要设置线程数,否则是不生效的。关于线程数的设置,官方有一个建议:
4核的机器建议设置为2或3个线程,
8核的建议设置6个线程,线程数一定要小于机器核数,因为Redis还有预留出其他线程做后台任务
比如备份、删除过期键等操作,还需要注意的是,线程数并不是越大越好,官方认为超过了8个基本就没什么意义了,因为主线程命令执行会存在一个瓶颈点,如果达到瓶颈,即便IO线程设置得再多,也是空转

5.Redis6.0采用多线程后,性能的提升效果如何?

Redis作者antirez在RedisConf2019分享时曾提到:Redis6引入的多线程IO特性对性能提升
至少是一倍以上。国内也有大牛曾使用unstable版本在阿里云ESC进行过测试,GET/SET命令
在4线程IO时性能相比单线程是几乎翻倍了。如果开启多线程,至少要4核的机器,且Redis实例
已经占用相当大的CPU的耗时的时候才建议使用,否则使用多线程没有意义

6.Redis60多线程的实现机制?

在这里插入图片描述

流程简述:

  • 1.主线程负责接收建立连接请求,获取socket放入全局等待读处理队列
  • 2.主线程处理完读事件之后,通过RR(Round Robin)将这些连接分配给这些IO线程
  • 3.主线程阻塞等待IO线程读取socket完毕
  • 4.主线程通过单线程的方式执行请求命令,请求数据读取并解析完成,但并不执行回写socket
  • 5.主线程阻塞等待IO线程将数据回写socket完毕
  • 6.解除绑定,清空等待队列

该设计有如下特定:

  • 1.IO线程要么同时在读socket,要么同时在写,不会同时读或写
  • 2.IO线程只负责读写socket解析命令,不负责命令处理

7.开启多线程后,是否会存在线程并发安全问题?

Redis的多线程部分只是用来处理网络数据的读写和协议解析,执行命令仍然是单线程顺序执行。
所以我们不需要去考虑控制key、lua、事务,LPUSH/LPOP等等的并发及线程安全问题

8.Redis6.0的多线程和Memcached多线程模型进行对比

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

  • 相同点:都采用了master线程-worket线程的模型
  • 不同点:Memcached执行主逻辑也是在worker线程里,模型更加简单,实现了真正的线程隔离,符合我们对线程隔离的常规理解。而Redis吧处理逻辑交还给master线程,虽然一定程度上增加了模型复杂度,但也解决了线程并发安全等问题

这篇关于Redis6.0多线程的疑惑解答的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/831436

相关文章

多线程解析报表

假如有这样一个需求,当我们需要解析一个Excel里多个sheet的数据时,可以考虑使用多线程,每个线程解析一个sheet里的数据,等到所有的sheet都解析完之后,程序需要提示解析完成。 Way1 join import java.time.LocalTime;public class Main {public static void main(String[] args) thro

Java 多线程概述

多线程技术概述   1.线程与进程 进程:内存中运行的应用程序,每个进程都拥有一个独立的内存空间。线程:是进程中的一个执行路径,共享一个内存空间,线程之间可以自由切换、并发执行,一个进程最少有一个线程,线程实际数是在进程基础之上的进一步划分,一个进程启动之后,进程之中的若干执行路径又可以划分成若干个线程 2.线程的调度 分时调度:所有线程轮流使用CPU的使用权,平均分配时间抢占式调度

Java 多线程的基本方式

Java 多线程的基本方式 基础实现两种方式: 通过实现Callable 接口方式(可得到返回值):

JAVA- 多线程

一,多线程的概念 1.并行与并发 并行:多个任务在同一时刻在cpu 上同时执行并发:多个任务在同一时刻在cpu 上交替执行 2.进程与线程 进程:就是操作系统中正在运行的一个应用程序。所以进程也就是“正在进行的程序”。(Windows系统中,我们可以在任务管理器中看 到进程) 线程:是程序运行的基本执行单元。当操作系统执行一个程序时, 会在系统中建立一个进程,该进程必须至少建立一个线

多线程篇(阻塞队列- LinkedBlockingDeque)(持续更新迭代)

目录 一、LinkedBlockingDeque是什么 二、核心属性详解 三、核心方法详解 addFirst(E e) offerFirst(E e) putFirst(E e) removeFirst() pollFirst() takeFirst() 其他 四、总结 一、LinkedBlockingDeque是什么 首先queue是一种数据结构,一个集合中

多线程篇(阻塞队列- LinkedBlockingQueue)(持续更新迭代)

目录 一、基本概要 1. 构造函数 2. 内部成员 二、非阻塞式添加元素:add、offer方法原理 offer的实现 enqueue入队操作 signalNotEmpty唤醒 删除线程(如消费者线程) 为什么要判断if (c == 0)时才去唤醒消费线程呢? 三、阻塞式添加元素:put 方法原理 图解:put线程的阻塞过程 四、非阻塞式移除:poll方法原理 dequ

spring笔记 多线程的支持

spring的工作机制 136  属性编辑器 140 spring事件的体系结构 168 Bean间的关系 109 继承 依赖 引用     Bean的继承          1 为了简化初始化的属性注入;          2 子Bean和父Bean相同的属性值,使用子Bean的     Bean的依赖 Srping控制相互依赖的Bean之间,属性注入的顺序,防止出错  depend-on

【编程底层思考】详解Java的JUC多线程并发编程底层组件AQS的作用及原理

Java中的AbstractQueuedSynchronizer(简称AQS)是位于java.util.concurrent.locks包中的一个核心组件,用于构建锁和其他同步器。AQS为实现依赖于FIFO(先进先出)等待队列的阻塞锁和相关同步器提供了一套高效、可扩展的框架。 一、AQS的作用 统一同步状态管理:AQS提供了一个int类型的成员变量state,用于表示同步状态。子类可以根据自己

多线程的系列文章

Java多线程学习(一)Java多线程入门 Java多线程学习(二)synchronized关键字(1)   Java多线程学习(二)synchronized关键字(2) Java多线程学习(三)volatile关键字 Java多线程学习(四)等待/通知(wait/notify)机制 Java多线程学习(五)线程间通信知识点补充 Java多线程学习(六)Lock锁的使用 Java多

多线程 线程池的创建

一简介 线程的使用在java中占有极其重要的地位,在jdk1.4极其之前的jdk版本中,关于线程池的使用是极其简陋的。在jdk1.5之后这一情况有了很大的改观。Jdk1.5之后加入了java.util.concurrent包,这个包中主要介绍java中线程以及线程池的使用。为我们在开发中处理线程的问题提供了非常大的帮助。 二:线程池 线程池的作用: 线程池作用就是限制系统中执行线程的数量。