首页 > 数据库 >Redis-11-Redis与Mysql的数据一致性

Redis-11-Redis与Mysql的数据一致性

时间:2024-06-09 18:54:49浏览次数:20  
标签:11 缓存 String 删除 Redis key Mysql public 延迟

1.是什么

数据一致性呢,讲的就是缓存中的数据和db中的数据是否能一致。

2.为什么

先看我这篇文章,了解下缓存策略:Redis-6-三种缓存读写策略

在文章中,介绍了并发场景下的一致性问题,我们已经确定了一个基本思路:

先更新db,再删除缓存。

这个方案,奠定了我们在读写操作时的基本思路。

2.1 主从复制延迟

在我们Mysql读写分离+主从复制延迟的场景下,缓存重建用了一个错误的值。

我们主库更新完数据并删除缓存后,缓存确实不存在了。

但是,db的从库读数据有稍许延迟,在这个时间段我们读取,缓存没数据,确实触发了缓存重建。

但是由于读取的从库还没有同步到主库更新过来的数据,导致我们重建的缓存值还是从库中的旧数据,仍然会有问题。

2.2 缓存服务宕机

假设我们的缓存服务宕机了,无法删除缓存。

这个直接就跟没删除缓存的操作一样,缓存的完全是个错误的旧数据。

3.解决

3.1 延时双删

针对主从同步未完成的情况,我们简单的方案就是,等一小会再删除。

来一个demo。

我们RedisService中存放操作缓存的方法,没啥特殊的,就是正常的操作缓存。

@Service
public class RedisService {

    @Autowired
    private StringRedisTemplate redisTemplate;

    public String get(String key) {
        return redisTemplate.opsForValue().get(key);
    }

    public void set(String key, String value, long timeout, TimeUnit unit) {
        redisTemplate.opsForValue().set(key, value, timeout, unit);
    }

    public void delete(String key) {
        redisTemplate.delete(key);
    }
}

DataService呢,记录我们完整的操作步骤。

嗯,你可以看到,实际上,我们在首次删除后,小小休息了下,又触发了次 redisService.delete(key);

@Service
public class DataService {

    @Autowired
    private RedisService redisService;

    public void updateData(String key, String value) {
        updateDatabase(key, value);
        // 首次删除
        redisService.delete(key);
        // 延迟双删
        deleteCacheWithDelay(key);
    }
    
    // 模拟数据库操作
    public void updateDatabase(String key, String value) {
    }

    @Async
    public void deleteCacheWithDelay(String key) {
        try {
            TimeUnit.SECONDS.sleep(5); // 延迟5秒
            redisService.delete(key);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
    }
}

问题是,这个延迟删除缓存,延迟时间到底设置要多久?

  • 延迟时间要大于主从复制的延迟时间。确保删除后,新的读请求重建出来的是正确的数据值。
  • 延迟时间要大于一次完整的缓存重建时间。即大于一个读请求查询db再更新缓存的时间,这样才能确保哪怕真有某个线程重建了个错误的,咱们还是能给它删除掉。

好了,你已经懂延时双删的概念了,现在,请你给出删除时间。

哈哈,懵了吧,我咋知道?嗯,问题就是,我咋知道?

实际情况下,这个时间是很难把控的,咱们就是完全凭借经验来设置个值,尽可能的去保证,极端情况下呢,它还是会有问题。

3.2 消息队列

这种方式,核心上还是一个再次删除的方案。

嗯,不就是延迟删除下缓存嘛,我们当然可以新建个延时消息。

mq消费端,收到消息后,删除对应的缓存。

这就是延时双删的升级版,通过咱们mq的机制,确保肯定能删除掉(消费成功),这样就算缓存宕机or代码报错了也能ok。

那么,还是会存在一个问题,我咋知道时间具体设置多久啊?

还是那句话,很难把控。

3.3 分布式事务

如果要做到强一致性,常见的解决方案就是分布式事务了:吃透此文,分布式事务会被你玩的出神入化

但是,分布式事务的引入,必然又涉及到复杂性的增加,也带来了性能的损失。

那我们引入缓存的初心是什么,不是为了性能吗,所以,这其实是个难以平衡的点。

需要你结合自己的实际场景,权衡使用。

标签:11,缓存,String,删除,Redis,key,Mysql,public,延迟
From: https://www.cnblogs.com/yang37/p/18239864

相关文章

  • 1164. 指定日期的产品价格
    1164.指定日期的产品价格题目链接:1164.指定日期的产品价格代码如下:#WriteyourMySQLquerystatementbelowselectp1.product_id,ifnull(new_price,10)aspricefrom(selectdistinctproduct_idfromProducts)asp1--所有的产品leftjoi......
  • 硬核!使用jsp+servlet+mysql从0搭建图书管理系统(一)
    一、写在开头1.本项目使用IDLE搭建,使用的数据库是mysql8.02.项目前端代码样式可以自行编写,本文注重的是servlet的逻辑处理3.项目使用的数据库和表如下1)bookinfo表2)borrwos(借阅表)3)managers(管理员表)4)readers(读者表)需要表的小伙伴可以根据对应字段自行创建二、......
  • 11 深入理解Linux文件系统与日志分析
    目录11.1深入理解Linux文件系统    11.1.1inode与block详解        1.inode和block概述        2.inode的内容        3.inode的号码        4.inode的大小    11.1.2硬链接与......
  • Win11系统下的MindSpore环境搭建
    技术背景笔者尝试过不少编程环境搭建的方案,例如常见的Ubuntu、Deepin、CentOS,也用过很多人力荐的Manjaro,这些发行版在需要办公的条件下,一般都需要结合Windows双系统使用。MacOS更适用于本地环境搭建,但是能兼容的显卡型号还是比较有限的。经过一些测试,其实我认为Win11+WSL2+Docker......
  • 打卡信奥刷题(70)用Scratch图形化工具信奥P1149 [NOIP2008 提高组] 火柴棒等式
    [NOIP2008提高组]火柴棒等式题目描述给你nnn根火柴棍,你可以拼出多少个形如A+......
  • 2024三款最佳的MySQL SQL工具,DBA必备神器
    随着数据库管理需求的不断提升,DBA需要强大的工具来优化查询、管理数据库和提高工作效率。以下是2024年三款最佳的MySQLSQL工具,推荐给所有DBA。1.SQLynxSQLynx 是一款功能强大的MySQL管理工具,以其高效的图形用户界面和丰富的功能深受DBA喜爱。优点:直观的GUI......
  • Leetcode1161. 最大层内元素和
    EverydayaLeetcode题目来源:1161.最大层内元素和解法1:层序遍历每次以「层」为单位进行拓展,统计该层的元素和,维护处理过程中的最大值层数和,以及层深度。代码:/**@lcapp=leetcode.cnid=1161lang=cpp**[1161]最大层内元素和*///@lccode=start/***......
  • redis做为缓存,mysql的数据如何与redis进行同步呢?
    让我们一步步来实现如何让MySQL数据库的数据和Redis缓存保持同步。想象一下,MySQL是一个大仓库,存放着所有重要的货物(数据),而Redis则像是一个快速取货窗口,让你能更快拿到常用的东西。为了让两者保持一致,我们需要搭建一座桥梁,让仓库里的变动能及时反映到取货窗口。第一步:理解同步......
  • Could not find artifact com.mysql:mysql-connector-j:pom:8.0.36 in central (https
    遇到修改依赖项的MySQL版本结果说找不到依赖项解决方法确保MySQL版本正确降低依赖项的MySQL版本,修改后更新即可以我的MySQL版本举例,可以降低MySQL版本到依赖项支持的版本<dependency><groupId>com.mysql</groupId><artifactId>m......
  • 安装MySQL数据库时遇到sample Databases,select databases that should be created:有
    SakilaDatabase:Sakila是一个经典的示例数据库,设计用于模拟电影租赁服务的业务流程。Sakila数据库包含电影、顾客、租赁、支付等表,可以用于练习SQL查询和了解数据库的关系模型。如果你想练习处理类似于电影租赁等实际业务场景的查询和数据操作,选择创建Sakila数据库是一......