缓存与分布式锁

news2024/11/15 7:22:40

一、缓存

1、缓存使用

        为了系统性能的提升,我们一般都会将部分数据放入缓存中,加速访问。

        适合放入缓存的数据有:

                即时性、数据一致性要求不高的;访问量大且更新频率不高的数据。

        在开发中,凡是放入缓存中的数据我们都应该指定过期时间,使其可以在系统即使没有主动更新数据也能自动触发数据加载进缓存的流程。避免业务崩溃导致的数据永久不一致问题。

2、使用redis作为缓存

 引入依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

配置文件

spring:
    redis:
        host: 192.168.56.10
        port: 6379

使用RedisTemplate操作redis 

@Autowired
StringRedisTemplate stringRedisTemplate;

@Test
public void testStringRedisTemplate(){
    ValueOperations<String, String> ops = stringRedisTemplate.opsForValue();
    ops.set("hello","world_"+ UUID.randomUUID().toString());
    String hello = ops.get("hello");
    System.out.println(hello);
}

二、缓存失效问题

1、缓存穿透

        缓存穿透是指查询一个一定不存在的数据,由于缓存是不命中,将去查询数据库,但是数 据库也无此记录,我们没有将这次查询的 null 写入缓存,这将导致这个不存在的数据每次 请求都要到存储层去查询,失去了缓存的意义。

        在流量大时,可能 DB 就挂掉了,要是有人利用不存在的 key 频繁攻击我们的应用,这就是 漏洞。

        解决: 缓存空结果、并且设置短的过期时间。

2、缓存雪崩

        缓存雪崩是指在我们设置缓存时采用了相同的过期时间,导致缓存在某一时刻同时失效,请求全部转发到 DB,DB 瞬时压力过重雪崩。

        解决: 原有的失效时间基础上增加一个随机值,比如 1-5 分钟随机,这样每一个缓存的过期时间的 重复率就会降低,就很难引发集体失效的事件。

3、缓存击穿

        对于一些设置了过期时间的 key,如果这些 key 可能会在某些时间点被超高并发地访问, 是一种非常“热点”的数据。 这个时候,需要考虑一个问题:如果这个 key 在大量请求同时进来前正好失效,那么所 有对这个 key 的数据查询都落到 db,我们称为缓存击穿。

        解决: 加锁。缓存不存在时。在查询数据库前先获取锁,在得到锁后,再次确认缓存是否存在,不存在则查询数据库并更新缓存。

三、缓存数据的一致性

1、保证一致性

双写模式

失效模式

读写锁

读数据等待写数据整个操作完成。

四、分布式锁

1、分布式锁与本地锁

本地锁只能锁住当前进程,在分布式情况下,有多少个服务就会产生几把锁。

2、分布式锁实现

public Map<String, List<Catelog2Vo>> getCatalogJsonFromDBWithRedisLock() {

        //1、占用分布式锁 锁和过期时间一起设置  原子性操作
        String uuid = UUID.randomUUID().toString();
        Boolean lock = redisTemplate.opsForValue().setIfAbsent("lock", uuid, 300, TimeUnit.SECONDS); //锁设置的时间很长,防止业务执行期间锁过期  todo 自动续锁
        if (lock) { //加锁成功
            System.out.println("获取分布式锁成功");
            //设置过期时间, 必须和加锁是原子性操作
            //redisTemplate.expire("lock", 30, TimeUnit.SECONDS);
            Map<String, List<Catelog2Vo>> lockThenDo = null;
            try {
                lockThenDo = getLockThenDo();
            } finally {
                //lua 脚本解锁
                String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
                redisTemplate.execute(new DefaultRedisScript<Long>(script, Long.class), Collections.singletonList("lock"), uuid);
            }

            //解锁,不能随便删除别人的锁
            //两步:获取值对比, 对比成功删除    一定要是原子性
//            redisTemplate.delete("lock");
//            String uuidString = redisTemplate.opsForValue().get("lock");
//            if (uuid.equalsIgnoreCase(uuidString)) {
//                //删除自己的锁
//                redisTemplate.delete("lock");
//            }

            return lockThenDo;
        } else {
            //加锁失败重试  自旋的方式
            //可以设置休眠 后重试
            System.out.println("获取分布式锁不成功,等待重试。。。。");
            try {
                Thread.sleep(200);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return getCatalogJsonFromDBWithRedisLock();
        }
    }

3、Redisson完成分布式锁

1、简介

        Redisson 是架设在 Redis 基础上的一个 Java 驻内存数据网格(In-Memory Data Grid)。充分的利用了 Redis 键值数据库提供的一系列优势,基于 Java 实用工具包中常用接口,为使用者提供了一系列具有分布式特性的常用工具类。

RLock lock = redisson.getLock("anyLock");// 最常见的使用方法
lock.lock();
// 加锁以后 10 秒钟自动解锁// 无需调用 unlock 方法手动解锁
lock.lock(10, TimeUnit.SECONDS);
// 尝试加锁,最多等待 100 秒,上锁以后 10 秒自动解锁 
Boolean res = lock.tryLock(100,10, TimeUnit.SECONDS);
if (res) {
    try {
        ...
    } finally {
        lock.unlock();
    }
}

五、springCache

1、简介

        Spring Cache利用了AOP,实现了基于注解的缓存功能,并且进行了合理的抽象,业务代码只需要简单地加一个注解,就能实现缓存功能了。

2、使用

启用缓存

//只需要在配置类中添加 @EnableCaching
@Configuration
@EnableCaching
public class CachingConfig {

    @Bean
    public CacheManager cacheManager() {
        return new ConcurrentMapCacheManager("addresses");
    }
}

 在需要缓存的数据方法加上注解

//    @CacheEvict(value = "catagory", allEntries = true)   第二种方法  批量删除某个分区下的所有数据
//    @Caching(evict = {
//            @CacheEvict(value = "catagory", key = "'getLevel1Cate'"),   //同时进行多种缓存操作  第一种方法 todo
//            @CacheEvict(value = "catagory", key = "'getCatelogJson'")
//    })
//    @CachePut //双写模式

    @CacheEvict(value = "catagory", key = "'getLevel1Cate'") //修改后自动删除缓存
    @Transactional
    @Override
    public List<CategoryEntity> updateCascade(CategoryEntity category) {}

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

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

相关文章

机器人前沿--PalmE:An Embodied Multimodal Language Model 具身多模态大(语言)模型

首先解释这篇工作名称Palm-E&#xff0c;发表时间为2023.03&#xff0c;其中的Palm是谷歌内部在2022.04开发的大语言模型&#xff0c;功能类似ChatGPT&#xff0c;只是由于各种原因没有那样火起来&#xff0c;E是Embodied的首字母&#xff0c;翻译过来就是具身多模态大语言模型…

基于5个K7的多FPGA PCIE总线架构的高性能数据预处理平台

板载FPGA实时处理器&#xff1a;XCKU060-2FFVA15172个QSFP光纤接口&#xff0c;最大支持10Gbps/lane板载DMA控制器&#xff0c;能实现双向DMA高速传输支持x8 PCIE主机接口&#xff0c;系统带宽5GByte/s1个R45自适应千兆以太网口1个FMC子卡扩展接口 基于PCIE总线架构的高性能数据…

c++包管理器

conan conan search&#xff0c;查看网络库 conan profile detect&#xff0c;生成缓存信息conan new cmake_exe/cmake_lib&#xff0c;创建cmakelists.txtconan install .&#xff0c;执行Conanfile.txt中的配置&#xff0c;生成相关的bat文件 项目中配置Conanfile.txt(或者…

【学习笔记】无人机(UAV)在3GPP系统中的增强支持(十一)-无人机服务可用性用例需求

引言 本文是3GPP TR 22.829 V17.1.0技术报告&#xff0c;专注于无人机&#xff08;UAV&#xff09;在3GPP系统中的增强支持。文章提出了多个无人机应用场景&#xff0c;分析了相应的能力要求&#xff0c;并建议了新的服务级别要求和关键性能指标&#xff08;KPIs&#xff09;。…

口袋算法的示例

原理 口袋算法是感知器(Perceptron)算法的一种改进。感知器算法是一种线性分类算法,但在训练数据不是线性可分的情况下,它可能无法收敛,即无法找到一个线性分类器来正确分类所有的训练样本。为了解决这个问题,口袋算法引入了一个"口袋"(Pocket),用来存储迄…

Redis② —— Redis线程模型

1. Redis是单线程吗&#xff1f; 指 接受客户请求 --> 解析请求 --> 进行数据读写操作 --> 发送数据给客户端 这个过程由一个主线程完成redis程序并不是单线程的&#xff0c;在启动时会启动后台进程 2.6之前启动两个后台线程&#xff0c;分别处理关闭文件、AOF刷盘4.…

Go 语言返回组装数据

文章id 文章标题 ..... 分类 字段 &#xff1a;[分类名&#xff0c;分类描述 .... ]标签字段 : [标签名, 标签id ..... ]type ArticleWithCategoryLabel struct {system.SysArticleCategoryName system.SysCategorie json:"category_name"LabelName system.SysLab…

CSS选择器(1)

以内部样式表编写CSS选择器&#xff0c;其主要编写在<head></head>元素里&#xff0c;通过<style></style>标签来定义内部样式表。 基本语法为&#xff1a; 选择器{ 声明块 } 声明块&#xff1a;是由一对大括号括起来&#xff0c;声明块中是一个一个的…

23种设计模式之责任链模式

责任链模式 1、定义 避免将一个请求的发送者与接受者耦合在一起&#xff0c;让多个对象都有机会处理请求。将接受请求的对象连接成一条链&#xff0c;并且沿着这条链传递请求&#xff0c;直到有一个对象能够处理它为止 2、责任链模式结构 Handler(抽象处理者)&#xff1a;定…

使用Python和MediaPipe实现手势控制音量(Win/Mac)

1. 依赖库介绍 OpenCV OpenCV&#xff08;Open Source Computer Vision Library&#xff09;是一个开源的计算机视觉和机器学习软件库。它包含了数百个计算机视觉算法。 MediaPipe MediaPipe是一个跨平台的机器学习解决方案库&#xff0c;可以用于实时人类姿势估计、手势识…

什么是im即时通讯?WorkPlus im即时通讯私有化部署安全可控

IM即时通讯是Instant Messaging的缩写&#xff0c;指的是一种实时的、即时的电子信息交流方式&#xff0c;也被称为即时通讯。它通过互联网和移动通信网络&#xff0c;使用户能够及时交换文本消息、语音通话、视频通话、文件共享等信息。而WorkPlus im即时通讯私有化部署则提供…

[MySQL][表的约束][二][主键][自增长][唯一键][外键]详细讲解

目录 1.主键2.自增长1.是什么&#xff1f;2.索引 3.唯一键4.外键1.为什么&#xff1f;2.是什么&#xff1f;3.如何理解外键约束&#xff1f; 5.综合案例 -- 阅读 1.主键 主键&#xff1a;primary key用来唯一的约束该字段里面的数据&#xff0c;不能重复&#xff0c;不能为空&a…

Linux系列--命令详解

目录 一、Linux资源管理方式 二、查询类型命令详解 三、文件管理类型命令详解 四、文件压缩与解压 五、文件编辑 六、系统命令 七、文件内容查看命令 一、Linux资源管理方式 linux操作系统采用一个文档树来组织所有的资源。这棵树的根目录的名字叫做&#xff1a;//…

护网HW面试常问——webshell内存马流量特征以及查杀

参考&#xff1a;学习干货|HVV必学远控工具及Webshell流量合集分析(建议收藏附面试题) 蚁剑 ini_set ini_set_time ini_set_limit ini_set("display_errors","0") 部分代码明文传输&#xff0c;较好辨认 哥斯拉 1、User-Agent (弱特征) 在默认的情况…

电脑文件误删除如何恢复?Top12电脑数据恢复软件汇总合集!(图文详解)

电脑文件误删除如何恢复&#xff1f;在日常使用电脑过程中&#xff0c;我们经常会遇到意外删除文件的情况。可能是因为按错了按键、误操作了鼠标&#xff0c;或者意外格式化了存储设备。这些情况都可能导致重要的文件不小心被删除。但是不用担心&#xff0c;有许多专业的数据恢…

【stm32】新建stm32标准库函数工程

新建stm32标准库函数工程 一.工程必要文件创建二、新建main函数三、添加库函数文件四、补充User文件夹下的文件五、工程启动文件选择 官方提供的stm32标准外设库文件所包含的内容介绍&#xff1a; 一.工程必要文件创建 前提&#xff1a;先通过keil新建一个项目工程 1.在新建工程…

Linux系统升级OpenSSH版本到openssh-9.8p1

1、升级OpenSSH就要对应的升级OpenSSL&#xff0c;所以要同时要准备openssh-9.8p1.tar.gz和openssl-3.3.1.tar.gz 2、将两个压缩包上传到/home/user目录。 3、为了防止ssh安装失败导致无法连接服务器&#xff0c;需要先安装并启动telnet连接协议&#xff0c;命令如下&#xf…

2024 微信小程序 学习笔记 第一天

微信公众平台 (qq.com) 小程序代码的构成 项目结构 JSON 配置文件 WXML 模板 WXSS 样式 JS 逻辑交互 小程序的宿主环境 宿主 通信模型 运行机制 组件 视图组件 view scrioll-view swiper swiper-item swiper属性 text button image image mode属性 小程序API 协…

[Linux]CentOS软件的安装

一、Linux 软件包管理器 yum 1.Linux安装软件的方式 在linux中安装软件常用的有三种方式&#xff1a; 源代码安装&#xff08;我们还需要进行编译运行后才可以&#xff0c;很麻烦&#xff09; rpm安装&#xff08;Linux的安装包&#xff0c;需要下载一些rpm包&#xff0c;但是…

SpringBoot+Vue实现简单的文件上传(txt篇)

SpringBootVue实现简单的文件上传 1 环境 SpringBoot 3.2.1&#xff0c;Vue 2&#xff0c;ElementUI 2 页面 3 效果&#xff1a;只能上传txt文件且大小限制为2M&#xff0c;选择文件后自动上传。 4 前端代码 <template><div class"container"><el-…