Redis核心机制-缓存、分布式锁

目录

缓存

缓存更新策略

定期生成

实时生成

缓存问题

缓存预热(Cache preheating)

缓存穿透(Cache penetration)

缓存雪崩(Cache avalanche)

缓存击穿(Cache breakdown)

分布式锁

分布式锁基础实现

引入过期时间

引入校验id

引入lua脚本

引入watch dog(看门狗)

引入Redlock算法


缓存

缓存的核心思路就是把常用的数据放入访问速度更快的地方,方便随时读取。使用Redis作为缓存,数据是直接存储在内存上的,对于关系型数据库例如MySql来说速度更快。

为什么说关系型数据库性能不高?

1.数据库将数据存储在硬盘上,硬盘的IO速度没有内存快。

2.如果查询不能命中索引,就需要进行表的遍历,这就会大大增加硬盘IO次数。

3.关系型数据库会对SQL的执行做一系列的解析,校验,优化工作。

4.复杂查询更加消耗效率。(笛卡尔积)

 如果全部请求直接访问数据库,对于数据库压力很大,很容易使数据库服务器宕机。使用Redis缓存可以加快读操作,写操作还是得写在数据库中。

缓存更新策略

定期生成

每隔一定时间,对访问数据频次较高的数据进行统计,挑选出访问频次最高的前N%的数据,导入到Redis中。实时性比较低,面对突发情况不友好。如春节期间,“春节”的搜索频率变高,在平时搜索频率比较低。

实时生成

用户查询数据,如果没有在Redis中命中,就在数据库中查询,然后将结果更新到Redis中。如果Redis缓存满了,就可以使用内存淘汰策略进行删除:

FIFO(First In First Out)先进先出

将缓存中存在时间最久的数据淘汰。

LRU(Least Recently Used)淘汰最久未使用的

记录每个key的最近访问时间,把最近访问时间最老的key淘汰。

LFU(淘汰访问次数最少的)

记录每个key最近一段时间的访问次数,淘汰访问次数最少得到。

Random随机淘汰

随机淘汰缓存中的key。

缓存问题

缓存预热(Cache preheating)

刚刚启动Redis作为MySQL缓存时,Redis自身为空,所有请求都会直接直接访问数据库,从而对数据库造成很大的压力。

提前准备热点数据导入Redis中,使Redis更快提供服务,解决缓存预热问题。

缓存穿透(Cache penetration)

访问的key在Redis和MySQL中都不存在,此时key不会放入缓存中,后续如果接着访问这个key,依然会访问到数据库。这样会给数据库造成压力。

针对查询的key进行校验,如要查询的key为手机号,首先对key的格式进行校验。

针对数据库不存在的key也放入redis中。

使用布隆过滤器,判定key是否存在。

缓存雪崩(Cache avalanche)

短时间内,大量的key失效(Redis挂了/大量key同时过期),导致数据库压力增大。

部署高可用的Redis系统,完善监控报警体系。

不给key设置过期时间,或者设置过期时间时加入随机因子。

缓存击穿(Cache breakdown)

热点key突然过期,大量请求直接访问MySQL数据库。

将这些热点key设置为永不过期。

分布式锁

分布式系统中,当不同节点访问统一资源时,就需要通过锁进行互斥控制,避免出现类似“线程 安全”问题。在分布式这种多进程,多主机的的场景中,就需要有一台服务器进行记录加锁操作。

分布式锁基础实现

使用Redis实现分布式锁,本质上就是通过设置一个键值对,然后通过键值对来判定是否已有其他进程加锁。

例如在网上买票的时候,车站提供了多个服务器处理买票的请求,客户端每次买票需要查询车票数量,判断车票数量是否大于1,满足条件车票数量减一。在高并发情况下,可能会导致超卖情况,此时引入分布式锁。

此时服务器对数据库进行操作时,就会先判断Redis中是否有加锁的键值对,Redis中的key就可以代表车次,表示该车次的票正在其他进程中进行操作。Redis中提供了setnx操作,当key设置成功,则代表加锁成功,反之就代表已经有其他进程进行加锁了。设置成功后,就可以对数据库进行读写操作了,操作完成之后再把Redis上刚刚的key进行删除。

但是这个方案并不完整,当加锁的进程在执行删除key操作之前遇到问题(如宕机),此时删除操作不能进行,其他进程也不能获取锁

引入过期时间

为解决加锁后加锁进程意外宕机的情况,在设置key时顺便设置过期时间,表示进程持有锁的最大时间,达到时间后就会自动删除key,使用set ex nx命令进行设置,不能分开设置,由于Redis事务不能保证两个操作都能成功执行,可能就会出现set nx操作成功,但是expire失败的情况。此时任然会出现无法正确释放锁的问题。

但是仍然存在问题,其他进程也可以操作Redis删除key,此时加锁就失去了意义

引入校验id

为解决其他进程删除key,引入校验机制,在设置键值对时,value设置为可以识别加锁服务器的身份。在执行解锁操作时,先根据value判断是否为加锁的服务器。该逻辑用伪代码表示:

String key = "要加锁的资源id";
String serverId = "服务器的编号";
//加锁,设置过期时间为10s
redis.set(key,serverId,"NX","EX","10s");
//执行各种逻辑,如数据库的增删查改
select();
update();
delete();
insert();
//解锁,先判断是否为加锁进程
if(redis.get(key) == serverId) {redis.del(key);
}

在执行解锁操作时,解锁的逻辑是分为两步的,不是原子操作。一个服务器内部,可能是多线程的,同一个服务器内部,两个线程都在执行解锁操作,就可能导致del操作被重复执行,然后将其他加锁线程的锁给删除了。

引入lua脚本

 为了使解锁操作变为原子的,使用Redis支持的lua脚本,将查询和删除操作打包为原子操作,可以将上述代码编写成一个.lua后缀的文件,一个lua脚本会被Redis服务器以原子的方式进行执行。

引入watch dog(看门狗)

设置key过期时间后,任然存在当前任务没有执行完,key就过期了的情况,导致锁提前失效。引入watch dog,本质上是加锁的服务器上一个单独的线程,通过这个线程来对锁的过期时间进行“续约”。这个线程并不是Redis提供,而是业务服务器上的线程。

假设设置一个key,过期时间为10s,设定看门狗线程没3s检测一次。

当3s时间到的时候,看门狗就会判定当前任务是否完成。

如果完成,可通过lua脚本直接释放锁。

未完成,则将过期时间重新设置为10s(续约)。

这样就不用担心锁提前失效的问题。如果该服务器挂了,那么看门狗线程也随之挂了,没人给锁续约,到达过期时间后key就会过期,让其他服务器能够获取锁。

引入Redlock算法

 实践中Redis一般是以集群的方式部署的(至少是主从结构),Redis成为分布式锁可能会遇到一些极端情况:负责加锁的master节点刚刚进行加锁操作,然后就挂了,此时slave节点成了新的master节点,由于此时的key并没有同步给slave节点,导致加锁操作形同虚设。

解决办法:引入一组Redis节点,每一组Redis节点都包含master节点和slave节点,组与组之间的数据都是一致的,相互之间为“备份”关系。在进行加锁操作时,设置加锁操作的超时时间,比如设置为30ms,超过30ms没有加锁,则视为加锁失败。如果当前节点加锁失败。就立即尝试下一个节点,当加锁成功的节点超过总结点的一半,则视为加锁成功。即使某些节点挂了也不会影响锁的正确性。

文章结束,感谢观看! 

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

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

相关文章

CF每日5题(1300-1500)

最近急速补练蓝桥杯中,疏于cf练习。 感觉自己过题还是太慢了。 今日水题,我水水水水。 1- 1979C lcm 水 1400 第 i i i局赢了,1个硬币顶 k [ i ] k[i] k[i]个贡献,所以每局分硬币 x i 1 k [ i ] x_i{1\over k[i]} xi​k[i]1​个…

从代码学习深度学习 - LSTM PyTorch版

文章目录 前言一、数据加载与预处理1.1 代码实现1.2 功能解析二、LSTM介绍2.1 LSTM原理2.2 模型定义代码解析三、训练与预测3.1 训练逻辑代码解析3.2 可视化工具功能解析功能结果总结前言 深度学习中的循环神经网络(RNN)及其变种长短期记忆网络(LSTM)在处理序列数据(如文…

easy-poi 一对多导出

1. 需求: 某一列上下两行单元格A,B值一样且这两个单元格, 前面所有列对应单元格值一样的话, 就对A,B 两个单元格进行纵向合并单元格 1. 核心思路: 先对数据集的国家,省份,城市...... id 身份证进行排序…

AI比人脑更强,因为被植入思维模型【42】思维投影思维模型

giszz的理解:本质和外在。我们的行为举止,都是我们的内心的表现。从外边可以看内心,从内心可以判断外在。曾国藩有7个识人的方法,大部分的人在他的面前如同没穿衣服一样。对于我们自身的启迪,我认为有四点&…

Spring Boot 打印日志

1.通过slf4j包中的logger对象打印日志 Spring Boot内置了日志框架slf4j,在程序中调用slf4j来输出日志 通过创建logger对象打印日志,Logger 对象是属于 org.slf4j 包下的不要导错包。 2.日志级别 日志级别从高到低依次为: FATAL:致命信息,表…

【IOS webview】源代码映射错误,页面卡住不动

报错场景 safari页面报源代码映射错误,页面卡住不动。 机型:IOS13 技术栈:react 其他IOS也会报错,但不影响页面显示。 debug webpack配置不要GENERATE_SOURCEMAP。 解决方法: GENERATE_SOURCEMAPfalse react-app…

ES中经纬度查询geo_point

0. ES版本 6.x版本 1. 创建索引 PUT /location {"settings": {"number_of_shards": 1,"number_of_replicas": 0},"mappings": {"location": {"properties": {"id": {"type": "keywor…

OpenCV界面编程

《OpenCV计算机视觉开发实践:基于Python(人工智能技术丛书)》(朱文伟,李建英)【摘要 书评 试读】- 京东图书 OpenCV的Python开发环境搭建(Windows)-CSDN博客 OpenCV也支持有限的界面编程,主要是针对窗口、控件和鼠标…

GOC L2 第五课模运算和周期二

课堂回顾: 求取余数的过程叫做模运算 每轮的动作都是重复的,我们称这个过程位周期。 课堂学习: 剩余计算器 秋天到了,学校里的苹果熟了,太乙老师,想让哪吒帮忙设计一个计算器,看每个小朋友能分…

54.大学生心理健康管理系统(基于springboot项目)

目录 1.系统的受众说明 2.相关技术 2.1 B/S结构 2.2 MySQL数据库 3.系统分析 3.1可行性分析 3.1.1时间可行性 3.1.2 经济可行性 3.1.3 操作可行性 3.1.4 技术可行性 3.1.5 法律可行性 3.2系统流程分析 3.3系统功能需求分析 3.4 系统非功能需求分析 4.系统设计…

Redis 除了数据类型外的核心功能 的详细说明,包含事务、流水线、发布/订阅、Lua 脚本的完整代码示例和表格总结

以下是 Redis 除了数据类型外的核心功能 的详细说明,包含事务、流水线、发布/订阅、Lua 脚本的完整代码示例和表格总结: 1. Redis 事务(Transactions) 功能描述 事务通过 MULTI 和 EXEC 命令将一组命令打包执行,保证…

STM32F103C8T6单片机硬核原理篇:讨论GPIO的基本原理篇章1——只讨论我们的GPIO简单输入和输出

目录 前言 输出时的GPIO控制部分 标准库是如何操作寄存器完成GPIO驱动的初始化的? 问题1:如何掌握GPIO的编程细节——跟寄存器如何打交道 问题2:哪些寄存器,去哪里找呢? 问题三,寄存器的含义&#xff…

前端布局难题:父元素padding导致子元素无法全屏?3种解决方案

大家好,我是一诺。今天要跟大家分享一个我在实际项目中经常用到的CSS技巧——如何让子元素突破父元素的padding限制,实现真正的全屏宽度效果。 为什么会有这个需求? 记得我刚入行的时候,接到一个需求:要在内容区插入…

当网页受到DDOS网络攻击有哪些应对方法?

分布式拒绝服务攻击也是人们较为熟悉的DDOS攻击,这类攻击会通过大量受控制的僵尸网络向目标服务器发送请求,以此来消耗服务器中的资源,致使用户无法正常访问,当网页受到分布式拒绝服务攻击时都有哪些应对方法呢? 建立全…

LeNet-5简介及matlab实现

文章目录 一、LeNet-5网络结构简介二、LeNet-5每一层的实现原理2.1. 第一层 (C1) :卷积层(Convolution Layer)2.2. 第二层 (S2) :池化层(Pooling Layer)2.3. 第三层(C3):…

【LLM】MCP(Python):实现 stdio 通信的Client与Server

本文将详细介绍如何使用 Model Context Protocol (MCP) 在 Python 中实现基于 STDIO 通信的 Client 与 Server。MCP 是一个开放协议,它使 LLM 应用与外部数据源和工具之间的无缝集成成为可能。无论你是构建 AI 驱动的 IDE、改善 chat 交互,还是构建自定义…

Docker 安装 Elasticsearch 教程

目录 一、安装 Elasticsearch 二、安装 Kibana 三、安装 IK 分词器 四、Elasticsearch 常用配置 五、Elasticsearch 常用命令 一、安装 Elasticsearch (一)创建 Docker 网络 因为后续还需要部署 Kibana 容器,所以需要让 Elasticsearch…

Swagger @ApiOperation

ApiOperation 注解并非 Spring Boot 自带的注解,而是来自 Swagger 框架,Swagger 是一个规范且完整的框架,用于生成、描述、调用和可视化 RESTful 风格的 Web 服务,而 ApiOperation 主要用于为 API 接口的操作添加描述信息。以下为…

【奇点时刻】GPT4o新图像生成模型底层原理深度洞察报告(篇2)

由于上一篇解析深度不足,经过查看学习相关论文,以下是一份对 GPT-4o 最新的图像生成模型 的深度梳理与洞察,从模型原理到社区解读、对比传统扩散模型,再到对未来趋势的分析。为了便于阅读,整理成以下七个部分&#xff…

C# 窗体应用(.FET Framework ) 打开文件操作

一、 打开文件或文件夹加载数据 1. 定义一个列表用来接收路径 public List<string> paths new List<string>();2. 打开文件选择一个文件并将文件放入列表中 OpenFileDialog open new OpenFileDialog(); // 过滤 open.Filter "(*.jpg;*.jpge;*.bmp;*.png…