Redis进阶篇

Redis线程模型

redis是基于内存运行的高性能k-v数据库,6.x之前是单线程, 对外提供的键值存储服务的主要流程 是单线程,也就是网络 IO 和数据读写是由单个线程来完成,6.x之后引入多线程而键值对读写命 令仍然是单线程处理的,所以 Redis 依然是并发安全的

Redis为什么快

  1. 完全基于内存操作,避免了传统的磁盘io读取内存这部分的消耗

  2. 数据结构简单,基于哈希表结构,可以在 O(1)的时间内计算出 hash 值并且找到对应的 entry位置,entry 里面是一个一个 key 指针和 value 指针这也是 redis 之所以性能高的原因之一

  3. 采用单线程,避免线程切换的事件,不存在竞争条件,也不会出现死锁而造成性能消耗

Redis多线程

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

Redis使用单线程的可维护性高。多线程模型虽然在某些方面表现优异,但是它却引入了程序执行顺序的不确定性,带来了并发读写的一系列问题,增加了系统复杂度、同时可能存在线程切换、甚至加锁解锁、死锁造成的性能损耗。

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

因为Redis的瓶颈不在内存,而是在网络I/O模块带来CPU的耗时,所以Redis6.0的多线程是用来处理网络I/O这部分,充分利用CPU资源,减少网络I/O阻塞带来的性能损耗。

3、Redis6.0 如何开启多线程?

默认情况下Redis是关闭多线程的,可以在conf文件进行配置开启 4、多线程模式下,是否存在线程并发安全问题?

如图,一次redis请求,要建立连接,然后获取操作的命令,然后执行命令,最后将响应的结果写到socket上。

在redis的多线程模式下,获取、解析命令,以及输出结果着两个过程,可以配置成多线程执行的,因为它毕竟是我们定位到的主要耗时点,但是命令的执行,也就是内存操作,依然是单线程运行的。所以,Redis 的多线程部分只是用来处理网络数据的读写和协议解析,执行命令仍然是单线程顺序执行,也就不存在并发安全问题。

Redis持久化

Redis 是一个内存数据库,数据保存在内存中,但是我们都知道内存的数据变化是很快的,也容易发生丢失。Redis 还为我们提供了持久化的机制,分别是RDB(Redis DataBase)和 AOF(Append Only File)

  1. RDB方式

RDB 持久化是指在指定的时间间隔内将内存中的数据集快照写入磁盘。也是默认的持久化方式,这种方式是就是将内存中数据以快照的方式写入到二进制文件中,默认的文件名为 dump.rdb。 在我们安装了 redis 之后,所有的配置都是在 redis.conf 文件中,里面保存了 RDB 和 AOF 两种持久化机制的各种配置。当符合一定条件时 Redis 会自动将内存中的数据进行快照并持久化到硬盘。

触发时机

(1)save命令触发:

该命令会阻塞当前Redis服务器,执行save命令期间,Redis不能处理其他命令,直到RDB完成为止,如果数据量大的话会造成长时间的阻塞,所以线上环境一般禁止使用。

(2)bgsave命令触发:

执行该命令时,Redis会在后台异步进行快照操作,快照同时还可以响应客户端请求。具体流程如下:

执行bgsave命令时,Redis主进程会fork一个子进程来完成RDB的过程,会先将数据写入到一个临时二进制文件中,待持久化过程都结束了,再用这个临时文件替换上次持久化好的文件(可以理解为Copy On Write机制)。Redis主进程阻塞时间只有fork阶段的那一下。相对于save,阻塞时间很短。基本上 Redis 内部所有的RDB操作都是采用 bgsave 命令。

fork的作用是复制一个与当前进程一样的进程。新进程的所有数据(变量、环境变量、程序计数器等)数值都和原进程一致,但是是一个全新的进程,并作为原进程的子进程。

(3)自动触发:

自动触发是可以在redis.conf配置文件中修改,默认达到以下三种条件,就会自动触发持久化,触发后,底层调用的其实还有bgsave命令

  1. AOF方式

以日志的形式来记录每个写操作,将 Redis 执行过的所有指令记录下来(读操作不记录),只许追文件但不可以改写文件,redis 启动之初会读取该文件重新构建数据,换言之,redis 重启的话就根据日志文件的内容将写指令从前到后执行一次以完成数据的恢复工作

Redis双写一致性

延时双删

  • (1)先淘汰缓存

  • (2)再写数据库

  • (3)休眠1秒,再次淘汰缓存

异步队列

增加消息队列,将redis更新操作交给kafka,由消息队列保证可靠性,再搭建一个消费服务,来异步更新redis

订阅binlog

通过订阅binlog来更新redis,把搭建的消费服务作为mysql的一个slave,订阅binlog,解析出更新内容,再更新到redis

Redis事务

Redis 事务本质是一组命令的集合,一个事务中的所有命令都会被序列化,在事务执行过程的中,会按照顺序执行. 所有的命令在事务中,并没有直接被执行. 只有发起执行 exec 命令的时候才会执行. 事务在执行的过程中,不会被其他客户端发送来的命令请求所打断。但是事务不保证同一事物中多条命令执行的原子性,即使命令有错误也会添加到队列中,执行报错也不影响其他命令执行

、MULTI:

用于标记事务块的开启。MULTI执行之后,Redis会将后续的命令逐个放到一个缓存队列中,当EXEC命令被调用时,所有队列中的命令才会被原子化执行。

2、EXEC:

在一个事务中执行所有先前放入队列的命令,然后恢复正常的连接状态。当使用WATCH命令时,只有当受监控的键没有被修改时,EXEC命令才会执行事务中的命令。

3、DISCARD:

放弃事务,清除事务队列中的命令,然后恢复正常的连接状态。如果使用了UNWATCH命令,那么DISCARD命令就会取消当前连接监控的所有键。

主从复制

主从复制,是指将一台 Redis 服务器的数据,复制到其他的 Redis 服务器。前者称为主节点(master),后者称为从节点(slave),数据的复制是单向的,只能由主节点到从节点

1、Redis为什么需要主从复制? 使用Redis主从复制的原因主要是单台Redis节点存在以下的局限性:

(1)Redis虽然读写的速度都很快,单节点的Redis能够支撑QPS大概在5w左右,如果上千万的用户访问,Redis就承载不了,成为了高并发的瓶颈。

(2)单节点的Redis不能保证高可用,当Redis因为某些原因意外宕机时,会导致缓存不可用

(3)CPU的利用率上,单台Redis实例只能利用单个核心,这单个核心在面临海量数据的存取和管理工作时压力会非常大。

2主从复制的好处: (1)数据冗余:主从复制实现了数据的热备份,是持久化之外的一种数据冗余方式。

(2)故障恢复:如果master宕掉了,使用哨兵模式,可以提升一个 slave 作为新的 master,进而实现故障转移,实现高可用

(3)负载均衡:可以轻易地实现横向扩展,实现读写分离,一个 master 用于写,多个 slave 用于分摊读的压力,从而实现高并发;

3、主从复制的缺点: 由于所有的写操作都是先在Master上操作,然后同步更新到Slave上,所以从Master同步到Slave服务器有一定的延迟,当系统很繁忙的时候,延迟问题会更加严重,Slave机器数量的增加也会使这个问题更加严重

哨兵机制

哨兵模式是一种特殊的模式,首先 Redis 提供了哨兵的命令,哨兵是一个独立的进程,作为进程,它会独立运行。其原理是哨兵通过发送命令,等待 Redis 服务器响应,从而监控运行的多个 Redis 实例。

key过期策略

  1. 惰性删除:惰性删除是指,某个键值过期后,此键值不会马上被删除,而是等 到下次被使用的时候,才会被检查到过期,此时才能得到删除。所以惰性删除的 缺点很明显:浪费内存,还需要维护一个字典记录 key 是否过期。

  2. 定期删除:每隔一定的时间,会扫描一定数量的数据库字典中一定数量的 key, 并清除其中已过期的 key。通过调整定时扫描的时间间隔和每次扫描的限定耗 时,可以在不同情况下使得 CPU 和内存资源达到最优的平衡效果。

Redis 中同时使用了惰性过期和定期过期两种过期策略

缓存穿透

key对应的数据不存在,例如id=-1 DB和Redis都没有数据

解决:

  1. 参数校验

  2. 对空值进行缓存,返回value=null

  3. 布隆过滤器,使用bitmap先将可以访问到的资源通过映射关系放入过滤器,当请求到达时,先走过滤器

缓存击穿

某个key再数据库存在,但在redis中key过期

解决:

  1. 提前对key做过期时间设置

  2. 监控数据

  3. 使用锁,只有一个请求获得互斥锁,然后db中将数据查询并返回到redis中,之后所有请求从redis中查询

缓存雪崩

redis中大量key集体过期

解决:

  1. 将失效时间分散,生成随机数key

  2. 多级架构,nginx缓存+redis缓存

  3. 记录缓存标记,如果过期会通知另一个线程更新

  4. 查不到加排他锁

缓存预热

1、什么是缓存预热:

缓存预热是指系统上线后,提前将相关的缓存数据加载到缓存系统。避免在用户请求的时候,先查询数据库,然后再将数据缓存的问题,用户直接查询事先被预热的缓存数据。

如果不进行预热,那么Redis初始状态数据为空,系统上线初期,对于高并发的流量,都会访问到数据库中, 对数据库造成流量的压力。

2、缓存预热解决方案:

(1)数据量不大的时候,工程启动的时候进行加载缓存动作;

(2)数据量大的时候,设置一个定时任务脚本,进行缓存的刷新;

(3)数据量太大的时候,优先保证热点数据进行提前加载到缓存

缓存降级

缓存降级是指缓存失效或缓存服务器挂掉的情况下,不去访问数据库,直接返回默认数据或访问服务的内存数据。降级一般是有损的操作,所以尽量减少降级对于业务的影响程度。

在项目实战中通常会将部分热点数据缓存到服务的内存中,这样一旦缓存出现异常,可以直接使用服务的内存数据,从而避免数据库遭受巨大压力。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/700854.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【PX4SimulinkGazebo联合仿真】在Simulink中使用ROS2控制无人机进入Offboard模式起飞悬停并在Gazebo中可视化

在Simulink中使用ROS2控制无人机进入Offboard模式起飞悬停并在Gazebo中可视化 系统架构Matlab官方例程Control a Simulated UAV Using ROS 2 and PX4 Bridge运行所需的环境配置PX4&Simulink&Gazebo联合仿真实现方法建立Simulink模型并完成基本配置整体框架各子系统实现…

一分钟 由浅入深 学会Navigation

目录 1.官网正式概念 1.1 初认知 2.导入依赖 2.1 使用navigation 2.2 safe Args插件-> 传递数据时用 3.使用Navigation 3.1 搭建初始框架 3.2 确定action箭头的属性 3.3 为Activity添加NavHostFragment控件 3.4 NavController 管理应用导航的对象 3.5 数据传递(单…

Linux——基础IO

📘北尘_:个人主页 🌎个人专栏:《Linux操作系统》《经典算法试题 》《C》 《数据结构与算法》 ☀️走在路上,不忘来时的初心 文章目录 一、C语言IO1、写文件2、读文件3、stdin & stdout & stderr 二、系统文件I/O1、写文件…

常用显示屏学习——LCD12864(含高级驱动程序)

LCD12864液晶显示屏 屏幕介绍 ① 可显示四行字符,每行可显示8个汉字或者16个数字和字母; ②可串行通信和并行通信; ③ 串口接口管脚信号 通信方法 (一)八位并行通信方法 (二)串行通信方法 用…

超实用,分享PostgreSQL和mysql的几点区别

前言 今天是元宵节,首先祝大伙元宵快乐!上一篇文章,给大家讲解了一下MySQL和PostgreSQL性能上的差别。这篇文章主要是记录一下日常应用中,两者常见的一些语法以及一些区别。 PostgreSQL的数据类型 数值类型 字符串类型 日期|时…

Linux--shell编程中分区表常用操作 全面且详细

文章中关于分区表常用操作目录: 一、概念 二、​​​​​​​创建分区表语法 ​​​​​​​三、创建一个表带多个分区 四、​​​​​​​加载数据到分区表中 五、加载数据到一个多分区的表中去 ​​​​​​​六、查看分区 七、​​​​​​​添加一个分区…

机器学习:逻辑回归原理

逻辑回归模型是一种广泛应用于分类问题的统计方法。尽管名为“回归”,但它实际上是一种分类算法,主要用于预测观察对象属于某个类别的概率。逻辑回归模型特别适用于二分类问题,但也可以通过一些策略扩展到多分类问题。 逻辑回归的应用与优化…

让C语言代码变抽象(二)

目录 前言: 代码: 前言: 在今天写代码的时候,我又想到一个更抽象的代码。 我在写注释的时候突然想想到条件编译的东西,好像也能用来注释东西。 代码: 我们在这直接上干货 我们知道在条件编译中有一个叫…

【前端素材】推荐优质后台管理系统Acara平台模板(附源码)

一、需求分析 后台管理系统在多个层次上提供了丰富的功能和细致的管理手段,帮助管理员轻松管理和控制系统的各个方面。其灵活性和可扩展性使得后台管理系统成为各种网站、应用程序和系统不可或缺的管理工具。 后台管理系统是一种用于管理和控制网站、应用程序或系…

Map集合特点、遍历方式、TreeMap排序及Collections和Arrays

目录 ​编辑 一、集合框架 二、 Map集合 特点 遍历方式 HashMap与Hashtable的区别 TreeMap Collections Arrays 一、集合框架 二、 Map集合 Map集合是一种键值对的集合,其中每个键对应一个值。在Java中,Map接口定义了一种将键映射到值的数据结…

嵌入式学习-qt-Day3

嵌入式学习-qt-Day3 一、思维导图 二、作业 完善对话框,点击登录对话框,如果账号和密码匹配,则弹出信息对话框,给出提示”登录成功“,提供一个Ok按钮,用户点击Ok后,关闭登录界面,跳…

「Java开发指南」MyEclipse如何支持Spring Scaffolding?(三)

在上文中(点击这里回顾>>),主要为大家介绍了CRUD Scaffolding,本文将继续介绍应用程序的分层、代码助手等。 MyEclipse v2023.1.2离线版下载 3. 应用程序的分层 应用程序分层是应用程序开发领域中非常常见的体系结构方法…

C++之类作用域

目录 1、全局作用域 2、类作用域 2.1、设计模式之Pimpl 2.2、单例模式的自动释放 2.2.0、检测内存泄漏的工具valgrind 2.2.1、可以使用友元形式进行设计 2.2.2、内部类加静态数据成员形式 2.2.3、atexit方式进行 2.2.4、pthread_once形式 作用域可以分为类作用域、类名…

c++学习记录 STL基本概念

1、STL基本概念 STL(Standard Template Library,标准模板库)STL广义上分为:容器(container)算法(algorithm)迭代器(iterator)容器和算法之间通过迭代器进行无…

线程共享和非共享的资源及线程优缺点

注意:共享的内存地址空间中不包括栈;共享文件描述符表,表示,同一进程中线程可以操作同一文件。

猫头虎分享已解决Bug || TypeError: Cannot read property ‘props‘ of undefined (React)

博主猫头虎的技术世界 🌟 欢迎来到猫头虎的博客 — 探索技术的无限可能! 专栏链接: 🔗 精选专栏: 《面试题大全》 — 面试准备的宝典!《IDEA开发秘籍》 — 提升你的IDEA技能!《100天精通鸿蒙》 …

c++的类型转换方法

一、静态类型转换(static_cast) 静态类型的转换主要用于基本类型之间的转换,比如int类型转换为double类型。但是static_cast也可以支持上下行的转换(存在继承关系之间的转换) 基本类型之间的转换举例 上下行转换的举…

金航标电子位于广西柳州鹿寨县天线生产基地于大年正月初九开工了!!!

金航标kinghelm(www.kinghelm.com.cn)总部位于中国深圳市,兼顾技术、成本、管理、效率和可持续发展。东莞塘厦实验室全电波暗室、网络分析仪、高低温测试柜等仪器设备齐全,可进行高低温、双85等测试,独立完成产品的检测…

数字化转型导师坚鹏:数据安全法解读与政府数字化转型

网络安全法、数据安全法、个人信息保护法解读与政府数字化转型 课程背景: 很多机构存在以下问题: 不清楚网络安全法、数据安全法、个人信息保护法立法背景? 不知道如何理解网络安全法、数据安全法、个人信息保护法政策? 不…

高级RAG:使用RAGAs + LlamaIndex进行RAG评估,包括原理、图和代码

原文地址:Using RAGAs LlamaIndex for RAG evaluation 2024 年 2 月 5 日 如果您已经为实际的业务系统开发了检索增强生成(Retrieval Augmented Generation, RAG)应用程序,那么您可能会关心它的有效性。换句话说,您…