黑马店评-04缓存更新策略,保证MySQL数据库中的数据和Redis中缓存的数据一致性

news2024/11/17 1:39:17

缓存更新策略(数据一致)

更新策略

缓存更新是Redis为了节约内存而设计出来的机制,当我们向Redis插入太多数据时就会导致缓存中的数据过多,所以Redis会对部分数据进行更新即淘汰

  • 低一致性需求(数据长久不发生变化): 使用内存淘汰机制,例如店铺类型信息的查询缓存,因为这部分数据很长一段时间都不需要更新
  • 高一致性需求: 使用主动更新机制,写入缓存的时候需要设置超时时间,例如店铺详情查询的缓存

在这里插入图片描述

主动更新实现

主动更新策略一般有如下几种方案

在这里插入图片描述

人工编码的三大问题

更新数据库后,删除缓存还是更新缓存?

  • 更新缓存: 每次更新数据库都更新缓存,如果中间没有人执行查询操作(写多读少),那么这些对缓存的更新动做就是无效的(用户根本就不会去缓存中查询数据)
  • 删除缓存: 更新数据库时把缓存删掉,只有用户下次做查询操作时才会更新缓存(用户发现Redis中没有数据就会去查询数据库同时把查询到的数据写入缓存)

如何保证缓存与数据库的操作的同时成功或失败?

  • 在单体系统中将缓存与数据库操作放在一个事务
  • 在分布式系统中利用TCC等分布式事务方案

先操作缓存还是先操作数据库?

  • 虽然这二者都存在线程安全问题,但是由于删除缓存的操作很快,更新数据库的操作相对较慢, 所以先操作数据库再删除缓存出现线程安全问题的概率相对较低

在这里插入图片描述

实现商铺缓存与数据库一致

根据店铺Id查询店铺时如果缓存未命中则查询数据库,将查询到的店铺信息写入Redis的同时设置缓存的超时时间

public static final Long CACHE_SHOP_TTL = 30L;
@Override
public Result queryById(Long id) {
    // 先从Redis中查询对应的店铺缓存,这里的常量值是固定的前缀+店铺id
    String shopJson = stringRedisTemplate.opsForValue().get(CACHE_SHOP_KEY + id);
    // 如果在Redis中查询到了店铺信息(String类型的JSON字符串)则转为Shop类型直接返回
    if (StrUtil.isNotBlank(shopJson)) {
        Shop shop = JSONUtil.toBean(shopJson, Shop.class);
        return Result.ok(shop);
    }
    // 在Redis中没查询到对应的店铺缓存信息则根据店铺Id去数据库中查询店铺信息
    Shop shop = getById(id);
    // 在数据库中也查不到就返回一个错误信息或者返回空(根据业务需求)
    if (shop == null){
        return Result.fail("店铺不存在!!");
    }
    // 在数据库中查到了店铺信息,则将shop对象转为json字符串存入redis同时设置缓存的超时时间(如30分钟)
    String jsonStr = JSONUtil.toJsonStr(shop);
    stringRedisTemplate.opsForValue().set(CACHE_SHOP_KEY + id, jsonStr,CACHE_SHOP_TTL, TimeUnit.MINUTES);
    // 最终把查询到的店铺信息返回给前端
    return Result.ok(shop);
}

根据店铺Id修改店铺时先修改数据库再删除缓存来解决双写问题,更新和删除通过事务去控制, 业务逻辑我们依旧是写在Service层的实现类中

// 更新商铺信息
@PutMapping
public Result updateShop(@RequestBody Shop shop) {
    // 直接将请求体中JSON格式的店铺信息写入数据库,这样在缓存有效期内,即使数据库中的店铺信息修改了,下次获取的还是之前缓存中的店铺信息
    shopService.updateById(shop);
    return Result.ok();
}
// 更新商铺信息
@PutMapping
public Result updateShop(@RequestBody Shop shop) {
    // 先将请求体中JSON格式的店铺信息写入数据库,再删除缓存,保证缓存中的店铺信息和数据库中的店铺信息一致性
    return shopService.update(shop);
}

public interface IShopService extends IService<Shop> {
    Result update(Shop shop);

}

@Override
@Transactional
public Result update(Shop shop) {
    // 首先先判一下店铺Id是否为空
    if (shop.getId() == null){
        return Result.fail("店铺id不能为空!!");
    }
    // 先修改数据库中对应的店铺信息
    updateById(shop);
    // 再将Redis中对应店铺的缓存删除
    stringRedisTemplate.delete(CACHE_SHOP_KEY + shop.getId());
    return Result.ok();
}

重启服务器进行测试,如访问餐厅时会将该餐厅的数据缓存到Redis中,然后使用POSTMAN携带JSON数据发送PUT请求http://localhost:8080/api/shop/更新餐厅信息

  • 店铺的信息修改后就不会再出现在Redis缓存中了, 只有我们再次访问时才会去数据库中查询店铺信息并写入缓存
{
  "area": "大关",
  "openHours": "10:00-22:00",
  "sold": 4215,
  "address": "金华路锦昌文华苑29号",
  "comments": 3035,
  "avgPrice": 80,
  "score": 37,
  "name": "yunqing茶餐厅",
  "typeId": 1,
  "id": 1
}

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

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

相关文章

day02_运算符_if

零、今日内容 1.运算符 2.scanner 3.if,ifelse,elseif 复习 学习方法: 睡觉前过电影(1jdk,配置环境变量2idea使用3HelloWorld程序解释 4变量5数据类型6String) 主方法是每次都要写的,因为代码要执行(psvm) 输出语句每次都要写的,因为要看结果(sout) 1.声明变量的语法格式 数据类…

网络安全(黑客)—0基础学习手册

目录梗概 一、自学网络安全学习的误区和陷阱 二、学习网络安全的一些前期准备 三、网络安全学习路线 四、学习资料的推荐 想自学网络安全&#xff08;黑客技术&#xff09;首先你得了解什么是网络安全&#xff01;什么是黑客&#xff01; 网络安全可以基于攻击和防御视角来…

Git【入门】从安装到会用(千字总结●超详细)

我的个人主页&#xff1a;☆光之梦☆_C语言基础语法&#xff08;超详细&#xff09;,【java入门】语法总结-CSDN博客 创作不易&#xff0c;如果能帮到你就好 注&#xff1a;你的 &#x1f44d;点赞 ⭐收藏 &#x1f4dd;评论 是对博主最大的支持与鼓励喔 认真看完这篇文章&am…

极智AI | 能够轻松构建大模型端到端应用的LangChain 到底是什么

欢迎关注我的公众号 [极智视界],获取我的更多经验分享 大家好,我是极智视界,本文来介绍一下 能够轻松构建大模型端到端应用的 LangChain,到底是什么。 邀您加入我的知识星球「极智视界」,星球内有超多好玩的项目实战源码下载,链接:https://t.zsxq.com/0aiNxERDq 先上官…

Cesium热力图

二、代码 <!doctype html> <html><head><meta charset"utf-8"><link rel"stylesheet" href"./css/common.css"><title>热力图</title><script src"./js/config.js"></script>…

手动实现SpringMVC底层机制

手动实现SpringMVC底层机制 &#x1f41f;准备工作&#x1f34d;搭建SpringMVC底层机制开发环境 实现任务阶段一&#x1f34d;开发ZzwDispatcherServlet&#x1f966;说明: 编写ZzwDispatcherServlet充当原生的DispatcherServlet(即核心控制器)&#x1f966;分析代码实现&#…

基于点标签的目标检测与计数深度学习框架盘点

(1)P2PNet <1>P2PNet提出 论文出处&#xff1a;Rethinking Counting and Localization in Crowds: A Purely Point-Based Framework 论文链接&#xff1a;https://arxiv.org/abs/2107.12746 开源代码&#xff1a;https://github.com/TencentYoutuResearch/CrowdCount…

物联网AI MicroPython传感器学习 之 MQ136硫化氢传感器

学物联网&#xff0c;来万物简单IoT物联网&#xff01;&#xff01; 一、产品简介 MQ136 是一种硫化氢检测传感器&#xff0c;感应范围为 1 - 200ppm。传感元件是 SnO2&#xff0c;它在清洁空气中的电导率较低。当存在 H₂S 气体时&#xff0c;传感器的电导率随着气体浓度的升…

Gralloc ION DMABUF in Camera Display

目录 Background knowledge Introduction ia pa va and memory addressing Memory Addressing Page Frame Management Memory area management DMA IOVA and IOMMU Introduce DMABUF What is DMABUF DMABUF 关键概念 DMABUF APIS –The Exporter DMABUF APIS –The…

PyTorch模型的多种导出方式提供给其他程序使用

PyTorch模型的多种导出方式提供给其他程序使用 flyfish PyTorch模型的多种导出方式 PyTorch模型的多种导出方式提供给其他程序使用1 模型可视化2 预训练模型3 ONNX模型导出有输入有输出TRAINING导出方式EVAL导出方式 4 自定义输入输出的名字&#xff0c;并可批量推理5 导出JI…

PyG两个data Datsaset v.s. InMemoryDataset

可以看到InMemoryDataset 对CPU更加友好 https://pytorch-geometric.readthedocs.io/en/latest/modules/data.html#pytorch-lightning-wrappers

Linux下C++编程-进度条

引言&#xff1a;本篇主要在linux下的C实现进度条的功能。按照多文件编程&#xff0c;同时使用Makefile文件完成多文件的编译、连接。 首先创建头文件&#xff1a; 1. progress.h #pragma once #include <iostream> #include <cstring> #include <iomanip>…

Navicat定时任务

Navicat定时任务 1、启动Navicat for MySQL工具&#xff0c;连接数据库。 2、查询定时任务选项是否开启 查询命令&#xff1a;SHOW VARIABLES LIKE ‘%event_scheduler%’; ON表示打开&#xff0c;OFF表示关闭。 打开定时任务命令 SET GLOBAL event_scheduler 0; 或者 SET G…

elasticsearch 8.5.3问题记录

一&#xff1a;解决 elasticsearch 高版本 warning: ignoring JAVA_HOMEC:\Program Files\Java\jdk-11&#xff1b; using bundled JDK if defined JAVA_HOME (set JAVA_HOME%JAVA_HOME%; )示例版本Elasticsearch 8.5.3 可以与 JDK 11 兼容&#xff0c;但不支持 JDK 17。确保选…

离散数学 期末复习

离散数学 期末复习 图片过多&#xff0c;若无法显示&#xff0c;请转至 https://chenhaotian.top/study/discrete-mathematics-final-review/ 访问全文 发布于 2023-06-18 第 1 章 命题逻辑 1.2 等值演算 真值表法 等值演算法 题&#xff1a;等值演算 题&#xff1a;等值演…

python 学习随笔 5

函数 在python中&#xff0c;函数也是对象。 def func():""" 这是文档字符串"""print("Hello World")fun带参数函数 函数和变量注解 def calc(a:int, b:int) -> int: # 为函数的形参和返回值标注类型return a b print(calc(1,3…

C语言重点突破(2)指针(三)

本章重点 1. 函数指针 2. 函数指针数组3. 指向函数指针数组的指针 4. 回调函数 1.函数指针 首先可以明确的是&#xff0c;函数指针和数组指针的类型都是指针类型&#xff0c;用来存放地址的&#xff0c;数组指针存放数组的地址&#xff0c;而函数指针存放的便是函数的地址。 …

ESPHome 通过http获取设备的状态

substitutions: { desc: 传感器, devicename: sensor }esphome:name: $devicenameplatform: ESP8266board: nodemcuv2arduino_version: latest# Enable logging logger:# Enable Home Assistant API api:encryption:key: "MhXiJqKKyCXTqjZWqtegaP1tQSUpPtbnXP9iV1i2TzE&qu…

SSM - Springboot - MyBatis-Plus 全栈体系(二十四)

第五章 SSM 二、SSM 整合配置实战 1. 依赖整合添加 1.1 数据库准备 依然沿用 mybatis 数据库测试脚本&#xff01; CREATE DATABASE mybatis-example;USE mybatis-example;CREATE TABLE t_emp(emp_id INT AUTO_INCREMENT,emp_name CHAR(100),emp_salary DOUBLE(10,5),PRIM…

视频号双11激励政策,快来看一看

双十一即将来临&#xff0c;不少平台都公布了自己的双十一政策。这篇文章&#xff0c;我们来看看视频号推出的激励政策&#xff0c;看有哪些需要准备的。