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 小米 华为 单反 装机 图拉丁
 
   -> 大数据 -> 关于缓存一致性的一些介绍 -> 正文阅读

[大数据]关于缓存一致性的一些介绍

当系统引入缓存的时候,同时也就会引入数据库和缓存数据不一致的问题,因为两个数据,不管是先更新哪一个,这两个操作之间都会有一定的时间差,在高并发的情况下,就会有读取数据不一致,甚至会导致数据错误的问题。

一些缓存方案

一般来说处理缓存数据的方案有这样几种:

  • 全量缓存,靠定时任务去同步缓存;
  • 先更新缓存,再更新数据库;
  • 先更新数据库,再更新缓存;
  • 先删除缓存,再更新数据库;
  • 先更新数据库,再删除缓存;

全量更新

这种方式很简单无脑,就是直接将数据库中的数据全都存放到缓存中,然后通过后台的定时任务定时去更新缓存数据,读数据的时候直接读缓存,写的时候就写数据库,简单高效,但是也存在着很多问题:

  • 数据冗余,很多无效数据也都会再缓存中,占用内存空间,当数据量大的时候这部分开销就不容忽视了;
  • 数据不一定,因为依靠的是定时任务定时去更新数据,也就是说在下次定时任务之前,读到的都是老数据;
  • 如果更新数据较多,且定时任务执行比较频繁,可能出现上一次的任务还没执行完成,下一次的任务就开始了。
    所以这种方式只适合数据体量比较小,且数据更新不太频繁的场景。

先更新缓存,再更新数据库

首先要明确这是两个操作,并且这两个操作不具备原子性,也就是说可能出现一个操作执行失败,另一个操作执行成功的情况。
如果先更新缓存执行成功了,但是更新数据库执行异常了,这样当缓存中的数据被淘汰清除之后,就会导致数据丢失了,显然这种问题是不能被接受的。
并且我们还要考虑并发问题,假设两个线程的执行顺序是这样的:

  • 线程A执行了更新缓存操作;
  • 线程B执行了更新缓存操作;
  • 线程B执行了更新数据库操作;
  • 线程A执行了更新数据库操作;
    这样缓存和数据库中的数据就不一致的,我们在缓存中读到的永远都是旧数据(线程A更新的数据)。

先更新数据库,再更新缓存

这种跟先更新缓存区别不大,也会导致数据不一样,但是不会有数据丢失的情况,毕竟是先更新的数据库,失败了就是失败了,也会返回失败的结果。

先删除缓存,再更新数据库

因为少了一次更新操作,数据都是从数据库中读取的,所以少了两次更新操作带来的数据不一致的问题,但是它还是有并发问题,假设两个线程的执行顺序是:

  • 线程A删除了缓存;
  • 线程B读取缓存,发现缓存中没有数据,就从数据库中读取了;
  • 线程B将读到的数据写入了缓存中;
  • 线程A更新了数据库。
    这样就导致了数据不一致,缓存中是旧数据,且一直都是旧数据,系统读到的也是旧数据直到缓存失效重新从数据库中读取数据。

先更新数据库,再删除缓存

这种方式其实也有并发问题,比如:

  • 缓存中先是没有数据的,线程A从数据库中读取了数据;
  • 线程B更新了数据库,并且删除了缓存数据;
  • 线程A将原来的数据写到了缓存中。

但是这种情况产生的概率会小一些,要满足多种条件:

  • 缓存原先是没有数据的或者缓存刚好失效;
  • 刚好有读写并发;
  • 线程A的两个操作时间间隔很长,而一般情况下,数据库的读操作要比写操作要快(涉及到加锁什么的),所以这个条件是不太容易满足的。

所以先更新数据库,再删除缓存是我们一般选择的方式,但是其实这种方式也是有问题:当删除缓存失败的时候,也会导致数据不一致的,缓存中的数据是旧数据,所以这里需要引入重试机制,比如可以向mq中发送一条删除缓存的消息,做一个异步重试删除缓存的操作,或者还有一个方案就是订阅数据库的binlog日志,应用程序专门订阅binlog日志,根据binlog日志的变化来维护缓存中的数据,阿里的canal中间件就提供了订阅binlog日志的功能。

缓存延迟双删策略

因为先更新数据库,再删除缓存也会有数据不一致的情况,所以有人就提出了延迟双删策略,就是你不是会把旧值写入缓存吗,那我就延迟一些,等下再来删除一次缓存,这样就能保证下次读取到的肯定是新值了,但是这个延迟时间不太好评估,需要根据实际项目去评判了。

  大数据 最新文章
实现Kafka至少消费一次
亚马逊云科技:还在苦于ETL?Zero ETL的时代
初探MapReduce
【SpringBoot框架篇】32.基于注解+redis实现
Elasticsearch:如何减少 Elasticsearch 集
Go redis操作
Redis面试题
专题五 Redis高并发场景
基于GBase8s和Calcite的多数据源查询
Redis——底层数据结构原理
上一篇文章      下一篇文章      查看所有文章
加:2022-03-17 22:14:33  更:2022-03-17 22:15:18 
 
开发: 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 6:19:13-

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