背景


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


查询数据


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


上面的查询流程如下:

  1. 用户请求系统,系统先查询Redis中是否有数据?
  2. 如果Redis中有数据,则直接将缓存中的数据响应给用户。
  3. 如果Redis中没有数据,则取查询MySQL数据库中是否有数据?
  4. 如果MySQL中有数据,则先将数据更新到Redis中,再将数据响应给用户。
  5. 如果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数据一致性?的更多相关文章

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

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

  2. 电商中的库存管理实现-mysql与redis

        库存是电商系统的核心环节,如何做到不少卖,不超卖是库存关心的核心业务问题.业务量大时带来的问题是如何更快速的处理库存计算. 此处以最简模式来讨论库存设计. 以下内容只做分析,不能直接套用,欢迎 ...

  3. Gearman + Nodejs + MySQL UDF异步实现 MySQL 到 Redis 的数据同步

    [TOC] 1, 环境 CentOS, MySQL, Redis, Nodejs 2, Redis简介 Redis是一个开源的K-V内存数据库,它的key可以是string/set/hash/list ...

  4. 06 python操作MySQL和redis(进阶)

    python操作mysql.redis 阶段一.mysql事务 主要用于处理操作量大,复杂度高的数据.比如说,在人员管理系统中,你删除一个人员,你即需要删除人员的基本资料,也要删除和该人员相关的信息, ...

  5. PHP商品秒杀问题解决方案实例详解【mysql与redis】

    本文实例讲述了PHP商品秒杀问题解决方案.分享给大家供大家参考,具体如下: 引言 假设num是存储在数据库中的字段,保存了被秒杀产品的剩余数量. if($num > 0){ //用户抢购成功,记 ...

  6. linux安装和配置 mysql、redis 过程中遇到的问题记录

    linux下部署mysql和redis网上的教程很多,这里记录一下我部署.配置的过程中遇到的一些问题和解决办法. mysql ①安装完成后启动的时候报错 Starting MySQL.The serv ...

  7. Mysql与Redis的同步实践

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

  8. 通过Gearman实现MySQL到Redis的数据同步

    对于变化频率非常快的数据来说,如果还选择传统的静态缓存方式(Memocached.File System等)展示数据,可能在缓存的存取上会有很大的开销,并不能很好的满足需要,而Redis这样基于内存的 ...

  9. 一步完成 MySQL 向 Redis 迁移

    从mysql搬一个大表到redis中,你会发现在提取.转换或是载入一行数据时,速度慢的让你难以忍受.这里我就要告诉一个让你解脱的小技巧.使用“管道输出”的方式把mysql命令行产生的内容直接传递给re ...

  10. MySQL to Redis

    [TOC] 简介 使用mysql2redis可以非常便捷的将mysql中的数据导出到redis中去, 通常是需要一个select语句即可实现. 软件安装 // 安装apr + apr-util $ w ...

随机推荐

  1. C++字符串大写字母转小写字母

    #include <iostream> #include <stdio.h> using namespace std; char* Capital_to_Small(char* ...

  2. 学习go语言编程之并发编程

    并发基础 并发包含如下几种主流的实现模型: 多进程 多线程 基于回到的非阻塞/异步IO 协程 协程 与传统的系统级线程和进程相比,协程最大的优势在于"轻量级",可以轻松创建上百万个 ...

  3. C++ GDAL用CreateCopy()新建栅格并修改波段的个数

      本文介绍基于C++语言GDAL库,为CreateCopy()函数创建的栅格图像添加更多波段的方法.   在C++语言的GDAL库中,我们可以基于CreateCopy()函数与Create()函数创 ...

  4. Linux驱动开发笔记(二):ubuntu系统从源码编译安装gcc7.3.0编译器

    前言   编译ubuntu驱动之前,发现使用的gcc是7.3.0,而使用apt管理和下载的都无法直接或间接安装gcc7.3.0,于是只能从源码安装gcc7.3.0编译器.   GCC 概述   GCC ...

  5. python运算符---day04

    1.python运算符 (1)算数运算符: + - * / // % ** (2)比较运算符: > < >= <= == != (3)赋值运算符:= += -= *= /= / ...

  6. 图片验证码pillow模块

    安装下载 pip install pillow 使用 需要引入PIL里面的Image from PIL import Image # mode为采用什么色系,size为大小px,color为颜色 im ...

  7. 【八股cover#4】OS Q&A与知识点

    OS Q&A与知识点 重点知识 进程 概念 ​ 我们编译的代码可执行文件只是储存在硬盘的静态文件,运行时被加载到内存,CPU执行内存中指令,这个运行的程序被称为进程. 进程是对运行时程序的封装 ...

  8. 【Azure API 管理】APIM如何配置客户端证书的CRL检测策略

    证书吊销列表 (Certificate Revocation List ,简称: CRL)  是 PKI 系统中的一个结构化数据文件,该文件包含了证书颁发机构 (CA) 已经吊销的证书的序列号及其吊销 ...

  9. expect tcl 摘录

    目录 部分参考来源说明 例子 expect命令 核心命令有三个 spawn.expect.send 其他expect命令 expect命令的选项 变量 tcl摘录 数据类型 符号 命令 其他说明 部分 ...

  10. win上vscode出现undefined reference to `__imp_WSACleanup'

    示例代码 #include <iostream> // 推荐加上宏定义 #define WIN32_LEAN_AND_MEAN #include <winsock2.h> #i ...