【Redis】缓存+分布式锁

目录

缓存

Redis最主要的使用场景就是作为缓存

缓存的更新策略:

1.定期生成

2.实时生成

面试重点:

缓存预热(Cache preheating):

缓存穿透(Cache penetration)

缓存雪崩 (Cache avalanche)

缓存击穿 (Cache breakdown)

分布式锁 

分布式锁的基本实现:

引入过期时间:

引入校验Id:

引入lua脚本:

引入watch dog(看门狗)

引入Redlock算法:


缓存

核心思路就是把⼀些常见的数据放到触手可及(访问速度更快)的地方, 方便随时读取.

访问速度特别的快,但由于存储空间是有限的,所有我们只能存储“热点数据”(频繁访问的数据)在Redis中
俗称“二八定律”:20%的热点数据,可以应对80%的应用场景,从而整体上的性能得到提升


Redis最主要的使用场景就是作为缓存

对应MySQL这种访问硬盘的数据库,Redis是内存数据库,Redis用做为MySQL的缓存

为什么MySQL性能不高?

1.首先数据存储在硬盘上,硬盘IO需要花费大量时间,尤其是随机访问;

2.如果查询中不能命中索引,那么将需要表的遍历,大大增加硬盘IO的次数

3.对应执行SQL需要一系列的解析,校验等等工作

4.如果是一些复杂查询,例如联合查询,笛卡尔积之类的操作效率会很低...............

如果数据库并发量特别高,那么它将会可能出现宕机(出现故障,罢工了,不做了)的情况

如何解决?

1.开源:增加多个设备,部署更多的数据库机器,构成数据库集群

2.节流:引入缓存,访问的时候尽量访问缓存内的数据,从而降低直接访问数据库的请求数量

实际开发中,往往是俩种方法结合起来使用

Redis为什么可以作为MySQL的缓存:

Redis访问速度比MySQL快很多,并且处理一个访问请求,Redis消耗的资源比MySQL少很多,因此Redis支持更大的并发量:

1.Redis数据在内存,并且访问速度比硬盘快很多

2.Redis只支持简单的KEY-VALUE 存储,不涉及很多复杂查询方法手段

业务服务器先查询 Redis, 看想要的数据是否在 Redis 中存在.

  • 如果已经在 Redis 中存在了, 就直接返回. 此时不必访问 MySQL 了.
  • 如果在 Redis 中不存在, 再查询 MySQL.


缓存的更新策略:

一个重要问题:那么多数据,哪些数据才是我们需要的热点数据呢?

1.定期生成

会将所有访问的数据,以日志的形式给记录下来,最后挑选出频率前%N的数据作为“热点数据”;

此处的数据,可以按照每天/周/月去更新热点数据 

2.实时生成

  • 如果在Redis查找到了,那么将直接返回
  • 如果在Redis没有查找到,那么从数据库查找,查找完并且写入Redis中

那么经过这样一段时间内,缓存的数据肯定会存储满,那么Redis也引入了对应的策略--------------内存淘汰机制:

通用的淘汰机制有以下机制:

  • FIFO (First In First Out) 先进先出 
    把缓存中存在时间最久的 (也就是先来的数据) 淘汰掉.  

     
  • LRU (Least Recently Used) 淘汰最久未使⽤的 
    记录每个 key 的最近访问时间. 把最近访问时间最⽼的 key 淘汰掉.  

     
  • LFU (Least Frequently Used) 淘汰访问次数最少的 
    记录每个 key 最近⼀段时间的访问次数. 把访问次数最少的淘汰掉.  

     
  • Random 随机淘汰 
    从所有的 key 中抽取幸运⼉被随机淘汰掉.  

 在Redis中已经实现好了以上类似机制:

整体来说 Redis 提供的策略和我们上述介绍的通用策略是基本⼀致的. 只不过 Redis 这里会针对 "过期 key" 和 "全部 key" 做分别处理.

面试重点:

缓存预热(Cache preheating):

1.定期生成的数据这种情况不涉及缓存预热;

2.实时生成:
Redis服务器首次接入连接之后是没有数据的,此时所有的请求将在MySQL中(就怕此时MySQL没有抗住这么多请求挂了),那么随之时间的推移,Redis上的数据慢慢越来越多,MySQL承担的压力就会小很多;

缓存预热就是解决上述问题:
将定期生成和实时生成结合一下,先通过“离线”的方式,通过统计的途径,先找到一些热点数据(这些数据并一定精准,有就行)导入到Redis中,就能帮助MySQL承担很大的压力,随之时间的推移,热点数据会逐渐调整,来使用当前情况;


缓存穿透(Cache penetration)

在查询某个key的时候,在Redis中没有,在MySQL中也没有,那么这么key肯定不会更新到Redis中~ 
但是这个查询没有,接连着查询了多次,依然会给MySQL造成一些压力;

为什么出现这种情况?

  • 业务设计不合理. 比如缺少必要的参数校验环节, 导致非法的 key 也被进行查询了.
  • 开发/运维误操作. 不小心把部分数据从数据库上误删了.
  • 黑客恶意攻击.

解决:

  • 针对要查询的参数进行严格的合法性校验. 比如要查询的 key 是用户的手机号, 那么就需要校验当前key 是否满足一个合法的手机号的格式.
  • 针对数据库上也不存在的 key , 也存储到 Redis 中,比如 value 就随便设成一个 "". 避免后续频繁访问数据库
  • 使用布隆过滤器先判定 key 是否存在, 再真正查询.

缓存雪崩 (Cache avalanche)

在短时间内,Redis上大规模的key失效,导致缓存命中率陡然下降,让MySQL的压力迅游变大,导致宕机~

为何产生?

1.Redis挂了

2.Redis没有挂,但是可能之前给很多key设置的过期时间相同,一下子全过期自动删除了

解决:

  • 部署高可用的 Redis 集群, 并且完善监控报警体系.
  • 不给 key 设置过期时间 或者 设置过期时间的时候添加随机时间因子.

缓存击穿 (Cache breakdown)

相当于缓存雪崩的特殊情况,针对Redis热点key全部过期了,导致大量的请求直接访问到MySQ中,引起数据库宕机

  • 基于统计的方式发现热点 key, 并设置永不过期.
  • 进行必要的服务降级. 例如访问数据库的时候使用分布式锁, 限制同时请求数据库的并发数.

分布式锁 

在一个分布式系统当中,会涉及到多个节点访问同一个公共资源的情况下,此时就需要通过“锁”来进行互斥,避免出现“线程安全”的问题;

像Java中的synchronized 这种锁只能在当前进程中生效,在分布式这种多个进程多个主机的场景下就不能使用了‘;

分布式锁的基本实现:

实现思路:通过设置一个键值对来标识锁的状态

举例买票的例子:

此时客户端1查询001车 还有1张车票 在即将执行1->0 过程前

客户端2也执行查询余票 发现还有一张,那么客户端2也执行1->0

那么这出现“超卖” 的情况,俩个人都买到票


加锁:

此时, 如果 买票服务器1 尝试买票, 就需要先访问 Redis, 在 Redis 上设置⼀个键值对. 比如 key 就是车次, value 随便设置个值 (比如 1).

        如果发现操作成功,那么就可以视为当前没有节点对001车次加锁,那么就可以进行数据库的读写,操作完成之后,就可以吧这个key删除(相当于解锁)

        如果服务器1在操作数据库时候,服务器2也想买票,那么它在给Redis新增key的时候,就会发现此时车次的key已经存在,就可以认为其他服务器此时正在持有锁,那么服务器2就可以等待或者放弃~

Redis中的setnx刚刚好就行对应此场景:当key不存在才可以创建成功,如果存在那么将失败 ~

此时如果某个服务器加锁成功,但意外发生了,服务器崩溃了没有执行解锁操作(删除操作),那么就导致其他服务器没有获取到锁;

引入过期时间:

可以设置key的过期时间,让这个锁持有多久,如果超过一定时间,那么将自动释放;

使用set ex nx 命令,在设置锁的同时加入过期时间;

注意这是一条命令

不能写成 setnx

                expire

此时是俩条命令,就有可能造成原子性,仍然会出现无法正确释放锁的问题


所谓的加锁就是在Redis上执行setnx生成一个key
解锁就是删除这个key

那么有没有可能会出现服务器1执行了加锁操作,而服务器2执行了解锁?
那么是有可能的

引入校验Id:

需要引入一点校验机制:

1.给服务器编号,每个服务器有一个自己的身份标识

2.进行加锁的时候,设置key-value 对应要针对的哪个资源加锁(比如车次),value存储刚才服务器的编号 例如“001:1” ->“001:服务器1”

这样就可以在删除key的时候,校验当前的key是否是当初加锁的服务器,避免删除错误~


在解锁的时候:
1.先查询判断是否删除 2. 才进行删除

此时这个是俩步操作,并不是原子的,就有可能出现问题

引入lua脚本:

很多程序里面都支持内嵌脚本语音.Redis支持Lua语音作为内嵌脚本~

if redis.call('get',KEYS[1]) == ARGV[1] then
return redis.call('del',KEYS[1])
else
1 2 3return 0
end;

过期时间续约问题可能存在,

在给key加锁的时候,设置它的过期时间,那么设置多久呢才是比较合适?

  • 设置时间短,那么可能在业务逻辑还没执行完,就释放锁了
  • 设置时间长,就可以导致锁释放不及时的可能

更好的是能够去进行“动态续约”

引入watch dog(看门狗)

本质上就是在加锁的服务器上的一个单独的线程,通过这个线程来对锁过期时间进行一个“续约”

❤ 举个具体的例子:

初始情况下设置过期时间为 10s. 同时设定看门狗线程每隔 3s 检测⼀次.

那么当 3s 时间到的时候, 看门狗就会判定当前任务是否完成.
  • 如果任务已经完成, 则直接通过 lua 脚本的方式, 释放锁(删除 key).
  • 如果任务未完成, 则把过期时间重写设置为 10s. (即 "续约")


使用Redis作为分布式锁,有没有可能Redis自身挂了? 

那么是很有可能的!!!

Redis一般是以集群(至少也是主从的形式,而不是单机)的方式去部署的

服务器1向它的master节点就行加锁操作,这个数据刚写入主节点,主节点挂了,从节点就会新的主节点

由于主节点和从节点之间的数据是同步的,但是有延迟

那么刚才写入的key还没有被新的主节点接收,此时相当于服务器1就没有成功进行加上锁

但是服务器2仍然可以进行去加上锁,

引入Redlock算法:

 由于主节点和主节点之间数据都是一致的,相互是备份的关系

在进行加锁的时候,会按照一定的顺序,针对这组Redis都进行加锁

如果某个节点加不上锁,并没有关系,可能是Redis挂了,继续给下一个节点加锁即可

如果此时key加锁成功的节点个数占总的一半,那么可视为加锁成功

同时解锁的时候,会把上述的节点都需要解锁~

简而言之, Redlock 算法的核心就是, 加锁操作不能只写给⼀个 Redis 节点, 而要写个多个!! 分布式系统中任何⼀个节点都是不可靠的. 最终的加锁成功结论是 "少数服从多数的".

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

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

相关文章

小阿卡纳牌

小阿卡纳牌 风:热湿 火:热干 水:冷湿 土:冷干 火风:温度相同,但是湿度不同,二人可能会在短期内十分热情,但是等待热情消退之后,会趋于平淡。 湿度相同、温度不同&#x…

初始JavaEE篇 —— Spring Web MVC入门(上)

找往期文章包括但不限于本期文章中不懂的知识点: 个人主页:我要学编程程(ಥ_ಥ)-CSDN博客 所属专栏:JavaEE 目录 RequestMappingg 注解介绍 Postman的介绍与使用 PostMapping 与 GetMapping 注解 构造并接收请求 接收简单参数 接收对象…

python -m pip和pip的主要区别

python -m pip和pip的主要区别在于它们与Python环境的关联方式和安装路径。‌ ‌与Python环境的关联方式‌: pip 是直接使用命令行工具来安装Python包,不指定特定的Python解释器。如果系统中存在多个Python版本,可能会导致安装的包被安装到…

golang通过AutoMigrate方法自动创建table详解

一.AutoMigrate介绍 1.介绍 在 Go 语言中,GORM支持Migration特性,支持根据Go Struct结构自动生成对应的表结构,使用 GORM ORM 库的 AutoMigrate 方法可以自动创建数据库表,确保数据库结构与定义的模型结构一致。AutoMigrate 方法非常方便&am…

SuperAGI - 构建、管理和运行 AI Agent

文章目录 一、关于 SuperAGI💡特点🛠 工具包 二、⚙️安装☁️SuperAGI云🖥️本地🌀 Digital Ocean 三、架构1、SuperAGI 架构2、代理架构3、代理工作流架构4、Tools 架构5、ER图 一、关于 SuperAGI SuperAGI 一个开发优先的开源…

CSAPP学习:前言

前言 本书简称CS:APP。 背景知识 一些基础的C语言知识 如何阅读 Do-做系统 在真正的系统上解决具体的问题,或是编写和运行程序。 章节 2025-1-27 个人认为如下章节将会对学习408中的操作系统与计算机组成原理提供帮助,于是先凭借记忆将其简单…

如何实现滑动删除功能

文章目录 1 概念介绍2 使用方法3 示例代码 我们在上一章回中介绍了GestureDetector Widget相关的内容,本章回中将介绍Dismissible Widget.闲话休提,让我们一起Talk Flutter吧。 1 概念介绍 我们在这里介绍的Dismissible是一个事件响应Widget,它和GestureDetector类…

【数据结构】_链表经典算法OJ:环形链表的约瑟夫问题

目录 1. 题目链接及描述 2. 解题思路 3. 程序 1. 题目链接及描述 题目链接:环形链表的约瑟夫问题_牛客题霸_牛客网 题目描述: 编号为 1 到 n 的 n 个人围成一圈。从编号为 1 的人开始报数,报到 m 的人离开。 下一个人继续从 1 开始报数…

装饰SpringMVC的适配器实现响应自动包装

文章目录 1.common-tool-starter1.目录结构2.ResultWrapper.java 2.common-web-starter1.目录结构2.IgnoredResultWrapper.java 自定义注解,忽略对返回结果的自动包装3.ReturnValueHandlersDecorator.java 对适配器进行扩展的装饰器4.WebAutoConfiguration.java 将装…

【PyQt5】数据库连接失败: Driver not loaded Driver not loaded

报错内容如下: 可以看到目前所支持的数据库驱动仅有[‘QSQLITE’, ‘QMARIADB’, ‘QODBC’, ‘QODBC3’, ‘QPSQL’, ‘QPSQL7’] 我在网上查找半天解决方法未果,其中有一篇看评论反馈是可以使用的,但是PyQt5的版本有点低,5.12…

论文笔记(六十三)Understanding Diffusion Models: A Unified Perspective(三)

Understanding Diffusion Models: A Unified Perspective(三) 文章概括 文章概括 引用: article{luo2022understanding,title{Understanding diffusion models: A unified perspective},author{Luo, Calvin},journal{arXiv preprint arXiv:…

【shell工具】编写一个批量扫描IP地址的shell脚本

批量扫描某个网段中的主机(并发) 创建目录编写脚本文件 mkdir /root/ip_scan_shell/ touch /root/ip_scan_shell/online_server.txt touch /root/ip_scan_shell/offline_server.txt touch /root/ip_scan_shell/ip_scan.sh写入下面shell到脚本文件中…

穷举vs暴搜vs深搜vs回溯vs剪枝系列一>解数独

题目: 解析: 部分决策树: 代码设计&剪枝&回溯: 代码: class Solution {private boolean[][] row, col;private boolean[][][] gird; public void solveSudoku(char[][] board) {//下标->数字&#xff…

[EAI-023] FAST: Efficient Action Tokenization for Vision-Language-Action Models

Paper Card 论文标题:FAST: Efficient Action Tokenization for Vision-Language-Action Models 论文作者:Karl Pertsch, Kyle Stachowicz, Brian Ichter, Danny Driess, Suraj Nair, Quan Vuong, Oier Mees, Chelsea Finn, Sergey Levine 论文链接&…

人工智能学习框架:深入解析与实战指南

📝个人主页🌹:一ge科研小菜鸡-CSDN博客 🌹🌹期待您的关注 🌹🌹 引言 随着人工智能(AI)技术的飞速发展,深度学习、强化学习和自然语言处理等领域的应用愈加广…

数据结构(树)

每一个节点包含&#xff1a;父节点地址 值 左子节点地址 右子节点地址 如果一个节点不含有&#xff1a;父节点地址或左子节点地址 右子节点地址就记为null 二叉树 度&#xff1a;每一个节点的子节点数量 二叉树中&#xff0c;任意节点的度<2 树的结构&#xff1a; 二叉查…

TikTok 推出了一款 IDE,用于快速构建 AI 应用

字节跳动(TikTok 的母公司)刚刚推出了一款名为 Trae 的新集成开发环境(IDE)。 Trae 基于 Visual Studio Code(VS Code)构建,继承了这个熟悉的平台,并加入了 AI 工具,帮助开发者更快、更轻松地构建应用——有时甚至无需编写任何代码。 如果你之前使用过 Cursor AI,T…

2025多目标优化创新路径汇总

多目标优化是当下非常热门且有前景的方向&#xff01;作为AI领域的核心技术之一&#xff0c;其专注于解决多个相互冲突的目标的协同优化问题&#xff0c;核心理念是寻找一组“不完美但均衡”的“帕累托最优解”。在实际中&#xff0c;几乎处处都有它的身影。 但随着需求场景的…

项目升级Sass版本或升级Element Plus版本遇到的问题

项目升级Sass版本或升级Element Plus版本遇到的问题 如果项目有需求需要用到高版本的Element Plus组件&#xff0c;则需要升级相对应的sass版本&#xff0c;Element 文档中有提示&#xff0c;2.8.5及以后得版本&#xff0c;sass最低支持的版本为1.79.0&#xff0c;所升级sass、…

机器学习第一道菜(二):玩转最小二乘法

机器学习第一道菜&#xff08;二&#xff09;&#xff1a;玩转最小二乘法 一、线性函数表达式1.1 函数表达式 y y y1.2 函数表达式 f θ ( x ) f_\theta(x) fθ​(x)1.3 最小误差 二、最小二乘法&#xff1a;数据拟合大师2.1 概念及其历史背景2.2 拟合优势2.3 数学表达式2.3.1 …