MySQL 缓存策略

MySQL 缓存方案用来干什么 ?

  • 缓存用户定义的热点数据,用户直接从缓存中获取热点数据,降低数据的写压力。
  • 场景分析
    • 内存访问速度是磁盘访问速度的 10 万倍。
    • 读的需求远远大于写的需求
    • MySQL 自身缓冲层跟业务无关
    • MySQL 作为项目主要数据库,便于统计分析。
    • 缓存数据库作为辅助数据库,存放热点数据

还有哪些方式提升 MySQL 访问性能

在这里插入图片描述

  • 读写分离
    • 是什么 ?
      • 设置多个从数据库,从数据库可能会在多个机器中。
      • 写操作依然在主数据库。
      • 主数据库提供数据的主要依据。
    • 解决了什么问题:从数据库主要解决读压力。
    • 原理:
      • 主从原理。
      • 异步复制:最终一致性;主从之间数据会有差异。
      • 如果读操作有一致性要求,读操作去读主数据库。
  • 连接池
    • 在服务端中创建多个与数据库的链接。
    • 解决了什么问题:并发提升数据库访问性能;复用连接资源,避免连接建立或断开、以及安全验证的开销。
    • 原理:MySQL 的网络模型:select;阻塞的 IO 模型。如果发送一个事务(多个 SQL 语句),这个事务必须在一个连接中执行。
  • 异步连接
    • 在服务端创建一个连接,针对这个连接采用非阻塞 IO。
    • 解决了什么问题:节省了网络传输时间。
    • 原理:使用了非阻塞 IO。

MySQL 缓存方案

  • Redis 缓存和 MySQL 一致性状态分析
    • MySQL 有,Redis 无。
    • MySQL 无,Redis 有。(错误状态)
    • 都有,数据不一致。(错误状态)
    • 都有,数据一致。
    • 都没有
  • 制定用户定义的热点数据读写策略
    • 读:先读 Redis 缓存,缓存存在直接返回;缓存不存在,去访问 MySQL 获取,再写 Redis。
    • 写:
      • 以安全为主
        • 先要删除 Redis 中的数据,然后再写 MySQL,最后将 MySQL 数据同步到 Redis。
        • 问题:缓存方案的主要目标是提升效率,而现在为了安全降低效率。
        • 只有一种情况使用:读远大于写。
      • 以效率为主
        • 先写 Redis 缓存并设置过期时间,再写 MySQL,等待 MySQL 同步到 Redis 中。
        • 过期时间选择:与 MySQL 网络传输时间 + MySQL 处理时间 + MySQL 同步到 Redis 的时间有关。
        • 安全问题:比如设置了过期时间为 200ms,在 200ms 窗口时间内,其它请求可能读到的是脏数据。

MySQL 主从复制

在这里插入图片描述

  • 工作原理:
    • 主库 DML 操作(增删改操作)通过 io-thread 写到 binlog。
    • 从库请求读取 binlog,通过 io-thread 写入从库本地 relay-log(中继日志)。
    • 从库通过 sql-thread 读取 relay-log,并把更新事件在从库重放(replay)一遍。
  • 复制流程:
    • Slave 中的 IO 线程连接上 Master,并请求从指定日志文件的指定位置之后的日志内容。
    • Master 接收到来自 Slave 的 IO 线程的请求后,负责复制的 IO 线程会根据请求信息读取日志指定位置之后的日志信息,返回给 Slave 的 IO 线程。返回信息中包含日志信息、Master 端 binlog 文件的名称、下次读取 Master 端 binlog 文件中的起始位置。
    • Slave 的 IO 线程接收到消息后,将接收到的日志内容依次添加到 Slave 端的 relay-log 文件末尾,并将读取到的 Master 端的 binlog 文件名和下次读取 binlog 文件中的起始位置记录到 master-info 文件中,以便在下一次读取的时候能够清楚地告诉 Master 从何处开始读取日志。
    • Slave 的 SQL 进程在检测到 relay-log 中新增加了内容后,会马上解析 relay-log 的内容为在 Master 端真实执行时的可执行内容,并在自身执行(重放)。

如何把 MySQL 的数据同步到 Redis ?

在这里插入图片描述

  • 额外增加一个中间件(go-mysql-transfer),该中间件伪装成 MySQL 的从数据库,不断地从 MySQL 中拉取数据(binlog)并进行解析,解析之后写到 Redis 中。(基于 MySQL 主从复制的原理,但是不会重放)
git clone https://gitee.com/mirrors/go-mysql-transfer

缓存方案的故障问题及解决

缓存穿透

  • 数据在 Redis 和 MySQL 中都没有,一直读取不存在的数据,造成 MySQL 访问性能急剧降低。
    • 假设黑客恶意请求服务器不存在的数据,此时 Redis 形同虚设,那么所有的请求压力都会堆积在 MySQL 中,相当于请求穿透了 Redis 直接到了 MySQL,造成 MySQL 访问性能急剧降低。
  • 解决
    • 在 Redis 中缓存不存在的热点数据为 <key, nil>,服务器每次读到 “nil” 字符串的时候,说明整个存储系统都没有这个数据,当客户端再次请求这个数据时,服务器可以直接返回。
      • 缺点: 如果黑客不断地随机出新的 key,那么 Redis 就会写很多不存在的 <key, nil>,可能会把 Redis 的内存撑爆(Redis 不怕请求多,而是怕内存不够)。
    • 部署布隆过滤器:布隆过滤器可以确定一个 key 是否存在。
      • 布隆过滤器要部署到 Redis 中,而不是部署到服务器中(如果有多个服务器,那么每次都需要把热点数据写到每个服务器的布隆过滤器中,这样的话,就需要维护多个布隆过滤器,很麻烦)。
      • 缺点:布隆过滤器只能增加数据,不能删除数据。

缓存击穿

  • 数据在 Redis 中没有,在 MySQL 中有,大量并发连接请求,造成 MySQL 访问性能急剧降低。
  • 解决
    • 分布式锁:请求数据的时候获取锁,若获取成功,则操作后释放锁;若获取锁失败,则休眠一段时间(200 ms)再去获取锁。
      • 服务器 A 先访问 Redis(要获取锁),发现数据不存在,然后访问 MySQL,发现数据存在,将数据同步给 Redis(要释放锁),后面的服务器 B、服务器 C 就可以直接从 Redis 中获取数据。
    • 将很热的 key 设置为不过期。

缓存雪崩

  • 大量缓存数据集中失效,但是数据在 MySQL 中存在,造成 MySQL 访问性能急剧降低。
  • 解决
    • 将很热的 key 设置为不过期。
    • 间隔设置过期时间。
    • 重启时,预先导入热数据到缓存(预热)。

缓存方案的弊端

  • 不能处理多语句的事务。
    begin;
    start transaction;
    sql1;
    sql2;
    commit;
    
  • Redis 不支持回滚。
  • 最终解决方案:分布式关系型数据库 TiDB

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/513345.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

winui开发笔记(五)应用程序图标

应用程序图标、发布者、显示名称大部分都在package.appxmanifest清单文件中&#xff0c;可以正常打开&#xff0c;也可以使用xml文本编辑器打开。 以下是一个正常的应用程序中所有的与图标相关的图片&#xff1a; 但是设置之后会有一圈白&#xff0c;包括在电脑最下边一行&…

Python异步IO库之uvloop使用详解

概要 在Python中,异步编程已经成为处理高并发和IO密集型任务的主要方式之一。而uvloop库则是一个专门针对异步IO操作进行优化的库,它能够显著提高异步程序的性能。本文将深入探讨uvloop库的使用方法、功能特性以及如何利用它来加速异步IO编程。 什么是uvloop库? uvloop是一…

Tensorflow2.0笔记 - 计算梯度

本笔记主要记录tf.GradientTape和tf.gradient的用法 import tensorflow as tf import numpy as nptf.__version__#要计算梯度的所有参数计算过程必须放到gradient tape中 #with tf.GradientTape as tape: w tf.constant(1.) x tf.constant(2.)with tf.GradientTape() as tap…

防御保护--课程笔记

一、内容安全 攻击可能只是一个点&#xff0c;防御需要全方面进行 IAE引擎 1、DFI和DPI技术 --- 深度检测技术 &#xff08;1&#xff09;DPI --- 深度包检测技术 --- 主要针对完整的数据包&#xff08;数据包分片&#xff0c;分段需要重组&#xff09;&#xff0c;之后对 数据…

C#高级:Winform桌面开发中DataGridView的详解

一、每条数据增加一个按钮&#xff0c;点击输出对应实体 请先确保正确添加实体的名称和文本&#xff1a; private void button6_Click(object sender, EventArgs e) {//SQL查询到数据&#xff0c;存于list中List<InforMessage> list bll.QueryInforMessage();//含有字段…

(C语言)sizeof和strlen的对比(详解)

sizeof和strlen的对⽐&#xff08;详解&#xff09; 1. sizeof sizeof是用来计算变量所占内存空间大小的&#xff0c; 单位是字节&#xff0c;如果操作数是类型的话&#xff0c;计算的是用类型创建的变量所占空间的大小。 sizeof 只关注占用内存空间的大小 &#xff0c;不在乎内…

【C语言】指针超级无敌金刚霹雳进阶(但不难,还是基础)

点击这里访问我的博客主页~~ 对指针概念还不太清楚的点击这里访问上一篇指针初阶2.0 上上篇指针初阶1.0 谢谢各位大佬的支持咯 今天我们一起来学习指针进阶内容 指针进阶 一、指针变量1、字符指针变量2、数组指针变量①数组指针变量的定义②数组指针变量的初始化 3、函数指…

【Linux从青铜到王者】进程信号

——————————————————————————————————————————— 信号入门 在了解信号之前有许多要理解的相关概念 我们可以先通过一个生活例子来初步认识一下信号 1.生活角度的信号 你在网上买了很多件商品&#xff0c;再等待不同商品快递的到来…

C++对象内存模型布局详解

目录 本文主要内容如下&#xff1a; 最后还有一些问题&#xff1a; 一、理解虚函数表 二、对象模型概述 三、继承下的C对象模型 单继承&#xff1a; 多继承&#xff1a; 一般的多继承&#xff08;非菱形继承&#xff09;&#xff1a; 菱形继承&#xff1a; 五、虚继承…

Nodejs 第四十七章(redis主从复制)

Redis主从复制是一种数据复制和同步机制&#xff0c;其中一个Redis服务器&#xff08;称为主服务器&#xff09;将其数据复制到一个或多个其他Redis服务器&#xff08;称为从服务器&#xff09;。主从复制提供了数据冗余备份、读写分离和故障恢复等功能。 以下是Redis主从复制的…

【双指针】Leetcode 11. 盛最多水的容器

【双指针】Leetcode 11. 盛最多水的容器 解法1 典型双指针 ---------------&#x1f388;&#x1f388;题目链接&#x1f388;&#x1f388;------------------- 解法1 典型双指针 时间复杂度O(N) 空间复杂度O(1) 双指针&#xff0c;前后&#xff0c;策略是每次向内移动小的…

数据库 与 数据仓库

OLTP 与 OLAP OLTP(On Line Transaction Processing&#xff0c;联机事务处理) 系统主要针对具体业务在数据库联机下的日常操作&#xff0c;适合对少数记录进行查询、修改&#xff0c;例如财务管理系统、ERP系统、交易管理系统等。该类系统侧重于基本的、日常的事务处理&#…