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

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

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

然后等待下次发生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. Rocket - tilelink - Fragmenter

    https://mp.weixin.qq.com/s/kNQrhlf33AErK7IzalnUDw   简单介绍Fragmenter的实现.   ​​   1. 基本介绍   用于把上游节点地址空间范 ...

  2. 面试题:我们重写一个对象的时候为什么要同时重写hashcode()和equals()方法

    个人博客网:https://wushaopei.github.io/    (你想要这里多有) 在创建的类不重写hashCode()和equals() 方法时,默认使用 java 提供的 java.l ...

  3. 高性能可扩展mysql 笔记(四)项目分区表演示

    个人博客网:https://wushaopei.github.io/    (你想要这里多有) 登录日志的分区 如何为Customer_login_log表分区? 从以下两个业务场景入手: 用户每次登 ...

  4. ansible取出register变量中最长字符串

    背景 在用ansible撰写一个etcd恢复的playbook时,有一个操作是获取etcd启动时的"initial-cluster"启动参数,该参数在etcd集群不同节点不一致,需 ...

  5. Java实现 蓝桥杯 算法训练VIP 报数(暴力+数学)约瑟夫环问题

    试题 算法训练 报数 问题描述 现有n个同学站成一圈,顺时针编号1至n.从1号同学开始顺时针1/2报数,报到1的同学留在原地,报到2的同学退出圆圈,直到只剩一名同学为止.问最后剩下的同学编号. 输入格 ...

  6. Java实现蓝桥杯 算法训练 ALGO-15 旅行家的预算

    问题描述 一个旅行家想驾驶汽车以最少的费用从一个城市到另一个城市(假设出发时油箱是空的).给定两个城市之间的距离D1.汽车油箱的容量C(以升为单位).每升汽油能行驶的距离D2.出发点每升汽油价格P和沿 ...

  7. Java实现 蓝桥杯 算法训练 审美课

    算法训练 审美课 时间限制:1.0s 内存限制:256.0MB 提交此题 问题描述 <审美的历程>课上有n位学生,帅老师展示了m幅画,其中有些是梵高的作品,另外的都出自五岁小朋友之手.老师 ...

  8. Java实现 蓝桥杯 基础练习 杨辉三角形

    基础练习 杨辉三角形 时间限制:1.0s 内存限制:256.0MB 提交此题 锦囊1 锦囊2 问题描述 杨辉三角形又称Pascal三角形,它的第i+1行是(a+b)i的展开式的系数. 它的一个重要性质 ...

  9. Java实现 LeetCode 378 有序矩阵中第K小的元素

    378. 有序矩阵中第K小的元素 给定一个 n x n 矩阵,其中每行和每列元素均按升序排序,找到矩阵中第k小的元素. 请注意,它是排序后的第k小元素,而不是第k个元素. 示例: matrix = [ ...

  10. 数据结构&算法

    20个最常用.最基础数据结构与算法: 10个数据结构:数组.链表.栈.队列.散列表.二叉树.堆.跳表.图.Trie 树. 10个 算法      :递归.排序.二分查找.搜索.哈希.贪心.分治.回溯. ...