IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 大数据 -> 缓存和db数据不一致问题(常被忽略的问题) -> 正文阅读

[大数据]缓存和db数据不一致问题(常被忽略的问题)

环境:

  • window10
  • vs2022
  • .net core 3.1

前言:
缓存是个好东西,转为解决高并发问题,在性能的这场较量中屡试不爽。但我们使用它的姿势可能并不对,甚至能给自己挖一个大坑。

参考:

《Redis缓存一致性问题解决方案》

1. 问题举例

以最常见的redis缓存举例,看下面的伪代码:

public class TestClass
{
    private Redis redis;
    private DB db;
    public UserEntity GetUserById(int id)
    {
        UserEntity user = null;
        var key = $"user:{id}";
        //1. 先从redis查缓存
        if (redis.Get<UserEntity>(key) == null)
        {
            //2. 没查到 从db中查询
            user = db.Select<UserEntity>($"select * from user where id={id}");
            //5. 缓存查询结果
            redis.SetString(key, user.ToJson());
        }
        return user;
    }

    public void UpdateUser(UserEntity user)
    {
        var key = $"user:{user.Id}";
        //3. 更新db
        db.Execute($"update user set Name='{user.Name}' where id={user.Id}");
        //4. 刷新缓存
        redis.Delete(key);
    }
}

上面的代码有问题:有可能造成数据库和缓存数据不一致情况。

按照上面注释中的标记的顺序理解,我们就会发现问题所在:
在这里插入图片描述
上面说的是分布式下redis缓存的情况,那么单机呢?单机应该没这个问题吧?

答:把上图中的程序A、程序B换成 线程A和线程B。。。

那把Redis改成程序内存呢?

答:假装上图中的redis是嵌在程序内的呢,和放在外面不是一个道理吗。。。

那么问题的本质是什么?

本质是:多线程环境下,对缓存和数据库有双写的情况。我们无法保证“5. 缓存查询结果”这一步写入的是最新的DB数据!!!

既然这样,那么我们在程序中加个锁不就行了吗?
这种想法不可取,在查询中加锁吗?查询变成单线程的了?

2. 解决方案

那么,有解决办法吗?
有,参照数据库的主从复制架构,看下面的架构图:

在这里插入图片描述

  • 当查询时:

    首先从cache中查询,查询失败后,拼接查询sql并将查询sql和key发送到队列,程序本身要临时从db中查询返回;
    消费者接到缓存请求后,执行sql并将结果以key存到redis中,等待下次使用;

  • 当写入是:

    程序先更新db数据,然后发送刷新cache请求;
    消费者接到刷新cache请求后,就将redis中对应的key删掉或更新key对应的值(sql重新执行一遍);

现在来看看是否会有缓存和db数据不一致问题?
没有了吧(当然,如果程序意外挂掉仍然会有问题,比如:"a. 更新DB"刚执行完,程序就crash了,"b. 发送清空某个key请求"还没来得及执行)。

  大数据 最新文章
实现Kafka至少消费一次
亚马逊云科技:还在苦于ETL?Zero ETL的时代
初探MapReduce
【SpringBoot框架篇】32.基于注解+redis实现
Elasticsearch:如何减少 Elasticsearch 集
Go redis操作
Redis面试题
专题五 Redis高并发场景
基于GBase8s和Calcite的多数据源查询
Redis——底层数据结构原理
上一篇文章      下一篇文章      查看所有文章
加:2022-03-04 15:39:43  更:2022-03-04 15:41:48 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 9:25:01-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码