Redis最终篇分布式锁以及数据一致性

  在前三篇我们几乎说完了Redis的所有的基础知识以及Redis怎么实现高可用性,那么在这一篇文章中的话我们主要就是说明如果我们使用Redis出现什么问题以及解决方案是什么,这个如果在未来的工作中也有可能会遇到,希望对看这篇博客的人有帮助,话不多说直接开干

一.Hotkey以及BigKey

 Hotkey:

   HotKey就是说在一段时间范围之内的访问频率特别高,所以我们常说缓存击穿的问题(不清楚的话可以看Redis持久化策略以及三大缓存问题-CSDN博客)的话几乎就是因为Hotkey所导致的问题常见的场景: 热点新闻 判断是否为Hotkey就是根据访问频率 发现的途径:1.会有第三方监控平台进行监控 2.就是使用命令   3.就是使用二级缓存也就是说JVM的缓存(Caffine)   如果实在不行的话那么就会搭建集群

//这个就能展现出所有的key的访问的次数
redis-cli -p 6379 --hotkeys

Bigkey:

     BigKey就是说以string为数据类型的话那么就是说value的值占用的空间超过512M那么或者如果是Zset数据类型的话那么就是说value的数目过多,所以的话Bigkey占用的内存空间就是特别大,那么我们都知道Redis是基于内存那么如果出现BigKey肯定对其中的一些方面产生一些影响:如AOF文件的重写因为AOF重写的话是需要进行写时复制的那么占用内存更大以及生成的RDB数据快照的话生成的文件也是比较大等等如果不知道AOF以及RDB的话那么可以看我的Hotkey的那个博客      解决方案: 1.可以将Bigkey进行拆分若干个smallKey 2.如果想要删除的话那么要进行异步以及批量进行删除

 

二.怎么保证数据库和缓存数据的一致性问题

 对于数据一致性问题的话这个是一个非常常见的问题除了这个场景的话还有就是Mysql进行读写分离的时候肯定也会遇到怎么保证主数据库和从数据库之间的数据一致性的问题,所以这个问题也是比较头疼的但是这个有一个特别的说明: 就是没有系统可以保证数据的实时的一致性,所以有一段时间的数据不一致的话那么是可以接受的 

解决方案: cannel+旁路缓存cannel中间件的话其实就是为了监听Mysql的binlog日志,因为如果数据库里面的数据发生变化的话那么binnlog日志里面的数据肯定也会发生变化那么这个时候我们的cannel中间件监听到之后这个时候就会告诉我们客户端然后就会对缓存中的数据进行一个删除的操作  旁路缓存: 这个就是说要从读以及写的方面进行说明:

读角度: 读的话那么客户端请求的时候肯定是从缓存中进行数据的读取如果缓存中没有的话那么肯定是从数据库中进行数据的读取那么除了读之外的话就会将读取的数据加载到缓存中 注意: 从缓存中读取数据的时候要先获得分布式锁 

写角度: 当进行数据修改的时候我们是先修改数据库当中的数据然后再删除缓存中的数据,那么这个时候就是又会有问题: 1.为什么不是修改缓存中的数据而是删除 2.为什么不是先改变缓存中的数据而是先改变数据库当中的数据  对于第一个问题:因为对于修改操作的话那么会有一定的时序性(有可能就是因为网络的问题导致修改和预期的结果不一致)而且删除更加轻量级

对于第二个问题:因为先修改(删除)缓存数据的话如果在修改数据库的时候出现网络问题导致修改数据库失败那么后面的请求就会读到旧的数据而且缓存中的数据就是以数据库的数据为根本所以肯定是先修改数据库中的数据

三.Redis分布式锁的应用以及实现原理

  对于分布式锁的话其实一点都不陌生如:我们常听的秒杀或者防止超卖的场景,但是对于分布锁很多人只是停留在理论的基础之上以及只知道这个概念但是不知道分布式锁的底层原理如怎么实现互斥性以及实现可重入性的下面的就会进行说明

 首先我们先说Redis分布式锁的实现方式: 首先我们肯定就是想到的就是原生锁

// NX 表示只有当键不存在时才设置键,EX 设置键的过期时间 这个主要就是为了解决死锁问题
SET RedislockName NX EX second

但是我们都知道如果设置过期时间的话那么如果到了过期时间的话但是我的线程执行的业务逻辑还没有执行完成这个时候如果释放锁的话那么就会产生巨大的问题,所以后来的话我们就使用Redission分布式锁

Redisson分布式锁:

 优点:这个相对于原生锁的话就是添加了一个看门狗(watchDog)机制也就是说会自动续约,这个看门狗机制就是说默认的条件下就是每隔10s就会检查key是否要过期了如果要过期的话那么就会进行续约,但是这个的话就是会有一个疑问: 假如我续约完成之后由于一些原因导致线程暂停那么这个时候不是会一直进行续约吗那么这个不就会产生一定的问题 回答: 会有一个心跳的检测功能,如果发生心跳在一段时间范围之内没有接收到回应的话那么就会自动释放分布式锁

实现步骤以及应用:
1.引入相关的依赖
<dependency>
    <groupId>org.redisson</groupId>
    <artifactId>redisson</artifactId>
    <version>2.7.0</version>
</dependency>
2.进行配置redisclient:
@Configuration
@Slf4j
public class redisConfig {
    private static final Logger logger = LoggerFactory.getLogger(redisConfig.class);

    @Bean
    public RedissonClient createClient() {
            Config config = new Config();
            config.useSingleServer()
                    .setAddress("redis://127.0.0.1:6379")
                            .setDatabase(4);
            return Redisson.create(config);
        }
3.获得以及释放锁实现相关的业务逻辑

线程实现的业务逻辑代码:

3.1. 在获得锁的时候添加持有锁的的参数(方案1)

 public void run() {
        RLock lock = redissonClient.getLock("lockName");
        boolean isLock = false;
        try {
            //3就是代表最多等待获得锁的时间
            //2就是代表的就是持有锁的时间
            isLock = lock.tryLock(3,2,TimeUnit.SECONDS); 
            if (isLock) {
                System.out.println("线程 " + threadId + " 获取到了锁");
                // 模拟业务逻辑
                System.out.println("线程 " + threadId + " 执行业务逻辑...");
                Thread.sleep(2000); // 模拟长时间的业务处理
            } else {
                System.out.println("线程 " + threadId + " 未能获取到锁");
            }
        } catch (InterruptedException e) {
            System.err.println("线程 " + threadId + " 被中断");
        } finally {
            // 释放锁
            if (isLock) {
                lock.unlock();
                System.out.println("线程 " + threadId + " 释放了锁");
            }
        }
    }

3.1.2.线程进行trylock的时候不添加持有锁的时间(方案2)

  isLock = lock.tryLock(3,TimeUnit.SECONDS); 

3.2.测试代码

3.3.测试结果

方案1:


 

不难看出来这个是会报错的这个错误的意思就是说 当一个线程试图解锁它没有锁住的对象时抛出的异常 那么就说明锁已经释放了并且被别的线程获得了那么看门狗机制不生效了

Exception in thread "Thread-13" java.lang.IllegalMonitorStateException: attempt to unlock lock, not locked by current thread by node id: eec734cc-03c5-4879-adf6-f981e58c0809 thread-id: 89

方案2:

这个和方案1不一样那么就说明看门狗机制,因为线程4获得锁之后业务逻辑没有执行完成那么这个时候不会自动释放锁的因为其他获得线程等待时间到了之后就获得不了锁了

特别说明: 使用分布式锁的中trylock方法的时候不要添加持有锁的时间

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

湘潭大学人工智能考试复习1(软件工程)

今年的试卷分值分布为&#xff1a; 选填40&#xff0c;两道计算题15x2 两道解答题15x2 复习重点&#xff1a; 1.人工智能学派派别 符号主义学派、连接主义学派、行为主义学派 各学派认知观&#xff1a; 符号主义&#xff08;逻辑主义、心理学派、计算机学派&#xff09;&am…

【蓝桥杯C/C++】深入解析I/O高效性能优化:std::ios::sync_with_stdio(false)

博客主页&#xff1a; [小ᶻZ࿆] 本文专栏: 蓝桥杯C/C 文章目录 &#x1f4af;前言&#x1f4af;C 语言与 C 语言的输入输出对比1.1 C 语言的输入输出1.2 C 语言的输入输出 &#x1f4af; std::ios::sync_with_stdio(false) 的作用与意义2.1 什么是 std::ios::sync_with_st…

GPT1.0 和 GPT2.0 的联系与区别

随着自然语言处理技术的飞速发展&#xff0c;OpenAI 提出的 GPT 系列模型成为了生成式预训练模型的代表。作为 GPT 系列的两代代表&#xff0c;GPT-1 和 GPT-2 虽然在架构上有着继承关系&#xff0c;但在设计理念和性能上有显著的改进。本文将从模型架构、参数规模、训练数据和…

嵌入式系统与OpenCV

目录 一、OpenCV 简介 二、嵌入式 OpenCV 的安装方法 1. Ubuntu 系统下的安装 2. 嵌入式 ARM 系统中的安装 3. Windows10 和树莓派系统下的安装 三、嵌入式 OpenCV 的性能优化 1. 介绍嵌入式平台上对 OpenCV 进行优化的必要性。 2. 利用嵌入式开发工具&#xff0c;如优…

戴尔 AI Factory 上的 Agentic RAG 搭载 NVIDIA 和 Elasticsearch 向量数据库

作者&#xff1a;来自 Elastic Hemant Malik, Dell Team 我们很高兴与戴尔合作撰写白皮书《戴尔 AI Factory with NVIDIA 上的 Agentic RAG》。白皮书是一份供开发人员参考的设计文档&#xff0c;概述了实施 Agentic 检索增强生成 (retrieval augmented generation - RAG) 应用…

特征交叉-MaskNet文章总结代码实现

MaskNet 这个模型是微博21年提出的&#xff0c;23年twitter(X)开源的推荐系统排序模块使用的backbone结构。 核心思想是认为DNN为主的特征交叉是addictive&#xff0c;交叉效率不高&#xff1b;所以设计了一种multiplicatvie的特征交叉 如何设计muliplicative特征交叉呢&#x…

GRU (门控循环单元 - 基于RNN - 简化LSTM又快又好 - 体现注意力的思想) + 代码实现 —— 笔记3.5《动手学深度学习》

目录 0. 前言 1. 门控隐状态 1.1 重置门和更新门 1.2 候选隐状态 1.3 隐状态 2. 从零开始实现 2.1 初始化模型参数 2.2 定义模型 2.3 训练与预测 3 简洁实现 4. 小结 0. 前言 课程全部代码&#xff08;pytorch版&#xff09;已上传到附件看懂上一篇RNN的所有细节&am…

Java 基于SpringBoot+vue框架的老年医疗保健网站

大家好&#xff0c;我是Java徐师兄&#xff0c;今天为大家带来的是Java Java 基于SpringBootvue框架的老年医疗保健网站。该系统采用 Java 语言开发&#xff0c;SpringBoot 框架&#xff0c;MySql 作为数据库&#xff0c;系统功能完善 &#xff0c;实用性强 &#xff0c;可供大…

JavaWeb-表单-07

表单标签 介绍 code: <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"> <meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>HTML-表单</title> &…

计算机网络socket编程(4)_TCP socket API 详解

个人主页&#xff1a;C忠实粉丝 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 C忠实粉丝 原创 计算机网络socket编程(4)_TCP socket API 详解 收录于专栏【计算机网络】 本专栏旨在分享学习计算机网络的一点学习笔记&#xff0c;欢迎大家在评论区交流讨论&…

向量数据库FAISS之五:原理(LSH、PQ、HNSW、IVF)

1.Locality Sensitive Hashing (LSH) 使用 Shingling MinHashing 进行查找 左侧是字典&#xff0c;右侧是 LSH。目的是把足够相似的索引放在同一个桶内。 LSH 有很多的版本&#xff0c;很灵活&#xff0c;这里先介绍第一个版本&#xff0c;也是原始版本 Shingling one-hot …

Django启用国际化支持(2)—实现界面内切换语言:activate()

文章目录 ⭐注意⭐1. 配置项目全局设置&#xff1a;启用国际化2. 编写视图函数3. 配置路由4. 界面演示5、扩展自动识别并切换到当前语言设置语言并保存到Session设置语言并保存到 Cookie ⭐注意⭐ 以下操作依赖于 Django 项目的国际化支持。如果你不清楚如何启用国际化功能&am…

【初阶数据结构与算法】线性表之栈的定义与实现(含源码和有效的括号练习)

文章目录 一、栈的概念与结构1.栈的概念与操作2.栈的底层结构选型 二、栈的实现1.栈结构的定义2. 栈的初始化和销毁栈的初始化栈的销毁 3.栈的扩容与入栈栈的扩容入栈 4.判断栈是否为空和出栈判断栈是否为空出栈 5.取栈顶元素和获取栈中有效元素个数取栈顶元素获取栈中有效元素…

基于Spring Boot+Unipp的博物馆预约小程序(协同过滤算法、二维码识别)【原创】

&#x1f388;系统亮点&#xff1a;协同过滤算法、二维码识别&#xff1b; 一.系统开发工具与环境搭建 1.系统设计开发工具 后端使用Java编程语言的Spring boot框架 项目架构&#xff1a;B/S架构 运行环境&#xff1a;win10/win11、jdk17 前端&#xff1a; 技术&#xff1a;框…

Python 快速入门(上篇)❖ Python基础知识

Python 基础知识 Python安装**运行第一个程序:基本数据类型算术运算符变量赋值操作符转义符获取用户输入综合案例:简单计算器实现Python安装** Linux安装: yum install python36 -y或者编译安装指定版本:https://www.python.org/downloads/source/ wget https://www.pyt…

【MyBatisPlus·最新教程】包含多个改造案例,常用注解、条件构造器、代码生成、静态工具、类型处理器、分页插件、自动填充字段

文章目录 一、MyBatis-Plus简介二、快速入门1、环境准备2、将mybatis项目改造成mybatis-plus项目&#xff08;1&#xff09;引入MybatisPlus依赖&#xff0c;代替MyBatis依赖&#xff08;2&#xff09;配置Mapper包扫描路径&#xff08;3&#xff09;定义Mapper接口并继承BaseM…

【人工智能】PyTorch、TensorFlow 和 Keras 全面解析与对比:深度学习框架的终极指南

文章目录 PyTorch 全面解析2.1 PyTorch 的发展历程2.2 PyTorch 的核心特点2.3 PyTorch 的应用场景 TensorFlow 全面解析3.1 TensorFlow 的发展历程3.2 TensorFlow 的核心特点3.3 TensorFlow 的应用场景 Keras 全面解析4.1 Keras 的发展历程4.2 Keras 的核心特点4.3 Keras 的应用…

Chrome 浏览器 131 版本新特性

Chrome 浏览器 131 版本新特性 一、Chrome 浏览器 131 版本更新 1. 在 iOS 上使用 Google Lens 搜索 自 Chrome 126 版本以来&#xff0c;用户可以通过 Google Lens 搜索屏幕上看到的任何图片或文字。 要使用此功能&#xff0c;请访问网站&#xff0c;并点击聚焦时出现在地…

2.不同语音ai任务dataset类写法

主流语音任务 语音数据读取基本原则 直接保存语音会将该对象保存在内存中&#xff08;Dataset类调用__getitem__方法&#xff09; 所以一般保存这些数据的存储路径文档&#xff08;表单&#xff09;而不是数据的直接copy&#xff08;不然占用内存太大了&#xff09; 通常用nump…

K8S + Jenkins 做CICD

前言 这里会做整体CICD的思路和流程的介绍&#xff0c;会给出核心的Jenkins pipeline脚本&#xff0c;最后会演示一下 实验/实操 结果 由于整体内容较多&#xff0c;所以不打算在这里做每一步的详细演示 - 本文仅作自己的实操记录和日后回顾用 要看保姆式教学的可以划走了&…