Redis的数据类型,线程,持久化机制
1. Redis是单线程还是多线程的,为什么?
Redis是单线程的(传统实现)
Redis在传统的实现中是单线程的。尽管它处理的任务很多,但它使用单线程来处理所有客户端的请求。这个设计决策有几个关键原因:
-
简化模型: 使用单线程可以避免多线程带来的并发控制复杂性。例如,多个线程之间的同步、互斥、竞态条件等问题。由于Redis的操作通常是内存中的简单计算,不需要多线程的并发控制。
-
性能优化: Redis大多数操作都在内存中进行,并且非常简单,所以没有必要使用多线程来处理。与硬盘I/O等复杂操作相比,内存操作非常快且可以被单线程高效处理。多线程会引入线程上下文切换和锁竞争,这反而会降低性能。
-
原子性保证: Redis的单线程模型能够保证每个操作的原子性。因为每个请求在处理时,Redis不会并发地处理其他请求,这就确保了命令的顺序执行,不会出现并发冲突。
-
顺序执行: 使用单线程可以简化请求的执行顺序,不必担心并发请求的调度问题。
Redis 6.0 引入了多线程
尽管传统上Redis使用单线程,但从Redis 6.0开始,Redis引入了多线程的功能,专门用于处理网络I/O部分。具体来说,它会使用多线程来处理网络请求的读写操作,减少了单线程在进行网络I/O时的阻塞,从而充分利用CPU资源,提高了网络I/O的效率。
- 传统的单线程:只用单个线程处理所有操作,包括网络I/O、请求处理等。
- 多线程优化:通过使用多个线程处理网络I/O,减少了阻塞,避免了CPU闲置,从而提高了整体性能。
总结来说,Redis传统上使用单线程来简化设计,避免复杂性,同时提供高效的内存操作和原子性保证。从6.0版本开始,通过多线程处理I/O,提高了性能。
2. Redis持久化机制有哪些?
Redis支持两种主要的持久化机制:AOF(Append-Only File)和RDB(Redis Database)。
AOF(Append-Only File)日志
-
原理:每当Redis执行写命令时,它会将该命令追加到AOF文件中。AOF的每一行记录都是对数据库的一个操作(如
SET、HSET等)。这种方式的优点是持久化非常细粒度,因为每个写操作都被记录下来。 -
优点:
- 数据丢失的可能性小(基于配置的同步策略)。
- 可以用来重建数据,AOF文件可以作为完全的备份。
-
缺点:
- 写操作会有一定的性能损耗,因为每次写操作都要先记录到文件。
- 文件可能会变得很大。
RDB(Redis Database)快照
-
原理:RDB持久化通过生成数据库的快照来保存数据。Redis在指定的时间点(或者达到一定操作次数后)会将内存中的数据写入到磁盘上的RDB文件。
-
优点:
- 快速恢复:通过RDB文件可以非常迅速地恢复数据。
- 效率高:由于生成快照时并不每次都记录数据变化,因此对性能影响较小。
-
缺点:
- 持久化频率低:默认情况下,RDB会定期生成快照,这可能导致在崩溃时丢失最近的部分数据。
- 由于是全量保存数据,所以RDB文件可能非常大。
混合持久化方式(AOF + RDB)
-
引入:Redis 4.0引入了混合持久化方式,它结合了AOF和RDB的优点:
- 使用RDB来保存数据的全量快照。
- 使用AOF来保存命令日志,以便记录和恢复所有变动。
-
优点:
- 在数据恢复时,可以减少丢失的数据量。
- 既能享受RDB的高效,也能保证AOF的持久化精度。
3. Redis的数据类型有哪些?
Redis有五种常见的基本数据类型,以及几个扩展的数据类型:
1. String(字符串)
- 说明:这是Redis中最基本的数据类型。它可以存储任何类型的数据(如字符串、整数、浮点数等)。
- 例子:
SET key "Hello World"。
2. Hash(哈希)
- 说明:Hash 是一个键值对集合,适用于存储对象。每个Hash有多个字段,每个字段和一个值相关联。
- 例子:
HSET user:1000 name "John" age 30。
3. List(列表)
- 说明:List 是一个有序的字符串集合,可以在列表两端执行插入和删除操作。
- 例子:
LPUSH mylist "item1"或RPUSH mylist "item2"。
4. Set(集合)
- 说明:Set 是一个无序的字符串集合,集合中的元素是唯一的,不允许重复。
- 例子:
SADD myset "apple" "banana"。
5. Zset(有序集合)
- 说明:Zset 是一个有序的字符串集合,其中每个元素都会关联一个分数(score)。它根据分数对元素进行排序。
- 例子:
ZADD leaderboard 100 "Alice" 200 "Bob"。
扩展数据类型:
-
BitMap
- 说明:BitMap 是一个位图数据结构,用于存储二进制的位数据,通常用于位运算。
- 例子:用于处理用户是否签到等场景。
-
HyperLogLog
- 说明:HyperLogLog 是一种用于估算数据基数的算法,通常用于统计大数据集的唯一元素的数量。
- 例子:统计一个大规模的用户访问量。
-
GEO(地理位置)
- 说明:GEO类型用于存储和操作地理位置信息,可以计算两个地理位置之间的距离等。
- 例子:
GEOADD locations 13.361389 38.115556 "Palermo"。
-
Stream(流)
- 说明:Stream 是一种用于消息队列的特殊数据结构,能够存储按时间排序的消息。
- 例子:
XADD mystream * name "Alice" age 30。
总结
- Redis 单线程的设计让它可以避免复杂的多线程同步问题,同时大多数操作在内存中,能够高效执行。
- Redis的持久化机制包括AOF日志、RDB快照以及混合持久化方式。
- Redis支持多种数据类型,包括基本的字符串、哈希、列表、集合、有序集合等,还支持BitMap、HyperLogLog、GEO和Stream等扩展数据类型。
1. BitMap 实现签到功能
BitMap 是一种利用位运算的特殊数据结构。每一位(bit)可以代表一个状态,通常用来高效地表示大量布尔类型的值。对于Redis中的 BitMap,我们常用它来进行一些集合操作,比如 用户签到记录。
实现示例:
假设我们要记录一组用户是否签到,可以使用一个整数的每一位来代表每个用户的签到状态。例如,1 表示签到,0 表示未签到。
步骤:
- 每个用户都有一个唯一的ID,使用用户ID去映射BitMap中的一个位置。
- 如果该位置的值是
1,表示该用户今天已签到,否则表示未签到。
实现示例代码:
// 假设我们有一个用户ID为12345的用户
int userId = 12345;
String key = "user:sign:today"; // 使用key来标识签到BitMap// 使用BitMap的setbit命令来设置该用户签到状态为1
redisClient.setbit(key, userId, 1); // 表示用户12345签到// 查询用户12345是否签到
boolean isSigned = redisClient.getbit(key, userId);
System.out.println("User signed in: " + isSigned); // 输出 true
在这个示例中,我们将每个用户的签到状态映射到一个BitMap中。用户ID作为偏移量,通过 setbit 或 getbit 操作来检查和设置每个用户的签到状态。
BitMap 优势:
- 可以高效地处理大量数据,节省内存。
- 可以用来处理签到、活跃用户等场景,尤其适用于大规模用户的二进制状态(例如是否在线、是否签到等)。
2. GEO 类型存储地理位置信息
Redis提供了一个专门用于存储和操作地理位置信息的类型 GEO。通过 GEO 类型,我们可以存储地理坐标,并执行与地理位置相关的操作,比如计算两点之间的距离。
GEOADD 示例中的数字解释:
GEOADD locations 13.361389 38.115556 "Palermo"
- 13.361389 和 38.115556 是 经度 和 纬度。这些数字是地点(Palermo)的地理坐标。
- “Palermo” 是我们要存储的地点名称,它与经纬度一起组成地理位置数据。
Redis内部会通过这些经纬度对地理位置进行编码并存储。当我们需要计算两点间的距离时,Redis可以利用这些经纬度信息进行计算。
计算距离:
GEODIST locations "Palermo" "Rome" km
- 这里
"Palermo"和"Rome"是两个地点名,Redis会返回它们之间的地理距离(单位为km或m等)。
GEO 类型的应用场景:
- 商户定位:根据用户的地理位置返回附近的商户。
- 社交网络:通过地理位置判断好友是否在附近等。
3. HyperLogLog 估算基数
HyperLogLog 是一种用于基数估算的算法。基数(Cardinality)指的是一组数据中不同元素的数量。通常用于统计大规模数据集中的唯一元素的数量,例如访问网站的唯一用户数量。
如何统计的:
- HyperLogLog 使用概率算法,通过映射不同的哈希值来估算唯一元素的数量。
- 它通过处理哈希值的二进制位来计算基数。由于哈希值是随机的,算法利用这些值的分布情况来估算基数。
实现过程:
- 对每一个输入的元素(如每个访问的用户ID),进行哈希运算。
- 基于哈希值的二进制位分布,统计出不同哈希值的“最大尾零位”的位置。
- 根据统计结果,利用算法估算出集合中的不同元素数量。
Redis中如何使用 HyperLogLog 统计访问量:
PFADD visitors user1 user2 user3 user4
PFCOUNT visitors
PFADD用于将元素加入HyperLogLog中,PFCOUNT返回该集合的估算基数(即不同元素的数量)。
这种方法非常高效,能够在空间非常小的情况下,处理大规模的基数估算。
HyperLogLog的优势:
- 空间占用小:对于大规模数据集,它的内存消耗远小于传统的计数方法(如存储所有元素)。
- 精度较低:由于是概率算法,因此估算结果会有一定误差,但通常误差非常小。
4. Stream 类型的消息队列
Redis的 Stream 类型用于实现消息队列,它能够存储按时间排序的消息。在流(Stream)中,每条消息都有一个唯一的ID,其中包含时间戳信息。
XADD 示例代码:
XADD mystream * name "Alice" age 30
在这个命令中:
mystream是流的名称。*是自动生成一个基于时间戳的唯一ID。"name" "Alice"和"age" 30是消息的字段和值。
Redis中的Stream会自动为每一条消息生成一个时间戳加自增ID的唯一消息ID,类似于 1619512143507-0,其中前面部分是时间戳,后面是自增的序号。
如何按照时间排序:
- 每条消息的ID包含时间戳,Redis会根据消息ID的时间戳自动按时间顺序对消息进行排序。
- 用户可以通过
XREAD或XREVRANGE等命令读取消息,从而实现按时间顺序的消费。
Stream的应用:
- 消息队列:通过Stream可以构建高效的消息队列。
- 实时数据流处理:可以实时获取和处理数据流。
总结:
- BitMap 用于处理大量的二进制状态(例如签到),通过位运算高效存储。
- GEO 存储地理位置信息,通过经纬度表示,支持计算地点之间的距离。
- HyperLogLog 用于基数估算,处理大规模数据集的唯一元素数量。
- Stream 用于存储按时间排序的消息,常用于实现高效的消息队列。
这些数据结构在实际开发中可以解决各种高效的数据存储和计算问题,特别是在大数据量的场景下。
相关文章:
Redis的数据类型,线程,持久化机制
1. Redis是单线程还是多线程的,为什么? Redis是单线程的(传统实现) Redis在传统的实现中是单线程的。尽管它处理的任务很多,但它使用单线程来处理所有客户端的请求。这个设计决策有几个关键原因: 简化模型…...
什么是ondelete cascade以及使用sqlite演示ondelete cascade使用案例
什么是ondelete cascade ON DELETE CASCADE是数据库中的一种约束,用于自动删除相关的记录。具体来说,当一个表中的记录(父表)被删除时,与其相关的其他表(子表)中的记录也会被自动删除&…...
Java设计模式 —— 【结构型模式】享元模式(Flyweight Pattern) 详解
文章目录 概述结构案例实现优缺点及使用场景 概述 享元模式也叫蝇量模式:运用共享技术有效地支持大量细粒度的对象; 常用于系统底层开发,解决系统的性能问题。像数据库连接池,里面都是创建好的连接对象,在这些连接对象…...
数据的简单处理——pandas模块——选择数据
要对读取的数据进行编辑,需要先学会选择数据的操作,如果选择行数据、列数据或者同时选择行列数据。 ############################## ##作者:白雪公主的后妈 ##时间:2024年12月29日 ##主题:数据的简单处理——pandas模…...
淘宝/天猫购物车商品列表API:深度解析与应用实践
引言 在电商领域,购物车功能是提升用户体验和增加销售额的关键工具。淘宝和天猫作为中国最大的电商平台,提供了丰富的API接口,其中包括获取购物车商品列表的API,即buyer_cart_list。本文将深入解析淘宝/天猫购物车商品列表API的功…...
位置式PID-控制步进电机-位置环-stm32
基本原理 1、软件设计 本闭环控制例程是在步进电机编码器测速例程的基础上编写的,这里只讲解核心的部分代码,有些变量的设置,头文件的包含等并没有涉及到,完整的代码请参考本章配套的工程。 我们创建了4个文件:bsp_pid.c和bsp_pid.h文件用来存放PID控制器相关程序,bsp_s…...
关于Qt::BlockingQueuedConnection的死锁问题
绑定信号槽时,如果信号对象和槽对象属于不同的线程,通过Qt::BlockingQueuedConnection可以实现同步调用,即发送信号的代码等待槽函数返回才继续运行 文档的说明: Qt::QueuedConnection The slot is invoked when control returns…...
Excel for Finance 07 `FV PV` 函数
Excel 的 FV 函数用于计算一笔投资在未来的价值,基于固定的利率和定期付款。这是一个金融函数,常用来分析储蓄计划、贷款、或投资的增长。 语法: FV(rate, nper, pmt, [pv], [type])参数说明: rate(必需)&…...
驱动开发系列31 - Linux Graphics 调试 mesa 的 glDrawArrays (三)
一:概述 接着前面驱动开发系列26 - Linux Graphics 调试 mesa 的 glDrawArrays (二)-CSDN博客的文章继续分析下glDrawArrays的实现,本文介绍一下在Gallium3D HW Driver中,驱动如何将绘制命令提交给GPU执行。看下驱动层的执行逻辑:即 draw_vbo 的过程。 二:回顾下draw_vbo…...
【探花交友】day03—MongoDB基础
目录 课程介绍 1、通用设置 1.1 需求分析 1.2 查询通用设置 1.2 陌生人问题 1.3 通知设置 1.4 黑名单管理 2、MongoDB简介 1.1、MongoDB简介 1.2、MongoDB的特点 1.3 数据类型 3、MongoDB入门 2.1、数据库以及表的操作 2.2、新增数据 2.3、更新数据 2.4、删除数…...
【Vue教程】使用Vite快速搭建前端工程化项目 | Vue3 | Vite | Node.js
🙋大家好!我是毛毛张! 🌈个人首页: 神马都会亿点点的毛毛张 🚩今天毛毛张分享的是关于如何快速🏃♂️搭建一个前端工程化的项目的环境搭建以及流程🌠 文章目录 1.前端工程化环境搭建&#…...
手机租赁平台开发全攻略打造高效便捷的租赁服务系统
内容概要 手机租赁平台开发,简单说就是让用户能轻松租赁各类手机的高效系统。这一平台不仅帮助那些想要临时使用高端手机的人们节省了不少资金,还为商家开辟了新的收入渠道。随着智能手机的普及,很多人并不需要长期拥有一部手机,…...
自由学习记录(31)
Java连接MySQL 找到那个关键jar包然后导入选中,就配置好MySQL的JDBC(Java Database Connectivity)了 菜单--文件--项目结构 项目设置--模块--选择要附着的项目--选择依赖--选中模块源--选中加号添加jar包 解压之后在里面可以看到这个最关键…...
【探花交友】用户登录总结
1.发送验证码 1.发送post请求 数据封装在map 获取map的手机号码 2.调用service层将手机号码 传入过去 3.正常返回状态码200 RestController RequestMapping("/user") public class LoginController {Autowiredprivate UserService userService;/*** 获取登录验证码*…...
LabVIEW声波谐振管自动化测量系统
开发了一种基于LabVIEW的声波谐振管自动化测量系统。该系统利用LabVIEW的强大功能,实现了对声波谐振频率的精确测量,提高了实验数据的采集效率和准确性。系统主要应用于物理教学和科研中,用于研究声波在谐振管中的传播特性。 项目背景 传统的…...
elasticsearch中的倒排索引
倒排索引是搜索引擎中常用的一种数据结构,适用于全文检索,能够通过文本内容高效检索到相应的文档。 一、倒排索引的基本概念 正排索引:传统的索引方式,按照文档id顺序存储文档,通过文档id找到文档对应的词。因此当需…...
【Elasticsearch】DSL查询文档
目录 1.DSL查询文档 1.1.DSL查询分类 1.2.全文检索查询 1.2.1.使用场景 1.2.2.基本语法 1.2.3.示例 1.2.4.总结 1.3.精准查询 1.3.1.term查询 1.3.2.range查询 1.3.3.总结 1.4.地理坐标查询 1.4.1.矩形范围查询 1.4.2.附近查询 1.5.复合查询 1.5.1.相关性算分 …...
接口测试Day04-postman生成测试报告ihrm项目
测试报告-利用newman插件 安装node.js 安装 双击 .msi 文件,一路下一步安装即可。无需特殊设定。测试安装成功 npm -v 安装npm 安装newman 安装newman npm install -g newman试安装成功 newman -v安装newman插件 - 扩展版 npm install -g newman-reporter-htmlex…...
常见的排序算法过程和比较分析
比较分析 排序类别排序算法时间复杂度(最好)时间复杂度(最坏)时间复杂度(平均)辅助空间复杂度稳定性插入排序直接插入排序O(n)O(n)O(n)O(1)稳定插入排序折半插入排序O(n)O(n)O(n)O(1)稳定插入排序希尔排序…...
基于Vue+SSM+SpringCloudAlibaba书籍管理系统
功能要求 一、登录功能(http://localhost:8080/#/login) 输入账号和密码(admin/admin)进行登录: 如果密码错误,给出提示信息 如果密码正确,跳转到主页 账号或密码错误: 账号密码正确:跳转到…...
JavaSec-RCE
简介 RCE(Remote Code Execution),可以分为:命令注入(Command Injection)、代码注入(Code Injection) 代码注入 1.漏洞场景:Groovy代码注入 Groovy是一种基于JVM的动态语言,语法简洁,支持闭包、动态类型和Java互操作性,…...
深入浅出Asp.Net Core MVC应用开发系列-AspNetCore中的日志记录
ASP.NET Core 是一个跨平台的开源框架,用于在 Windows、macOS 或 Linux 上生成基于云的新式 Web 应用。 ASP.NET Core 中的日志记录 .NET 通过 ILogger API 支持高性能结构化日志记录,以帮助监视应用程序行为和诊断问题。 可以通过配置不同的记录提供程…...
R语言AI模型部署方案:精准离线运行详解
R语言AI模型部署方案:精准离线运行详解 一、项目概述 本文将构建一个完整的R语言AI部署解决方案,实现鸢尾花分类模型的训练、保存、离线部署和预测功能。核心特点: 100%离线运行能力自包含环境依赖生产级错误处理跨平台兼容性模型版本管理# 文件结构说明 Iris_AI_Deployme…...
shell脚本--常见案例
1、自动备份文件或目录 2、批量重命名文件 3、查找并删除指定名称的文件: 4、批量删除文件 5、查找并替换文件内容 6、批量创建文件 7、创建文件夹并移动文件 8、在文件夹中查找文件...
3.3.1_1 检错编码(奇偶校验码)
从这节课开始,我们会探讨数据链路层的差错控制功能,差错控制功能的主要目标是要发现并且解决一个帧内部的位错误,我们需要使用特殊的编码技术去发现帧内部的位错误,当我们发现位错误之后,通常来说有两种解决方案。第一…...
工程地质软件市场:发展现状、趋势与策略建议
一、引言 在工程建设领域,准确把握地质条件是确保项目顺利推进和安全运营的关键。工程地质软件作为处理、分析、模拟和展示工程地质数据的重要工具,正发挥着日益重要的作用。它凭借强大的数据处理能力、三维建模功能、空间分析工具和可视化展示手段&…...
vue3 定时器-定义全局方法 vue+ts
1.创建ts文件 路径:src/utils/timer.ts 完整代码: import { onUnmounted } from vuetype TimerCallback (...args: any[]) > voidexport function useGlobalTimer() {const timers: Map<number, NodeJS.Timeout> new Map()// 创建定时器con…...
【HTML-16】深入理解HTML中的块元素与行内元素
HTML元素根据其显示特性可以分为两大类:块元素(Block-level Elements)和行内元素(Inline Elements)。理解这两者的区别对于构建良好的网页布局至关重要。本文将全面解析这两种元素的特性、区别以及实际应用场景。 1. 块元素(Block-level Elements) 1.1 基本特性 …...
使用 SymPy 进行向量和矩阵的高级操作
在科学计算和工程领域,向量和矩阵操作是解决问题的核心技能之一。Python 的 SymPy 库提供了强大的符号计算功能,能够高效地处理向量和矩阵的各种操作。本文将深入探讨如何使用 SymPy 进行向量和矩阵的创建、合并以及维度拓展等操作,并通过具体…...
React---day11
14.4 react-redux第三方库 提供connect、thunk之类的函数 以获取一个banner数据为例子 store: 我们在使用异步的时候理应是要使用中间件的,但是configureStore 已经自动集成了 redux-thunk,注意action里面要返回函数 import { configureS…...
