为什么对缓存只删除不更新

不更新缓存是防止并发更新导致的数据不一致。

所以为了降低数据不一致的概率,不应该更新缓存,而是直接将其删除,

然后等待下次发生cache miss时再把数据库中的数据同步到缓存。

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

有两个选择:

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

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

如果先删除缓存,有一个明显的逻辑错误:考虑两个并发操作,线程A删除缓存后,线程B读该数据时会发生Cache Miss,然后从数据库中读出该数据并同步到缓存中,此时线程A更新了数据库。

结果导致,缓存中是老数据,数据库中是新数据,并且之后的读操作都会直接读取缓存中的脏数据。(直到key过期被删除或者被LRU策略踢出)

如果数据库更新成功后,再删除缓存,就不会有上面这个问题。

可能是由于数据库优先,第二种方式也被称为Cache Aside Pattern。

Cache Aside Pattern

cache aside在绝大多数情况下能做到数据一致性,但是在极端情况仍然存在问题。

  • 首先更新数据库(A)和删除缓存(B)不是原子操作,任何在A之后B之前的读操作,都会读到redis中的旧数据。

    但是,正常情况下操作缓存的速度会很快,通常是毫秒级,出现上述情况的概率很低。
  • 更新完数据库后,线程意外被kill掉,由于没有删除缓存,缓存中的脏数据会一直存在。
  • 线程A读数据时cache miss,从Mysql中查询到数据,还没来得及同步到redis中,

    此时线程B更新了数据库并把Redis中的旧值删除。随后,线程A把之前查到的数据同步到了Redis。

    显然,此时redis中的是脏数据。

    通常数据库读操作比写操作快很多,所以除非线程A在同步redis前意外卡住了,否则发生上述情况的概率极低。

虽然以上情况都有可能发生,但是发生的概率相比“先删除缓存再更新数据库”会低很多。

Read/Write Through Pattern

cache aside是我们自己的应用程序维护两个数据存储系统,而Read/Write Through Pattern是把同步数据的问题交给缓存系统了,应用程序不需要关心。

Read Through是指发生cache miss时,缓存系统自动去数据库加载数据。

Write Through是指如果cache miss,直接更新数据库,然后返回,如果cache hit,则更新缓存后,由缓存系统自动同步到数据库。

以Redis为例,通常我们不会把数据库的数据全部缓存到redis,而是采用一定的数据精简或压缩策略,以节省缓存空间。

就是说,让缓存系统设计出通用的缓存方案不太现实,不过根据自己的业务定制一个在项目内部通用的中间件是可行的。

Write Behind

Write Behind方案在更新数据时,只更新缓存,不更新数据库。而是由另外一个服务异步的把数据更新到数据库。

逻辑上,和Linux中的write back很类似。这个设计的好处是,I/O操作很快,因为是纯内存操作。

但是由于异步写库,可能要牺牲一些数据一致性,譬如突然宕机会丢失所有未写入数据库的内存数据。

阿里巴巴的Canal中间件是一种相反的设计,它先更新mysql,然后通过binlog把数据自动同步到redis。

这种方案会全量同步数据到redis,不适合只缓存热点数据的应用。

总结

以上没有哪种方案是完美的,都无法做到强一致性。

我们总要在性能和数据准确性之间做出妥协。

https://www.pixelstech.net/article/1562504974-Consistency-between-Redis-Cache-and-SQL-Database

https://coolshell.cn/articles/17416.html

为什么不更新缓存,而是直接删除

Mysql和Redis数据同步策略的更多相关文章

  1. 转载:MySQL和Redis 数据同步解决方案整理

    from: http://blog.csdn.net/langzi7758521/article/details/52611910 最近在做一个Redis箱格信息数据同步到数据库Mysql的功能. 自 ...

  2. redis作为mysql的缓存服务器(读写分离,通过mysql触发器实现数据同步)

    一.redis简介Redis是一个key-value存储系统.和Memcached类似,为了保证效率,数据都是缓存在内存中.区别的是redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录 ...

  3. redis 数据淘汰策略与配置

    redis 数据淘汰策略 volatile-lru:从已设置过期的数据集中挑选最近最少使用的淘汰volatile-ttr:从已设置过期的数据集中挑选将要过期的数据淘汰volatile-random:从 ...

  4. redis数据同步之redis-shake

    redis-shake简介 redis-shake是阿里开源的用于redis数据同步的工具,基本功能有: 恢复restore:将RDB文件恢复到目的redis数据库. 备份dump:将源redis的全 ...

  5. 用 C# 写一个 Redis 数据同步小工具

    用 C# 写一个 Redis 数据同步小工具 Intro 为了实现 redis 的数据迁移而写的一个小工具,将一个实例中的 redis 数据同步到另外一个实例中.(原本打算找一个已有的工具去做,找了一 ...

  6. mysql 集群 数据同步

    mysql集群配置在网站负载均衡中是必不可少的: 首先说下我个人准备的负载均衡方式: 1.通过nginx方向代理来将服务器压力分散到各个服务器上: 2.每个服务器中代码逻辑一样: 3.通过使用redi ...

  7. redis 数据删除策略和逐出算法

    数据存储和有效期 在 redis 工作流程中,过期的数据并不需要马上就要执行删除操作.因为这些删不删除只是一种状态表示,可以异步的去处理,在不忙的时候去把这些不紧急的删除操作做了,从而保证 redis ...

  8. Mysql和Redis数据如何保持一致

    先阐明一下Mysql和Redis的关系:Mysql是数据库,用来持久化数据,一定程度上保证数据的可靠性:Redis是用来当缓存,用来提升数据访问的性能. 关于如何保证Mysql和Redis中的数据一致 ...

  9. Mysql与Redis的同步实践

    一.测试环境在Ubuntu kylin 14.04 64bit 已经安装Mysql.Redis.php.lib_mysqludf_json.so.Gearman. 点击这里查看测试数据库及表参考 本文 ...

随机推荐

  1. [PHP学习教程 - 网络]003.获得当前访问的页面URL(Current Request URL)

    引言:获取当前请求的URL路径,自动判断协议(HTTP or HTTPS). 一句话的事情,下面直接上高清无MSK的精妙代码! 功能函数 获得当前请求的页面路径(URL)地址 语法:$url = ge ...

  2. java方式实现堆排序

    一.堆排序和堆相关概念描述 堆排序是指利用堆这种数据结构所设计的一种排序算法.堆是一个近似完全二叉树的结构,并同时满足堆的性质:即子结点的值总是小于(或者大于)它的父节点,若子结点的值总是小于它的父节 ...

  3. vc程序设计--对键盘与鼠标的响应(1)

    // WindowsProject2.cpp : 定义应用程序的入口点. // /** * 当按下CTRL键时输出信息:CTRL键被压下 * 当按下K键时输出信息:K键被压下 * 当按下CTRL+K键 ...

  4. 【MobileNet-V1】-2017-CVPR-MobileNets Efficient Convolutional Neural Networks for Mobile Vision Applications-论文阅读

    2017-CVPR-MobileNets Efficient Convolutional Neural Networks for Mobile Vision Applications Andrew H ...

  5. itext7史上最全实战总结

    1. itext7史上最全实战总结 1.1. 前言 最近有个需求需要我用Java手动写一份PDF报告,经过考察几种pdf开源代码,最终选取了itext7,此版本为7.1.11,由于发现网上关于该工具的 ...

  6. Java实现 LeetCode 343 整数拆分(动态规划入门经典)

    343. 整数拆分 给定一个正整数 n,将其拆分为至少两个正整数的和,并使这些整数的乘积最大化. 返回你可以获得的最大乘积. 示例 1: 输入: 2 输出: 1 解释: 2 = 1 + 1, 1 × ...

  7. Java实现 洛谷 P1487 陶陶摘苹果(升级版)

    题目描述 又是一年秋季时,陶陶家的苹果树结了n个果子.陶陶又跑去摘苹果,这次她有一个a公分的椅子.当他手够不着时,他会站到椅子上再试试. 这次与NOIp2005普及组第一题不同的是:陶陶之前搬凳子,力 ...

  8. Java实现 蓝桥杯 算法提高金属采集

    问题描述 人类在火星上发现了一种新的金属!这些金属分布在一些奇怪的地方,不妨叫它节点好了.一些节点之间有道路相连,所有的节点和道路形成了一棵树.一共有 n 个节点,这些节点被编号为 1~n .人类将 ...

  9. CentOS8.1操作系下使用通用二进制包安装MySQL8.0(实践整理自MySQL官方)

    写在前的的话: 在IT技术日新月异的今天,老司机也可能在看似熟悉的道路上翻车,甚至是大型翻车现场!自己一个人开车过去翻个车不可怕,可怕的是带着整个团队甚至是整个公司一起翻车山崖下,解决办法就是:新出现 ...

  10. 用mvc框架查询数据库数据

    介绍下mvc框架,mvc框架一种软件设计典范,用一种业务逻辑.数据.界面显示分离的方法组织代码,将业务逻辑聚集到一个部件里面,在改进和个性化定制界面及用户交互的同时,不需要重新编写业务逻辑. 首先我们 ...