IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 大数据 -> Redis中的阻塞点 -> 正文阅读

[大数据]Redis中的阻塞点

Redis中的阻塞点

Redis作为一个高性能的缓存中间件,在进行网络IO以及键值对读写时仅仅使用的单线程,如果产生阻塞将无法正常响应客户端,所以我们需要了解Redis中到底存在哪些阻塞操作,我们可以按照Redis的关联对象分为如下四种大类。

  • 客户端:键值对的增删改查、网络IO、数据库级别的操作(FLUSHALL、FLUSHDB)。

  • 磁盘:持久化操作RDB快照、AOF追加日志、AOF日志重写。

  • 主从节点:主从同步。

  • 切片集群:向其它实例同步哈希槽信息、数据迁移(负载均衡有热点数据访问量过大,需要重新分配哈希槽)。

客户端阻塞操作

键值对增删改查

键值对的增删改查是和客户端的主要交互部分,如果操作的复杂度过高是会阻塞主线程的,例如查询全部key值keys *、查询Set的所有value值SMEMBERS、查询Hash的全量查询HGETALL以及各种聚合操作(交集、并集、差集等)这些都有可能阻塞主线程,这也就是阻塞点之一。

除了复杂的查询操作外,我们还需要知道删除操作也是存在阻塞风险,虽然删除的时间复杂度为O(1),因为Redis的键值数据保存在全局哈希表中,删除的效率自然高但删除的步骤不仅仅只是删除元素而已,具体分为如下步骤

  • 将对应键值对占用的内存空间释放。

  • 将释放的内存空间插入到空闲内存块链表中,方便后续内存的管理和分配。

所以一旦删除多个元素,那么插入空闲内存块链表的时间就会增长,这里需要特别注意的就是bigkey的删除,虽然删除的元素不多,但是删除后释放的空间大,这样插入到空闲内存块链表中的内存也会增大,从而导致阻塞。

网络IO

Redis在网络层面采用了多路复用IO模型,采用网络套接字避免了建立连接和等待请求到达这些阻塞操作,所以网络IO并不是阻塞点。

数据库级别的操作

数据库级别的操作其实针对的就是FLUSHALL、FLUSHDB这类操作,删除key既然有阻塞的风险那么清空数据库肯定会释放大量的内存空间,也会有阻塞的风险。

磁盘操作

持久化操作RDB文件,主线程会fork子进程完成,需要注意的是fork一瞬间对主线程是阻塞的,而且实例越大对主线程的阻塞时间就越长因为fork的时候会复制主内存的虚拟页表。

重写AOF文件,主线程会fork子进程bgrewriteaof完成。

至于追加写入AOF文件这个根据回写策略(Always、Everysec、No)除了No会由操作系统自己决定写入,其余两种都需要主线程同步写入,如果大量的写操作需要记录到AOF文件中自然就会导致主线程阻塞。

主从节点操作

主从节点间的操作一般是指主从节点同步,主从节点同步一般包括主线程生成RDB文件、传输给从库、从库清空数据库、加载RDB文件。

主从同步中的RDB文件生成主线程和fork子进程完成,而清空数据库已经分析过,那么将RDB文件加载进入内存其实也是一个阻塞操作,文件越大阻塞时间越长。

切片集群操作

对于我们的切片集群Cluster,每个实例主节点都会保存一部分哈希槽的信息,这个信息会在所有主实例间传递这个过程是不会阻塞主线程的,而对于数据迁移Redis Cluster采用同步迁移方案如果存在bigkey那么将阻塞主线程如果不存在bigkey那么将不会阻塞主线程。

阻塞点分析

综上分析得出以下五个阻塞点。

  • 键值对的全量查询或者聚合查询

  • bigkey的删除

  • 数据库级别操作也就是FLUSHALL、FLUSHDB

  • AOF追加写入

  • 主从同步从库RDB文件加载

在Redis主线程上直接执行上述操作显然会导致阻塞,为了避免这种情况Redis提供了异步线程机制,但并不是所有的阻塞点都能异步执行,需要分析是否为关键路径操作。

非关键路径客户端不需要使用执行操作的结果,直接返回OK给客户端就行如客户端1所示,而关键路径是客户端需要等待线程的执行结果,所以无论是主线程执行还是子线程执行都会阻塞,如客户端2所示。

  • 键值对的全量查询或者聚合查询其实都是需要客户端等待Redis响应结果,所以查询是关键路径操作,不能采用异步执行。

  • bigkey的删除这是一个典型的非关键路径不需要向客户端返回具体的值为非关键路径,可以异步执行。

  • 数据库操作FLUSHALL、FLUSHDB和bigkey的删除类似也是非关键路径。

  • AOF追加写入一般认为是同步写入,但写入后不需要返回客户端详细结果,所以也可以异步执行。

  • RDB文件加载必须要阻塞执行,因为客户端需要从节点提供读取服务需要保证数据的完整性,不可异步执行。

综上bigkey的删除、数据库清空操作、AOF日志追加操作可以异步执行。

异步子线程机制

Redis拥有自己的一套异步机制,当Redis启动后会调用系统函数pthread_create创建子线程,如图中提到复杂AOF日志追加、键值删除或清空数据库、文件关闭的异步执行。

当客户端发起操作时,主线程会将数据库操作封装为一个任务以删除为例放入到任务队列中,同时向客户端发送一个完成的信息表明删除完成,这时删除操作其实还未进行,等到后续子线程从任务队列中读取任务时才是真正的删除开始,这也被称为惰性删除。

需要注意的是异步删除键值对方案和异步数据库清空方案都是4.0以后的版本提出

  • 键值对删除少量数据还是可以适用del做同步删除,而bigkey的删除推荐使用UNLINK,该命令会在另外的一个线程回收内存异步进行。

  • 数据库清空可以采用4.0提出的异步方案FLUSHALL、FLUSHDB,加入异步指令FLUSHALL ASYNC,FLUSHDB ASYNC即可异步执行。

而前面提到的AOF追加写入日志在回写策略中配置了everysec(配置No不由Redis写入是操作系统负责写入,配置always只能主线程完成)选项后,主线程将AOF写日志封装成一个任务放入任务队列中,后续子线程读取任务后开始异步写入。

  大数据 最新文章
实现Kafka至少消费一次
亚马逊云科技:还在苦于ETL?Zero ETL的时代
初探MapReduce
【SpringBoot框架篇】32.基于注解+redis实现
Elasticsearch:如何减少 Elasticsearch 集
Go redis操作
Redis面试题
专题五 Redis高并发场景
基于GBase8s和Calcite的多数据源查询
Redis——底层数据结构原理
上一篇文章      下一篇文章      查看所有文章
加:2022-04-30 08:47:05  更:2022-04-30 08:47:28 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 0:47:19-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码