Redis系列 - Redis缓存更新:先更新数据库还是先更新缓存?

2023-10-29

Redis系列 - Redis缓存更新:先更新数据库还是先更新缓存?

在更新缓存时,对于更新完数据库,是更新缓存呢,还是删除缓存。又或者是先删除缓存,再更新数据库,其实都会存在一定的问题。

Cache Aside Pattern(旁路缓存模式)

这是最常用的缓存使用方式了。其具体逻辑如下

  • 失效:应用程序先从cache取数据,没有得到,则从数据库中取数据,成功后,放到缓存中。
  • 命中:应用程序从cache中取数据,取到后返回。
  • 更新:先把数据存到数据库中,成功后,再让缓存失效。

我们更新时是先更新数据库,数据库更新成功后再让缓存失效。那么这种方式真的没有问题么?

我们可以考虑一下以下的并发场景:

  1. 缓存key1刚好失效
  2. 请求A发起读请求没有命中缓存去数据库查询,此时查询出来的结果是老的数据
  3. 请求B发起更新请求,先更新数据库,
  4. 请求B让缓存失效
  5. 此时请求A将步骤2中读取出来的老数据写入缓存

以上的并发场景理论上确实会发生导致脏数据的产生,但是在实际的生产环境中出现的概率非常低,因为这个条件需要发生在读缓存时缓存失效,而且并发着有一个写操作。而实际上数据库的写操作会比读操作慢得多,而且还要锁表,而读操作必需在写操作前进入数据库操作,而又要晚于写操作更新缓存,所有的这些条件都具备的概率基本并不大。

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

改方案会导致数据不一致的原因如下:

  1. 请求A进行写操作,删除缓存(并更新数据库,此时还没更新)
  2. 请求B查询发现缓存不存在
  3. 请求B去数据库查询得到旧的值
  4. 请求B将旧的值写入缓存
  5. 此时请求A将新值更新进数据库

这种情况下如果缓存不被更新或者被过期策略淘汰,那么这个数据将永远是脏数据。

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

我们可以看下以下的并发场景:

  1. 线程A和线程B同时去更新数据key1
  2. 线程A更新了数据库数据key1,此时value1
  3. 线程A更新了数据库数据key1,此时value2(最新的数据)
  4. 线程B更新的缓存key1的值为value2
  5. 线程A更新的缓存key1的值为value1

由于线程A的更新数据库操作早于线程B,线程B更新的结果value2才是最新的结果,最终应该把value2放入缓存才符合实际的需求。但是因为网络等原因,B却比A更早更新了缓存。这就导致了脏数据,因此这种方案存在线程安全问题。

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

该方案不做考虑,若先更新缓存,缓存更新成功,但是更新数据库时发生异常导致回滚,那么缓存中的数据无法回滚,导致数据不一致。

 

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Redis系列 - Redis缓存更新:先更新数据库还是先更新缓存? 的相关文章

  • 带 Java 客户端的键值数据库

    我基本上想在磁盘上存储一个哈希表 以便以后可以查询它 我的程序是用Java 编写的 哈希表从字符串映射到列表 那里有很多键值存储 但经过大量研究 阅读后 尚不清楚哪一个最适合我的目的 以下是一些对我来说很重要的事情 简单的键值存储 允许您使
  • 在节点中使用redis获取hash key的所有字段和值

    红色是使用哈希 我需要存储具有多个字段和值的哈希键 我尝试如下 client hmset Table1 Id 9324324 ReqNo 23432 redis print client hmset Table1 Id 9324325 Re
  • 是否可以使用带有 FUSE 文件系统的 Linux VFS 缓存?

    默认情况下 Linux VFS 缓存似乎不适用于 FUSE 文件系统 例如 read 调用似乎被系统地转发到 FUSE 文件系统 我在 FUSE 特定的远程文件系统上工作 我需要一个非常积极的缓存 我需要实现自己的页面缓存吗 或者是否可以为
  • 连接到 localhost:6379 时出现错误 99。无法分配请求的地址

    设置 我有一个虚拟机 并在虚拟机中运行三个容器 一个 nginx 代理 一个非常简约的 Flask 应用程序和 redis Flask 应在端口 5000 上提供服务 而 redis 应在 6379 上提供服务 这些容器中的每一个都可以作为
  • Redis部署配置-主从复制

    目前我有两台服务器 我已经部署了基于node js Express JS的Web服务API 我正在使用 Redis 来缓存 JSON 字符串 将此设置部署到生产中的最佳选择是什么 我懂了here https stackoverflow co
  • AWS Redis 从外部连接

    有没有办法从外部 AWS 网络连接 AWS 上托管的 Redis 实例 我有一个基于 Windows 的 EC2 实例在 AWS 上运行 另一个是 Redis 缓存节点 我知道有人问过这个问题 但答案是在基于 Linux 的系统中 但我的是
  • 使用 EVAL、SCAN 和 DEL 的 Redis 通配符删除脚本返回“非确定性命令后不允许写入命令”

    因此 我正在寻求构建一个 lua 脚本 该脚本使用 SCAN 根据模式查找键并删除它们 原子地 我首先准备了以下脚本 local keys local done false local cursor 0 repeat local resul
  • 如何在redis中创建自己的数据库?

    There are 0 to 15 databases in redis 我想使用 redis cli 创建自己的数据库 有什么命令可以实现吗 Redis 数据库并不等同于 MySQL 等 DBMS 中的数据库名称 这是一种为键创建隔离和命
  • 使用brew在MacOSx上安装Redis JSON

    如何使用brew 在 macOSx 上安装 RedisJSON 如何在不编译redis的情况下启用redis上的模块 我不想使用 docker 客户端 Redis Stack 可能是最简单的方法 它不仅仅是 RedisJSON 还包括 Re
  • Laravel - 缓存 Eloquent 并频繁更新

    是否可以对经常修改的对象使用缓存 例如 假设我们有一个 BlogPost 对象 并且有一个经常更改的 num of views 列 以及其他列 是否可以更新缓存和数据库中的 num of views 字段 而不破坏缓存对象并重新创建它 我可
  • Redis 块推送直到列表有空位

    我正在寻找类似的东西BLPUSH该命令将阻塞 直到列表的长度低于指定值max size 目的是防止生产者运行速度快于消费者时列表无限增长 功能与 python 非常相似Queue put https docs python org 3 li
  • 我的 Redis 自动生成的密钥

    我不知道我的 Redis 版本 4 0 9 到底发生了什么 我正在运行一个应用程序并使用 Redis 来存储我的数据库 但是 然后 Redis 自动创建 3 个新键 Backup1 Backup2 Backup3 并删除我的所有数据 这是我
  • 仅当尚未设置时才进行原子设置

    仅当尚未在 Redis 中设置时 是否有办法执行原子设置 具体来说 我正在创建一个像 myapp user user email 这样的用户 并且希望 Redis 在 user email 已被占用时返回错误 而不是默默地替换旧值 比如声明
  • 如何让客户端下载动态生成的非常大的文件

    我有一个导出功能 可以读取整个数据库并创建一个包含所有记录的 xls 文件 然后文件被发送到客户端 当然 导出完整数据库的时间需要大量时间 并且请求很快就会以超时错误结束 处理这种情况的最佳解决方案是什么 例如 我听说过使用 Redis 创
  • Redis hash写入速度非常慢

    我面临一个非常奇怪的问题 使用 Redis 时 我的写入速度非常糟糕 在理想的情况下 写入速度应该接近 RAM 上的写入速度 这是我的基准 package redisbenchmark import redis clients jedis
  • Caffeine Expiry 中如何设置多个过期标准?

    我正在使用 Caffeine v2 8 5 我想创建一个具有可变到期时间的缓存 基于 值的创建 更新以及 该值的最后一次访问 读取 无论先发生什么都应该触发该条目的删除 缓存将成为三层值解析的一部分 The key is present i
  • SignalR 无法连接到 SSL 上的 Azure Redis

    我目前在 Azure 上托管我的 redis 缓存服务器 并让 signalR 依赖它作为骨干 使用以下内容 GlobalHost DependencyResolver UseRedis 服务器 端口 密码 eventKey 这可以在端口
  • socket.io 广播功能 & Redis pub/sub 架构

    如果有人能帮助我解决一个小疑问 我将不胜感激 使用socket io广播功能和在Redis上使用pub sub设计架构有什么区别 例如 在另一个示例中 node js 服务器正在侦听 socket io 针对 键 模型 todo 和值 数据
  • Redis Docker compose无法处理RDB格式版本10

    我无法在 docker compose 文件中启动 redis 容器 我知道docker compose文件没问题 因为我的同事可以成功启动项目 我读到有一个删除 dump rdb 文件的解决方案 但我找不到它 我使用Windows机器 任
  • 如何在Redis中进行持久化存储?

    关闭redis服务器后 使用set存储的值被破坏 在这里我找到了使用持久性存储的方法 有人帮助我 如何使用javascript实现这一点 我想将客户端的一些值存储在 redis 数据库中 并且必须在其他客户端中使用该值 您需要配置 Redi

随机推荐

  • STM32 嵌入式开发常用网站推荐

    作者 蚂蚁会游泳 日期 2022 06 11 前言 本文推荐了一些做嵌入式软硬件开发常用到的网站 一 资料下载 正点原子资料下载中心 描述 该网站可以下载正点原子各种开发板的软件资料 网址 http www openedv com docs
  • 机器学习——特征工程和评价指标

    0 前言 首先学习特征工程这部分知识之前 要对机器学习的算法用过使用 1 特征工程 就机器学习的数据而言 特征就是数据的列名 有多少列 就有多少个维度的特征 就定义而言 特征是指数据中抽取出来对结果预测有用的信息 特征工程就是使用一些技巧来
  • 64位java8,jdk8下载,解压版

    JAVA8使用量非常广泛 但是找下往往都是安装版的 想我这种人直接自己配置环境变量用 十分不想搞个安装版 下面是解压版的 下面是打印出的version信息 wndows版本的 下面是java version的信息 直接拿走 java ver
  • 关于在linux(Ubuntu 18.04.1 LTS)环境中安装并使用AppImageLauncher

    安装步骤 1 去github上下载AppImageLauncher deb 文件 2 在下载文件所在文件夹下打开终端输入 sudo dpkg f filename deb 3 报错提示缺少依赖项 则继续输入一下内容 sudo apt get
  • 大数据 爬取网站并分析数据

    大数据 爬取前程无忧校园招聘 flume hive mysql 数据可视化 自己搭建的hadoop博客 1 爬取前程无忧网页和校园招聘 1 1用scrapy爬取前途无忧网站 我爬了10w多条数据 在存入MongoDB中 1 2 存入Mogo
  • JSP弹出对话框两种实现方式

    JSP弹出对话框两种实现方式 1 一种是弹出一个新的窗体出来 window open test html 用于控制弹出新的窗口test html 如果test html不与主窗口在同一路径下 前面应写明路径 绝对路径 http 和相对路径
  • 【NOIP 2004 提高组】合并果子

    题就自己找啦 各大OJ上应该都有 题目 题目描述 在一个果园里 多多已经将所有的果子打了下来 而且按果子的不同种类分成了不同的堆 多多决定把所有的果子合成一堆 每一次合并 多多可以把两堆果子合并到一起 消耗的体力等于两堆果子的重量之和 可以
  • NewMoonDog 影子狗 基于JavaScript的跑酷游戏,复制就能玩

    这是一款横版跑酷类游戏 应为是JavaScript的所以不需要其他复杂的配置和环境 点击就能运行 线上试玩 http longsong games newmoon 文末有代码地址 操作介绍 跳跃 坐下 跳砍 往后跑 向前跑 enter 无敌
  • Python-pandas的基础函数

    zstarling 基础 进阶 多表处理 索引index 的用途 基础 import pandas as pd list1 001 002 003 df pd Series list1 df2 df map int print df2 df
  • 15_Numpy使用sort和argsort函数进行(行・列)排序

    15 Numpy使用sort和argsort函数进行 行 列 排序 如果将NumPy函数numpy sort 应用于二维NumPy数组ndarray 则可以获得一个ndarray 其中每一行和每一列的值都按升序分别排序 如果要按特定的行或列
  • Neo4j入门(五)删除节点的正确姿势

    本文还是照例讲讲自己工作中遇到的坑 本文将会讲述如何在Neo4j中正确地删除节点 图数据库在删除节点的时候 并不像删除属性和删除关系那样方便 原因就在于删除节点时 可能有关系与之相连 因此需要考虑这个问题 Neo4j在删除节点时 已经考虑了
  • centos下升级python

    wget http www python org ftp python 2 6 Python 2 6 tgz tar zxvf Python 2 6 tgz cd Python 2 6 configure enable ipv6 prefi
  • 你知道豆瓣电影是怎么评分的吗?(实战篇—手把手教你分析豆瓣电影)

    点赞再看 养成好习惯 Python版本3 8 0 开发工具 Pycharm 写在前面的话 如果你是因为看到标题进来的 那恭喜你 又多了一个涨 入 知 坑 识的机会 在这篇豆瓣电影Top250的分析文章中 你并不会得到一个像标题那样确切的答案
  • java 代码 导出表结构生成doc文档(支持MySQL,Oracle)

    1 导入依赖
  • JetBrains全家桶安装配置:基于macOS M1

    一 JetBrains全家桶 官网下载地址 JetBrains官网 安装步骤 第一步 第二步 插件市场 第三步 第四步 IDE Eval Reset 插件安装 第五步 Auto reset before per restart 二 支持产品
  • QLlistwidget 自定义item 并获取 item上的内容

    如上面这个界面 添加一个自定义 item 第一行 1 自定义item 在item中添加一个lable 和 按钮 QWidget widget1 new QWidget ui gt listWidget QHBoxLayout layout
  • conda安装fbprophet注意事项

    注意 截止目前 2022年06月19日 fbprophet支持python 3 8及已下版本 安装 步骤1 conda install pystan 步骤2 conda install c conda forge fbprophet 步骤3
  • 基于TensorFlow的模型和训练的自定义方法(附源码)

    文章目录 自定义模型和训练 1 Define the Model 2 Define Optimizer and Loss 3 Evaluate Untrained Model 4 Define Metrics 5 Apply Gradien
  • 万代南梦宫假面骑士时尚品牌HENSHIN by KAMEN RIDER首登中国;安宏资本宣布与资生堂达成协议

    美国啤酒花供应商在比利时建立新的欧洲营运中心 总部位于华盛顿雅基玛的种植商拥有的最大啤酒花供应商Yakima Chief Hops YCH 已完成在比利时最先进的存储仓库建设 以更好地服务于全球酿造社区 向欧洲的扩张将大大改善YCH的客户体
  • Redis系列 - Redis缓存更新:先更新数据库还是先更新缓存?

    Redis系列 Redis缓存更新 先更新数据库还是先更新缓存 在更新缓存时 对于更新完数据库 是更新缓存呢 还是删除缓存 又或者是先删除缓存 再更新数据库 其实都会存在一定的问题 Cache Aside Pattern 旁路缓存模式 这是