谷粒商城----缓存与分布式锁

news2024/10/16 22:17:10

1、缓存使用

为了系统性能的提升,我们一般都会将部分数据放入缓存中,加速访问。而 db 承担数据落盘工作。

哪些数据适合放入缓存?

 即时性、数据一致性要求不高的
 访问量大且更新频率不高的数据(读多,写少)

举例:电商类应用,商品分类,商品列表等适合缓存并加一个失效时间(根据数据更新频率来定),后台如果发布一个商品,买家需要 5 分钟才能看到新的商品一般还是可以接受的

在这里插入图片描述

data = cache.load(id);//从缓存加载数据
If(data == null){
data = db.load(id);//从数据库加载数据
cache.put(id,data);//保存到 cache 中
}
return data;

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

2、springboot整合redis(StringRedisTemplate)

    @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);
    }

在这里插入图片描述

3、缓存使用-改造三级分类业务

在这里插入图片描述

缓存穿透,缓存击穿,缓存雪崩

在这里插入图片描述

在这里插入图片描述

4、分布式锁setnx

在这里插入图片描述

🚩优化一:过期时间(解决不释放锁导致死锁问题)

在这里插入图片描述

🚩优化二:过期时间和加锁同步setex+nx(解决加锁原子性问题)

在这里插入图片描述

在这里插入图片描述

🚩优化三:redis+lua脚本解决删锁原子性问题

在这里插入图片描述

    /**
     * 分布式锁
     *  lua脚本
     * @return
     */
    public Map<String, List<Catelog2Vo>> getCatelogJsonFromDBWithRedisLock() {
        // 1.占分布式锁  设置这个锁10秒自动删除 [原子操作]
        String uuid = UUID.randomUUID().toString();
        Boolean lock = stringRedisTemplate.opsForValue().setIfAbsent("lock", uuid, 30, TimeUnit.SECONDS);

        if (lock) {
            // 2.设置过期时间加锁成功 获取数据释放锁 [分布式下必须是Lua脚本删锁,不然会因为业务处理时间、网络延迟等等引起数据还没返回锁过期或者返回的过程中过期 然后把别人的锁删了]
            Map<String, List<Catelog2Vo>> data;
            try {
                data = getDataFromDB();
            } finally {
//			stringRedisTemplate.delete("lock");
                String lockValue = stringRedisTemplate.opsForValue().get("lock");

                // 删除也必须是原子操作 Lua脚本操作 删除成功返回1 否则返回0
                String script = "if redis.call('get',KEYS[1]) == ARGV[1] then return redis.call('del',KEYS[1]) else return 0 end";
                // 原子删锁
                stringRedisTemplate.execute(new DefaultRedisScript<>(script, Long.class), Arrays.asList("lock"), uuid);
            }
            return data;
        } else {
            // 重试加锁
            try {
                // 登上两百毫秒
                Thread.sleep(50);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return getCatelogJsonFromDBWithRedisLock();
        }
    }

5、redisson分布式锁

	@ResponseBody
	@RequestMapping("/index/hello")
	public String hello() {
		RLock lock = redissonClient.getLock("my-lock");
		// 阻塞式等待
		lock.lock();
		try {
			Thread.sleep(2000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		} finally {
			lock.unlock();
		}
		return "hello";
	}

在这里插入图片描述
在这里插入图片描述

6、双写一致性与延迟双删

双写一致性

🚩双写一致性的解决方案一:可以在修改数据的方法加锁,就是每次只允许一个线程去修改数据库,这样就保证了Mysql和redis数据的一致性

🚩双写一致性的解决方案二:给redis设置过期时间,过期后就会去Mysql查最新的数据,保证最终数据一致

在这里插入图片描述

失效模式

在这里插入图片描述

延迟双删

延时双删的方案的思路是,为了避免更新数据库的时候,其他线程从缓存中读取不到数据,就在更新完数据库之后,再sleep一段时间,然后再次删除缓存。

sleep的时间要对业务读写缓存的时间做出评估,sleep时间大于读写缓存的时间即可。

流程如下:

1、线程1删除缓存,然后去更新数据库
2、线程2来读缓存,发现缓存已经被删除,所以直接从数据库中读取,这时候由于线程1还没有更新完成,所以读到的是旧值,然后把旧值写入缓存
3、线程1,根据估算的时间,sleep,由于sleep的时间大于线程2读数据+写缓存的时间,所以缓存被再次删除
4、如果还有其他线程来读取缓存的话,就会再次从数据库中读取到最新值
在这里插入图片描述

消息队列

这是网上很多文章里都有写过的方案。但是这个方案的缺陷会更明显一点。

先更新数据库,成功后往消息队列发消息,消费到消息后再删除缓存,借助消息队列的重试机制来实现,达到最终一致性的效果。

在这里插入图片描述

import redis.clients.jedis.Jedis;

public class DelayedDoubleDeleteExample {
    private static final int DELAY_TIME = 1000; // 延迟双删时间,单位:毫秒

    // 模拟数据库
    private static String database = "Original Data";
    
    // 模拟缓存
    private static Jedis cache = new Jedis("localhost", 6379);

    public static void main(String[] args) throws InterruptedException {
        // 初始化缓存
        cache.set("key", database);
        
        // 更新数据
        updateDataInDatabase("Updated Data");

        Thread.sleep(DELAY_TIME); // 等待延迟双删时间

        // 获取数据
        String data = getData("key");
        System.out.println("Data: " + data);
    }

    private static void updateDataInDatabase(String newData) {
        // 先更新数据库
        database = newData;
        
        // 再删除缓存
        cache.del("key");
        System.out.println("Cache deleted");
    }

    private static String getData(String key) {
        // 先从缓存读取数据
        String data = cache.get(key);

        if (data == null) {
            // 缓存不存在,从数据库读取最新数据
            data = database;
            
            // 将数据写入缓存
            cache.set(key, data);
            System.out.println("Cache updated");
        }

        return data;
    }
}

7、Cannal

在这里插入图片描述

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

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

相关文章

day3_C++

day3_C 思维导图用C的类完成数据结构 栈的相关操作用C的类完成数据结构 循环队列的相关操作 思维导图 用C的类完成数据结构 栈的相关操作 stack.h #ifndef STACK_H #define STACK_H#include <iostream> #include <cstring>using namespace std;typedef int datat…

SplitMask:大规模数据集是自我监督预训练的必要条件吗?

自监督预训练需要大规模数据集吗?这是2021年发布的一篇论文&#xff0c;它在自监督预训练场景中使用小数据集&#xff0c;如Stanford Cars, Sketch或COCO&#xff0c;它们比ImageNet小几个数量级。并提出了一种类似于BEiT的去噪自编码器的变体SplitMask&#xff0c;它对预训练…

光伏发电双向电能表DTSD1352

安科瑞 华楠 DTSD1352 导轨式多功能电能表&#xff0c;是主要针对电力系统&#xff0c;工矿企业&#xff0c;公用设施的电能统 计、管理需求而设计的一款智能仪表&#xff0c;产品具有精度高、体积小、安装方便等优点。集成常 见电力参数测量及电能计量及考核管理&#xff0c;…

PY32F003F18之RS485通讯

PY32F003F18将USART2连接到RS485芯片&#xff0c;和其它RS485设备实现串口接收后再转发的功能。 一、测试电路 二、测试程序 #include "USART2.h" #include "stdio.h" //getchar(),putchar(),scanf(),printf(),puts(),gets(),sprintf() #include "…

2.10 PE结构:重建重定位表结构

Relocation&#xff08;重定位&#xff09;是一种将程序中的一些地址修正为运行时可用的实际地址的机制。在程序编译过程中&#xff0c;由于程序中使用了各种全局变量和函数&#xff0c;这些变量和函数的地址还没有确定&#xff0c;因此它们的地址只能暂时使用一个相对地址。当…

二十、MySQL多表关系

1、概述 在项目开发中&#xff0c;在进行数据库表结构设计时&#xff0c;会根据业务需求以及业务模块之间的关系&#xff0c;分析并设计表结构&#xff0c;由于业务之间相互关联&#xff0c;所以各个表结构之间也存在着各种对应关系 2、多表关系分类 &#xff08;1&#xff0…

2023大数据挑战赛全国六强团队获奖经验+ppt分享(四)

团队名称 陛下请移步至地下室 团队成员 张晓立&#xff08;华东师范大学&#xff09; 团队名次 全国第三名 赛题描述说明介绍 2023大数据挑战赛赛题说明决赛评分标准回顾 参赛分享与收获 大赛提供了非常丰富有趣的数据&#xff0c;能把数据分析明白就能获得高分。首先分析metri…

Delphi、C# 和 TypeScript 之父 Anders Hejlsberg(安德斯·海尔斯伯格,海神)赶潮AI

自2022年11月ChatGPT横空出世&#xff0c;一波由AIGC引发的热潮轰轰烈烈持续传播。 全球各国政府及大型互联网企业都在积极布局人工智能解决方案&#xff0c;抢占人工智能高地&#xff0c;推动人工智能产业健康发展。 Delphi、C# 和 TypeScript 之父&#xff0c;位列Microsof…

口袋参谋:如何规避差评风险?一招让你实现宝贝0差评!

​作为卖家&#xff0c;不会还有人不知道差评的威力吧&#xff01; 如果你宝贝销量大&#xff0c;差评率本身就低&#xff0c;偶尔一个差评可能影响不大。 但如果你是新宝贝上架&#xff0c;销量少的可怜&#xff0c;差评就是重磅炸弹&#xff0c;99.99%让店铺的评分绿得发亮…

git bash 常见场景用法

1.git 客户端 2.git 代码操作&#xff08;下载、上传、删除、查看仓库地址&#xff09; 下载代码&#xff1a; git clone 仓库路径 上传代码&#xff1a; git add git commit -m "注释" git push 删除代码&#xff1a; git rm [-r] 代码&#xff1b;git commit -m…

腾讯云新用户:定义、专属福利及优惠活动

在当今的数字化时代&#xff0c;云计算已成为企业和个人不可或缺的技术服务。腾讯云作为国内领先的云计算服务提供商&#xff0c;为新用户提供了一系列专属福利和优惠活动。本文将详细介绍腾讯云新用户的定义、专属福利和优惠活动&#xff0c;助力大家轻松上云&#xff01; 一、…

基于Java+SpringBoot+Vue前后端分离高校专业实习管理系统设计和实现

博主介绍&#xff1a;✌全网粉丝30W,csdn特邀作者、博客专家、CSDN新星计划导师、Java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专…

Tomcat多实例 + Tomcat负载均衡、动静分离(Nginx联动)

多实例联动 一、Tomcat 多实例1.1 什么是Tomcat多实例&#xff1f;1.2 配置思路1.3 配置实现1.3.1 安装jdk1.3.2 安装tomcat1.3.3 配置 tomcat 环境变量1.3.4 修改端口号1.3.5 修改各 tomcat 实例中的 startup.sh 和 shutdown.sh 文件&#xff0c;添加 tomcat 环境变量1.3.6 启…

01_前端css编写的三种方式

前言 CSS的引入方式共有三种&#xff1a;行内样式、内部样式表、外部样式表 一、内联式引入 用法&#xff1a; 在元素上直接通过style属性进行设置css样式设置 示例&#xff1a; <h1 style"color:red;">style属性的应用</h1> <p style"font-si…

建站系列(五)--- 前端开发语言之HTML、CSS、JavaScript

目录 相关系列文章前言一、前端开发与后端开发二、前端语言简介&#xff08;一&#xff09;、HTML&#xff08;二&#xff09;、CSS&#xff08;三&#xff09;、JavaScript 三、学习指导&#xff08;一&#xff09;、开发环境&#xff08;二&#xff09;、第一个Hello&#xf…

【实训】“宅急送”订餐管理系统(程序设计综合能力实训)

&#x1f440;樊梓慕&#xff1a;个人主页 &#x1f3a5;个人专栏&#xff1a;《C语言》《数据结构》《蓝桥杯试题》《LeetCode刷题笔记》《实训项目》 &#x1f31d;每一个不曾起舞的日子&#xff0c;都是对生命的辜负 前言 大一小学期&#xff0c;我迎来了人生中的第一次实训…

4.6版本Wordpress漏洞复现

文章目录 一、搭建环境二、漏洞复现1.抓包2.准备payload3.发送payload4.检查是否上传成功5.连接payload 国外的&#xff1a;Wordpress&#xff0c;Drupal&#xff0c;Joomla&#xff0c;这是国外最流行的3大CMS。国内则是DedeCMS和帝国&#xff0c;PHPCMS等。 国内的CMS会追求大…

2023/9/8 -- C++/QT

作业 1> 自行封装一个栈的类&#xff0c;包含私有成员属性&#xff1a;栈的数组、记录栈顶的变量 成员函数完成&#xff1a;构造函数、析构函数、拷贝构造函数、入栈、出栈、清空栈、判空、判满、获取栈顶元素、求栈的大小 02stack.h: #ifndef __02STACK_H__ #define __…

​重生奇迹MU魔法师的装备属性​

魔法师的武器主要武器装备&#xff0c;主要分类为单手武器、双手武器、戒指、项链、盾牌、头盔、铠甲、护手、护腿、鞋子&#xff0c;玩家需要根据情况集齐这些装备。 智力果实以及体力果非常重要&#xff0c;在实战的时候非常实用。实获取途径一般是果实合成、宝藏&#xff0…

说说分布式系统容器化

继上一篇浅谈高并发分布式架构演进路径&#xff0c;单体服务完成分布式架构改造&#xff0c;转型为微服务。随着微服务数量的急剧增加&#xff0c;跨应用、跨系统的调用越来越多&#xff0c;调用关系和依赖关系日益复杂&#xff0c;这种复杂性增加了系统的设计、实施和维护的难…