如何保证MySQL和Redis数据一致性?
背景
在高并发的业务场景中,因为MySQL数据库是操作磁盘效率比较低,因此大多数情况下数据库都是高并发系统的瓶颈。因为Redis操作数据是在内存中进行,所以就需要使用Redis做一个缓存。让请求先访问到Redis,而不是直接访问MySQL数据库。效果图如下

查询数据
上面的业务场景,就是一个典型的MySQL存储数据和Redis缓存数据的业务场景。下面来看看一般的查询流程,如下图:

上面的查询流程如下:
用户请求系统,系统先查询Redis中是否有数据? 如果Redis中有数据,则直接将缓存中的数据响应给用户。 如果Redis中没有数据,则取查询MySQL数据库中是否有数据? 如果MySQL中有数据,则先将数据更新到Redis中,再将数据响应给用户。 如果MySQL中没有数据,则响应空数据给用户,请求结束。
上面的查询流程很简单,通过先查Redis缓存,避免大量请求访问MySQL数据库,从而大大提高系统响应效率。而且如果Redis中没有而MySQL中有,当从MySQL拿到数据以后,先将数据更新到Redis缓存中,这样下次请求同一份数据的时候就能从Redis中获取了。
更新数据
上面的查询流程是没什么问题,可是数据很有可能会更新。那么更新的时候怎么操作才能保证Redis和MySQL中的数据都更新成功并且一致呢?
下面看看一种常用的解决方案(双删缓存):

第一个问题:为什么是删除Redis缓存数据而不是更新数据?
假设我们缓存的数据是要做一个很复杂的计算,而且还不一定能用到。那如果你更新MySQL数据之后去更新Redis缓存不是就很耗时了,而且有可能做无用功。
第二个问题:为什么是先删除Redis缓存数据而不是先更新数据库呢?
我们不妨假设先更新MySQL中的数据,然后再删除缓存。如果更新完MySQL但是删除Redis失败了(别问为什么会失败?系统故障行不行,全球断电行不行?),那下次查询请求过来,因为Redis中有缓存数据,所以直接返回Redis缓存的旧数据了,是不是就出问题了?
那我们再看看,如果先删除Redis缓存,再更新MySQL。如果删除完Redis成功,但是更新MySQL失败。下次查询的时候,查询到Redis缓存发现没有,再去查MySQL,然后更新到Redis,虽然MySQL更新失败了,但是Redis中的数据和MySQL是一致的。
第三个问题:为什么更新完MySQL后还要再删一次Redis缓存呢?
假设我们第一次删完Redis结束,正在更新MySQL但是还没更新成功的时候,这时候有另外一个请求来查询数据。第二个请求查询Redis没有,然后查询MySQL这时候因为MySQL还没更新完,所以查询到的还是旧数据,同时把旧数据更新到Redis中了,等下一个请求再来查询的时候发现Redis有数据,就直接返回旧数据了。
因此更新完MySQL后需要再次删除Redis缓存。这样即使更新数据中间有其他个请求把旧数据更新到Redis中了,因为再次删了Redis缓存中的旧数据,依然能够避免其他请求获取到旧数据。
❝
我们认为数据是否更新成功是以MySQL中的数据为准,因此MySQL还没更新完成前或者更新失败,获取到旧数据不算是问题。所以我们只要保证Redis和MySQL中的数据一致就行。
❞
如何保证MySQL和Redis数据一致性?的更多相关文章
- Mysql和Redis数据如何保持一致
先阐明一下Mysql和Redis的关系:Mysql是数据库,用来持久化数据,一定程度上保证数据的可靠性:Redis是用来当缓存,用来提升数据访问的性能. 关于如何保证Mysql和Redis中的数据一致 ...
- 电商中的库存管理实现-mysql与redis
库存是电商系统的核心环节,如何做到不少卖,不超卖是库存关心的核心业务问题.业务量大时带来的问题是如何更快速的处理库存计算. 此处以最简模式来讨论库存设计. 以下内容只做分析,不能直接套用,欢迎 ...
- Gearman + Nodejs + MySQL UDF异步实现 MySQL 到 Redis 的数据同步
[TOC] 1, 环境 CentOS, MySQL, Redis, Nodejs 2, Redis简介 Redis是一个开源的K-V内存数据库,它的key可以是string/set/hash/list ...
- 06 python操作MySQL和redis(进阶)
python操作mysql.redis 阶段一.mysql事务 主要用于处理操作量大,复杂度高的数据.比如说,在人员管理系统中,你删除一个人员,你即需要删除人员的基本资料,也要删除和该人员相关的信息, ...
- PHP商品秒杀问题解决方案实例详解【mysql与redis】
本文实例讲述了PHP商品秒杀问题解决方案.分享给大家供大家参考,具体如下: 引言 假设num是存储在数据库中的字段,保存了被秒杀产品的剩余数量. if($num > 0){ //用户抢购成功,记 ...
- linux安装和配置 mysql、redis 过程中遇到的问题记录
linux下部署mysql和redis网上的教程很多,这里记录一下我部署.配置的过程中遇到的一些问题和解决办法. mysql ①安装完成后启动的时候报错 Starting MySQL.The serv ...
- Mysql与Redis的同步实践
一.测试环境在Ubuntu kylin 14.04 64bit 已经安装Mysql.Redis.php.lib_mysqludf_json.so.Gearman. 点击这里查看测试数据库及表参考 本文 ...
- 通过Gearman实现MySQL到Redis的数据同步
对于变化频率非常快的数据来说,如果还选择传统的静态缓存方式(Memocached.File System等)展示数据,可能在缓存的存取上会有很大的开销,并不能很好的满足需要,而Redis这样基于内存的 ...
- 一步完成 MySQL 向 Redis 迁移
从mysql搬一个大表到redis中,你会发现在提取.转换或是载入一行数据时,速度慢的让你难以忍受.这里我就要告诉一个让你解脱的小技巧.使用“管道输出”的方式把mysql命令行产生的内容直接传递给re ...
- MySQL to Redis
[TOC] 简介 使用mysql2redis可以非常便捷的将mysql中的数据导出到redis中去, 通常是需要一个select语句即可实现. 软件安装 // 安装apr + apr-util $ w ...
随机推荐
- P1536 村村通(并查集)
村村通 题目描述 某市调查城镇交通状况,得到现有城镇道路统计表.表中列出了每条道路直接连通的城镇.市政府 "村村通工程" 的目标是使全市任何两个城镇间都可以实现交通(但不一定有直接 ...
- 【Android 逆向】【攻防世界】APK逆向
1. apk安装到手机,提示输入flag 2. jadx打开apk 定位到checkSN方法 public boolean checkSN(String userName, String sn) { ...
- 关于Image的mode属性(多图示例)
一.总览 Image的mode是指图片裁剪.缩放的模式,共有14个合法值,分别是: /** 缩放模式,不保持纵横比缩放图片,使图片的宽高完全拉伸至填满 image 元素 */ scaleToFill ...
- PrettyTable模块
# 用来生成美观的ASCII格式的表格 pip install prettytable # 导入 from prettytable import PrettyTable # 使用 tb = pt.Pr ...
- 【LeetCode剑指offer#06】实现pow函数、计算x的平方根
实现pow函数 实现 pow(x, n) ,即计算 x 的整数 n 次幂函数(即,xn ). 示例 1: 输入:x = 2.00000, n = 10 输出:1024.00000 示例 2: 输入:x ...
- 【LeetCode滑动窗口专题】水果成篮 + 最小覆盖子串(hard)+ 字符串的排列
二刷刷到滑动窗口,发现有一些细节和遗漏,在此补充 实际上关于滑动窗口的题还有一题:最小长度的子数组 进入正题 水果成篮 LeetCode904水果成篮 你正在探访一家农场,农场从左到右种植了一排果树. ...
- Java 重写引入
1 package com.bytezero.override; 2 /* 3 * 方法的重新(override/overwrite) 4 * 5 * 1.重写:子类继承父类以后,可以对父类中同名同参 ...
- [VueJsDev] 基础知识 - Button的全局节流
[VueJsDev] 目录列表 https://www.cnblogs.com/pengchenggang/p/17037320.html Button的全局节流 ::: details 目录 目录 ...
- live [lɪv , laɪv] 动词读lɪv 形容词读laɪv
live [lɪv , laɪv] 动词读lɪv 形容词读laɪv live 英 [lɪv , laɪv] 美 [lɪv , laɪv] v. 居住;住;生存;(尤指在某时期)活着;(以某种方式)生活 ...
- masscode.io snippets 和 vscode 联动 代码片段
https://masscode.io/ 软件作用 代码片段 vscode 可以联动使用 下载不行 慢的话, 下载 fastgithub,打开后再下载