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

技术研究:Redis 数据结构与 I/O 模型

数据结构

Redis之所以“快”,一方面因为它是内存数据库,所有操作都在内存上完成,内存的访问速度本来就快。另一方面则是因为高效的数据结构,使得操作键值效率较高。总体来说,Redis使用了一个用来保存每个Key/Value的全局哈希表结构,其中Value类型又包括了支持集合类型的双向链表、压缩列表、跳表等五大底层结构。简单来说,底层数据结构一共有 6 种,分别是简单动态字符串、双向链表、压缩列表、哈希表、跳表和整数数组。它们和数据类型的对应关系如下图所示:

Redis使用了一个全局维度的哈希表来保存所有的Key/Value,每个哈希表本质上都是一个数组,这个数组的每个元素称为一个哈希桶。哈希桶中的元素保存的并不是Value本身,而是指向Value的指针,如下图所示:

由数据结构的知识可以知道,哈希表的时间复杂度为O(1),因此它非常适合快速查找的场景。当往哈希表中写入的数据变的很多时,哈希冲突问题就会出现。Redis采用了链式哈希来解决哈希冲突。但是,如果哈希表里写入的数据越来越多,哈希冲突链也会进而变得很长,从而导致这个链条上得元素查找耗时长,效率降低。因此,Redis还会对哈希表做rehash操作。所谓rehash,就是增加现有的哈希桶的数量,让逐渐增多的entry元素能够在更多的桶之间分散保存,减少单个桶中的元素数量,从而减少单个桶中的冲突。在具体操作中,Redis会开辟一个新的哈希表(比如:大小为之前的两倍),然后把之前哈希表的数据重新映射到新的哈希表,最后释放之前的哈希表。在拷贝之前哈希表数据到新哈希表时,涉及到数据量过大,有可能会造成Redis的线程阻塞,从而无法服务其他的请求。因此,Redis采用了渐进式哈希的解决方案。简单来说,所谓渐进式哈希就是不一次性把老哈希表中的数据迁移完,而是在每次处理一个请求时,从老哈希表中的第一个索引位置开始,顺带着将这个索引位置上的所有entries拷贝到新哈希表中;等下一个请求时,再顺带拷贝下一个索引位置的entries。如此,便将一次性的大量拷贝的开销,分摊到多次处理请求的过程中,避免了耗时的操作和服务的中断。此外,渐进式rehash执行时,除了根据键值对的操作来进行数据迁移,Redis本身还会有一个定时任务在执行rehash,如果没有键值对操作时,这个定时任务会周期性地(例如每100ms一次)搬移一些数据到新的哈希表中,这样可以缩短整个rehash的过程。

I/O 模型

我们通常说的Redis单线程,主要是指:Redis 6.0 之前版本的 网络I/O 和 键值对读写 是由一个线程来完成的。除了网络I/O 和 键值对读写之外的其他功能,大多都是由额外的线程执行的。比如:持久化、异步删除、集群数据同步等操作。

Note:Redis 6.0之后对网络I/O改为使用多线程,但是,仍然使用单线程处理键值对的读写操作。

Redis 为什么用单线程?

多线程系统中,通常会有共享资源需要被多个线程访问和修改。为了保证这些共享资源的正确性,需要额外的机制(如锁)来进行控制。这些机制会带来额外的开销。多线程开发中,并发访问控制是一个难点。如果没有精细设计,只是简单使用粗粒度的互斥锁,会导致大部分线程在等待锁,导致并行变成串行,系统吞吐率不升反降。

Redis的单线程效率:

我们都知道,Redis公开出来的数据:Redis使用单线程也可以达到每秒10万级的处理能力(前提条件:在一定的服务器配置下才能达到)。

为什么这么高效?核心原因有两个:

(1)Redis的大部分操作都在内存上完成 + 采用了高效的数据结构

(2)Redis采用了多路复用机制,使其在网络I/O操作中能够并发处理大量的客户端请求,从而实现高吞吐率。

其中,原因(2)是Redis单线程高效率的重点,它避免了accept() 和 send()/recv() 潜在的网络I/O操作的阻塞点

Redis I/O模型:

Redis在设计中基于Linux的I/O多路复用机制实现了自己的I/O模型,如下图所示:

上图中的多个FD就是多个套接字(Socket),Redis的网络框架通过调用epoll让内核监听这些套接字。此时,Redis线程不会阻塞在某一个特定的监听 或 已连接的套接字上。因此,Redis可以同时和多个客户端连接并处理请求,从而提升并发性

相关文章:

技术研究:Redis 数据结构与 I/O 模型

数据结构 Redis之所以“快”,一方面因为它是内存数据库,所有操作都在内存上完成,内存的访问速度本来就快。另一方面则是因为高效的数据结构,使得操作键值效率较高。总体来说,Redis使用了一个用来保存每个Key/Value的全…...

46-扇孔的处理及铺铜以及布线

1.先连信号线 2.电源管脚,以如下方式处理: 引线打孔处理...

LVS实验的三模式总结

文章目录 LVS的概念叙述NAT工作模式实战案例**思想:**NAT工作模式的优点NAT工作模式的缺点 NAT工作模式的应用场景大致配置 route:打开路由内核功能 部署DR模式集群案例工作思想:大致工作图如下思路模型 具体配置与事实步骤补充 防火墙标签解…...

游戏安全入门-扫雷分析远程线程注入

前言 无论学习什么,首先,我们应该有个目标,那么入门windows游戏安全,脑海中浮现出来的一个游戏 – 扫雷,一款家喻户晓的游戏,虽然已经被大家分析的不能再透了,但是我觉得自己去分析一下还是极好…...

bert-base-chinese模型的完整训练、推理和一些思考

前言 使用google-bert/bert-base-chinese模型进行中文文本分类任务,使用THUCNews中文数据集进行训练,训练完成后,可以导出模型,进行预测。 项目详细介绍和数据下载 数据集下载地址 Github完整代码 现记录训练过程中的一些感悟…...

JS基础5(JS的作用域和JS预解析)

JS的作用域 1. 全局作用域 全局作用域是在代码的任何地方都能访问到的最外层作用域。在浏览器环境下,全局作用域就是window对象,因此所有在全局作用域中声明的变量和函数都会成为window对象的属性和方法。 var globalVar "I am global"; …...

Doris 夺命 30 连问!(中)

导言 抱歉,作为从 S2 开始的骨灰级玩家看到 EDGUZI 官宣首发上线,兴奋之余忘了写文档 - -||,还望各位看官老爷见谅,这次错了,下次还敢 ^_^ 这是继上次的 30 问上篇的中篇,也是 10 个问题,有些…...

书生.浦江大模型实战训练营——(四)书生·浦语大模型全链路开源开放体系

最近在学习书生.浦江大模型实战训练营,所有课程都免费,以关卡的形式学习,也比较有意思,提供免费的算力实战,真的很不错(无广)!欢迎大家一起学习,打开LLM探索大门&#xf…...

SpringBoot 整合 RabbitMQ 实现延迟消息

一、业务场景说明 用于解决用户下单以后,订单超时如何取消订单的问题。 用户进行下单操作(会有锁定商品库存、使用优惠券、积分一系列的操作);生成订单,获取订单的id;获取到设置的订单超时时间&#xff0…...

Cilium:基于开源 eBPF 的网络、安全性和可观察性

基于 eBPF 的网络、安全性和可观察性 Cilium 是一种开源的云原生解决方案,它利用 Linux 内核中的 eBPF 技术来提供、保护和监控工作负载之间的网络连接。 什么是 eBPF? eBPF 是一项源自 Linux 内核的技术,允许沙盒程序在特权上下文&#x…...

Axios 详解与使用指南

Axios 详解与使用指南 1. Axios 简介 Axios 是一个基于 Promise 的 HTTP 客户端,能够在浏览器和 Node.js 环境中运行。它提供了一种简便的方式来执行 HTTP 请求,并支持多种请求方法,如 GET、POST、PUT、DELETE 等。Axios 的配置灵活&#x…...

深度学习 —— 个人学习笔记20(转置卷积、全卷积网络)

声明 本文章为个人学习使用,版面观感若有不适请谅解,文中知识仅代表个人观点,若出现错误,欢迎各位批评指正。 三十九、转置卷积 import torch from torch import nndef trans_conv(X, K):h, w K.shapeY torch.zeros((X.shape[…...

解决Mac系统Python3.12版本pip安装报错error: externally-managed-environment的问题

遇到的问题 在Mac安装了Python3.12.x版本(3.12.3、3.12.4)后,当尝试pip3 install xxx的时候,总是报错:error: externally-managed-environment error: externally-managed-environment This environment is external…...

lvm知识终结

、什么是 LVM LVM 是 Linux 下对磁盘分区进行管理的一种工具,适合管理大存储设备,并允许用户动态调整文件系统的大小 lvm 常用的命令 功能 PV 管理命令 VG 管理命令 LV 管理命令 scan 扫描 pvscan vgscan lvscan create 创建 pvcreate v…...

ESP32S3 IDF 对 16路输入输出芯片MCP23017做了个简单的测试

这次还是使用了idf老版本4.4.7,上次用了5.3,感觉不好用,官方的MCP23017芯片是英文版,真的很难读明白,可能是我英语水平不够吧。先看看每个寄存器的功能: IODIRA 和 IODIRB: 输入/输出方向寄存器 IPOLA 和 I…...

【技术前沿】Flux.1部署教程入门--Stable Diffusion团队最前沿、免费的开源AI图像生成器

项目简介 FLUX.1 是一种新的开源图像生成模型。它由 Stable Diffusion 背后的团队 Black Forest Labs 开发。 官网中有以下功能开源供大家参考: FLUX.1 擅长在图像中准确再现文字,因此非常适合需要清晰文字或短语的设计。无论是标牌、书籍封面还是品牌…...

Redis 的 STREAM 和 RocketMQ 是两种不同的消息队列和流处理解决方案,它们在设计理念、功能和用途上有显著区别。以下是它们的主要区别:

20240813 Redis 的 STREAM 和 RocketMQ 是两种不同的消息队列和流处理解决方案,它们在设计理念、功能和用途上有显著区别。以下是它们的主要区别:1. 使用 Redis 的 Sorted Set 数据结构连接到 Redis示例用法添加事件获取滑动窗口内的事件移除过期事件连接…...

Visual Studio Code安装与C/C++语言运行(上)

Visual Studio Code(VS Code)作为微软开发的一款轻量级但功能强大的源代码编辑器,广泛应用于各种编程语言的开发,包括C/C。以下将详细介绍VS Code的安装过程以及与C/C语言运行环境的配置。 一、Visual Studio Code的安装 1. 准备…...

探索数据可视化,数据看板在各行业中的应用

数据可视化是一种通过图形化手段将数据呈现出来的技术,它将复杂的数据和信息转化为易于理解的图表、地图、仪表盘等视觉元素,使得数据的模式、趋势和关系更加直观地展现出来。通过数据可视化,用户可以快速识别重要信息、发现潜在问题&#xf…...

haralyzer 半自动,一次性少量数据采集快捷方法

使用场景:半自动,一次性少量数据采集需求在工作中还是不少遇到的,无论使用模拟的方式,或者破解都不太划算。其实这种需求,使用半自动爬虫是最简单的。不需要考虑网站反爬虫的问题,因为你使用的就是真实的浏…...

在rocky linux 9.5上在线安装 docker

前面是指南,后面是日志 sudo dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo sudo dnf install docker-ce docker-ce-cli containerd.io -y docker version sudo systemctl start docker sudo systemctl status docker …...

Module Federation 和 Native Federation 的比较

前言 Module Federation 是 Webpack 5 引入的微前端架构方案,允许不同独立构建的应用在运行时动态共享模块。 Native Federation 是 Angular 官方基于 Module Federation 理念实现的专为 Angular 优化的微前端方案。 概念解析 Module Federation (模块联邦) Modul…...

从零实现STL哈希容器:unordered_map/unordered_set封装详解

本篇文章是对C学习的STL哈希容器自主实现部分的学习分享 希望也能为你带来些帮助~ 那咱们废话不多说&#xff0c;直接开始吧&#xff01; 一、源码结构分析 1. SGISTL30实现剖析 // hash_set核心结构 template <class Value, class HashFcn, ...> class hash_set {ty…...

C++ 求圆面积的程序(Program to find area of a circle)

给定半径r&#xff0c;求圆的面积。圆的面积应精确到小数点后5位。 例子&#xff1a; 输入&#xff1a;r 5 输出&#xff1a;78.53982 解释&#xff1a;由于面积 PI * r * r 3.14159265358979323846 * 5 * 5 78.53982&#xff0c;因为我们只保留小数点后 5 位数字。 输…...

Linux --进程控制

本文从以下五个方面来初步认识进程控制&#xff1a; 目录 进程创建 进程终止 进程等待 进程替换 模拟实现一个微型shell 进程创建 在Linux系统中我们可以在一个进程使用系统调用fork()来创建子进程&#xff0c;创建出来的进程就是子进程&#xff0c;原来的进程为父进程。…...

华硕a豆14 Air香氛版,美学与科技的馨香融合

在快节奏的现代生活中&#xff0c;我们渴望一个能激发创想、愉悦感官的工作与生活伙伴&#xff0c;它不仅是冰冷的科技工具&#xff0c;更能触动我们内心深处的细腻情感。正是在这样的期许下&#xff0c;华硕a豆14 Air香氛版翩然而至&#xff0c;它以一种前所未有的方式&#x…...

Mysql中select查询语句的执行过程

目录 1、介绍 1.1、组件介绍 1.2、Sql执行顺序 2、执行流程 2.1. 连接与认证 2.2. 查询缓存 2.3. 语法解析&#xff08;Parser&#xff09; 2.4、执行sql 1. 预处理&#xff08;Preprocessor&#xff09; 2. 查询优化器&#xff08;Optimizer&#xff09; 3. 执行器…...

Go 并发编程基础:通道(Channel)的使用

在 Go 中&#xff0c;Channel 是 Goroutine 之间通信的核心机制。它提供了一个线程安全的通信方式&#xff0c;用于在多个 Goroutine 之间传递数据&#xff0c;从而实现高效的并发编程。 本章将介绍 Channel 的基本概念、用法、缓冲、关闭机制以及 select 的使用。 一、Channel…...

现有的 Redis 分布式锁库(如 Redisson)提供了哪些便利?

现有的 Redis 分布式锁库&#xff08;如 Redisson&#xff09;相比于开发者自己基于 Redis 命令&#xff08;如 SETNX, EXPIRE, DEL&#xff09;手动实现分布式锁&#xff0c;提供了巨大的便利性和健壮性。主要体现在以下几个方面&#xff1a; 原子性保证 (Atomicity)&#xff…...

【C++进阶篇】智能指针

C内存管理终极指南&#xff1a;智能指针从入门到源码剖析 一. 智能指针1.1 auto_ptr1.2 unique_ptr1.3 shared_ptr1.4 make_shared 二. 原理三. shared_ptr循环引用问题三. 线程安全问题四. 内存泄漏4.1 什么是内存泄漏4.2 危害4.3 避免内存泄漏 五. 最后 一. 智能指针 智能指…...