redis+mysql数据一致性+缓存穿透解决方案

news2024/11/26 4:54:42

在分布式事务中我们知道有cap定理,即 我们保证高可用的情况下,必然要牺牲一些一致性,在保证强一致性的情况下,必然会牺牲一些可用性。而我们redis+mysql数据一致性的使用策略就是在我们保证可用性的情况下尽量保证数据的一致性。想要达到强一致性,不加锁,只用 一些缓存策略那必然不是不可能的

1.一般 查询的业务情况

我们常用的 情况有  对一些热点的数据,或者频繁的查询的数据,如果频繁访问数据库,必然会对数据库造成很大的压力,为了减缓这种压力,我们 用redis做缓存,数据库做底    我们的查询数据的情况一般如下

这样看似好像并没有什么问题,但是当我们想象这样一个业务场景

现在 我要对 该数据 A进行 修改,那么我们修改数据A之后,必然会要修改缓存 和数据库中的数据

那么问题来了,高并发的情况下,在修改数据的时候,如果来了一个查询操作,在这之间会怎么样呢?我们是先修改缓存数据,还是先修改数据库的数据呢?

我们要么先删除缓存 再修改数据库 ,要么先修改数据库再删除缓存,但是这两种情况都会出现 redis 和数据库 数据不一致的情况 

2.删除 缓存 +修改数据库

3.先修改数据库 再删除缓存

 所以综上所述  我们一般会采用 先修改数据库 然后再删除缓存,这也是 大家 选择的的比较多的方案

4.数据一致性兜底解决方案

先写库再删缓存”方案结合事务控制,能彻底保证缓存和数据库的一致性,但会极大程度损耗性能。而且对于业务操作来说,执行业务逻辑、更新库都没报错,偏偏走到最后删缓存时出错,因此需要将整个事务回滚,这是极不公平的  

 所以我们对删除缓存 进行一系列的 处理   

1. try catch  捕捉到 缓存删除失败,在catch中再次删除缓存,也就是 失败的话 重试多次

2. 延时双删  

1.删除缓存

2. 修改数据库

3.休眠 一段时间

4.再次删除缓存

3.异步处理  

这也是比较推荐的方案 

我们先 修改数据库,修改之后,使用mq 发送消息,然后由mq进行对缓存的删除,这样对业务代码侵入也比较低

5.缓存穿透解决

我们知道什么是缓存穿透,就是 请求 一个不存在的数据,然后 由于数据不存在,就不会加入到缓存,会一直访问数据库,这时候会对数据库造成非常大的压力  解决方案一般有两种

 布隆过滤器   和返回null 值  我们  这里只实现返回null值

 当我们 数据 在数据库查不到的时候,我们缓存一个空数据,为了防止内存浪费,我们给该空数据设置一个过期时间,这样 无论谁 用空数据 过度访问 ,都不会给数据库造成太大压力

我们以根据 商品 id 查询数据为例子,同时也对应我们 标题1 的业务实现

 

  @Override
    public Result getByShopId(Long id) {
        //查缓存
        Map entriesMap = redisTemplate.opsForHash().entries(RedisConstants.CACHE_SHOP_KEY + id);

        if(StrUtil.isNotBlank((CharSequence) entriesMap.get("nullId"))){
            log.info(entriesMap.get("nullId").toString());
            log.info("店铺信息不存在");
            return Result.fail("店铺信息不存在");
        }
        // 有的话返回
        if(!entriesMap.isEmpty()){
            Shop shop = BeanUtil.fillBeanWithMap(entriesMap, new Shop(), false);
            log.info("缓存查询到了");
            return  Result.ok(shop);
        }
        //没有的话查数据库
        Shop shopById = query().eq("id", id).one();
        if(BeanUtil.isNotEmpty(shopById)){
            //数据库有的话 添加缓存并且返回
            Map<String, Object> stringObjectMap = BeanUtil.beanToMap(shopById);
            redisTemplate.opsForHash().putAll(RedisConstants.CACHE_SHOP_KEY + id,stringObjectMap);
            // 设置过期时间 防止内存 占满
            redisTemplate.expire(RedisConstants.CACHE_SHOP_KEY+id,RedisConstants.CACHE_SHOP_TTL,TimeUnit.MINUTES);
            return  Result.ok(shopById);
        }
        //数据库没有 返回false
        //解决缓存穿透   访问不存在的数据 缓存为null值 并且设置过期时间
        redisTemplate.opsForHash().put(RedisConstants.CACHE_SHOP_KEY+id,"nullId","null");
        redisTemplate.expire(RedisConstants.CACHE_SHOP_KEY+id,RedisConstants.CACHE_NULL_TTL, TimeUnit.SECONDS);
        return Result.ok("返回成功");
    }

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

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

相关文章

MySql的基本语法操作

查看数据库和表 查看所有的数据库 show databases; 建立一个新的数据库 create database database_name; 也可以是 create database if not exists database_name; 表示这个数据库不存在才建立 而不会打断其他sql语句的执行&#xff0c;而如果没有加的话&#xff0c;创建…

神经网络及大模型科普揭秘

一、生物神经元及神经元构成的神经网络 下图是生物神经元的示意图: 生物神经元由细胞体、树突、轴突、轴突末梢四部分构成。 下图是生物神经网络的一个简单示意图: 生物神经元通过电信号在彼此间传递信号,神经元的各个树突接收输入信号,经过细胞体汇总,如果最终总和高…

【动态规划-最长公共子序列(LCS)】力扣97. 交错字符串

给定三个字符串 s1、s2、s3&#xff0c;请你帮忙验证 s3 是否是由 s1 和 s2 交错 组成的。 两个字符串 s 和 t 交错 的定义与过程如下&#xff0c;其中每个字符串都会被分割成若干 非空 子字符串&#xff1a; s s1 s2 … sn t t1 t2 … tm |n - m| < 1 交错 是 s1…

【微服务】服务注册与发现 - Eureka(day3)

CAP理论 P是分区容错性。简单来说&#xff0c;分区容错性表示分布式服务中一个节点挂掉了&#xff0c;并不影响其他节点对外提供服务。也就是一台服务器出错了&#xff0c;仍然可以对外进行响应&#xff0c;不会因为某一台服务器出错而导致所有的请求都无法响应。综上所述&…

网络安全概述:从认知到实践

一、定义 网络安全&#xff0c;即致力于保护网络系统所涵盖的硬件、软件以及各类数据&#xff0c;切实保障其免遭破坏、泄露或者篡改等不良情形的发生。 二、重要性 个人层面&#xff1a;着重于守护个人隐私以及财产安全&#xff0c;为个人在网络世界中的各项活动提供坚实的保…

分享几个做题网站------学习网------工具网;

以下是就是做题网站&#xff1b;趣IT官网-互联网求职刷题神器趣IT——互联网在线刷题学习平台&#xff0c;汇集互联网大厂面试真题&#xff0c;拥有java、C、Python、前端、产品经理、软件测试、新媒体运营等多个热门IT岗位面试笔试题库&#xff0c;提供能力测评、面试刷题、笔…

Meta 首个多模态大模型一键启动!首个多针刺绣数据集上线,含超 30k 张图片

小扎在 Meta Connect 2024 主题演讲中宣布推出首个多模态大模型 Llama 3.2 vision&#xff01;该模型有 11B 和 90B 两个版本&#xff0c;成为首批支持多模态任务的 Llama 系列模型&#xff0c;根据官方数据&#xff0c;这两个开原模型的性能已超越闭源模型。 小编已经迫不及待…

算法修炼之路之二分查找

目录 一:三大二分介绍及模板 1.普通二分 2.查找左右边界的二分及模板 二:LeetCode OJ练习 1.第一题 2.第二题 3.第三题 4.第四题 5.第五题 6.第六题 一:三大二分介绍及模板 1.普通二分 这里通过一道题来引出普通二分及模板 LeetCode_704 二分查找 画图分析: 具体代…

AI 大模型的核心能力与应用场景全解析

深入理解 AI 大模型&#xff1a;核心能力与应用场景全解析 AI大模型是什么 通过概念考察的方式了解AI大模型&#xff0c;拆开来看。 AI领域术语丰富&#xff0c;涵盖模式识别、自然语言处理、神经网络、机器学习、深度学习、强化学习及人类反馈强化学习。大模型&#xff1a;把…

Springboot人才求职招聘系统源码(前台+后台)

文章目录 1 项目描述2 后台功能3 获取方式 项目技术&#xff1a;springboot 运行环境&#xff1a;jdk1.8idea/eclipsemaven3mysql5.6 1 项目描述 基于springboot的招聘系统&#xff0c;包括前台和后台管理系统&#xff0c;前台包括首页&#xff0c;应聘职位&#xff0c; 在…

[C语言]指针和数组

目录 1.数组的地址 2.通过指针访问数组 3.数组和指针的不同点 4.指针数组 1.数组的地址 数组的地址是什么&#xff1f; 看下面一组代码 #include <stdio.h> int main() { int arr[5] {5,4,3,2,1}; printf("&arr[0] %p\n", &arr[0]); printf(&qu…

最新版IntelliJ IDEA 2024.2.3 创建SpringBoot项目(包含各种依赖的选择和功能)

创建SpringBoot项目 1 . 打开IDEA 选择新建项目 2. 基础项目创建 在顶端几个选项可以选择创建基本的java项目 填写项目名称,文件位置,选择构建工具 3. 下方选择springboot 选择构建的方式 三种方式虽然不同但是,基本功能都一致, Gradle-Groovy 是指使用 Groovy 语言编写…

鸿蒙开发(NEXT/API 12)【访问控制应用权限管控概述】程序访问控制

默认情况下&#xff0c;应用只能访问有限的系统资源。但某些情况下&#xff0c;应用存在扩展功能的诉求&#xff0c;需要访问额外的系统数据&#xff08;包括用户个人数据&#xff09;和功能&#xff0c;系统也必须以明确的方式对外提供接口来共享其数据或功能。 系统通过访问…

http2详细讲解

github链接 &#xff1a; http2

免费音频剪辑软件大揭秘:让声音创作更轻松

在精神娱乐越发丰富的现在&#xff0c;音频内容的创作和编辑变得越来越重要。无论是专业的音乐制作人&#xff0c;还是自媒体创作者&#xff0c;都可能需要一款功能强大且易于使用的音频剪辑软件来处理音频素材。今天我们一同来探讨有什么好用的免费音频剪辑软件吧。 1.福昕音…

UGUI(六大UI根基组件)

Rect Transform 各种参数 是显示pos还是width/height 还是left/top/right/bottom之类巴拉巴拉&#xff0c;各种混合的展示baby&#xff0c;都是看anchor的设置 pivot的设置影响具体数值 至于blueprint mode &#xff0c;就是用了之后框框不变&#xff0c;who wanna do thi…

Graph Retrieval-Augmented Generation: A Survey

最近&#xff0c;检索增强生成(RAG)在解决大型语言模型(llm)的挑战方面取得了显著的成功&#xff0c;而无需再培训。通过引用外部知识库&#xff0c;RAG改进了LLM输出&#xff0c;有效地减轻了诸如“幻觉”、缺乏特定于领域的知识和过时信息等问题。然而&#xff0c;数据库中不…

数据结构与算法篇(图)(持续更新迭代)

目录 一、引言 二、基本概念 三、图的定义 四、图的基本概念和术语 1. 有向图 2. 无向图 3. 简单图 4. 多重图 5. 完全图&#xff08;也称简单完全图&#xff09; 6. 子图 7. 连通、连通图和连通分量 8. 强连通图、强连通分量 9. 生成树、生成森林 10. 顶点的度、…

通信工程学习:什么是OSPF开放式最短路径优先

OSPF&#xff1a;开放式最短路径优先 OSPF&#xff08;Open Shortest Path First&#xff0c;开放式最短路径优先&#xff09;是一种内部网关协议&#xff08;IGP&#xff09;&#xff0c;被广泛应用于计算机网络中&#xff0c;特别是在构建大型和复杂的网络时。以下是对OSPF的…

【Linux】进程第三弹(虚拟地址空间)

目录 现象 底层原因 数据不发生修改 数据修改 小总结 地址空间本质 为什么要有地址空间 现象 来看代码&#xff1a; #include <stdio.h> #include <unistd.h> #include <sys/types.h>int val 50;int main() {printf("father process is running…