后端技术_MySQL缓存策略
最近更新:2024-09-23
|
字数总计:2.3k
|
阅读估时:8分钟
|
阅读量:次
- 重要日志
- CURD执行过程
- MySQL缓存策略
- MySQL缓存用来做什么
- 还有哪些方式提升mysql访问性能(*)
- 缓存方案是怎么做的?(*)
- 缓存和mysql一致性状态分析
- 读写策略
- 数据同步方案
- mysql主从复制
- 同步中间件原理
- 问题是否完全解决?
- 缓存方案弊端
- redis和mysql总结
- redis
- mysql
重要日志
- undolog:1)依据undolog中的rollpoint用来回滚,来实现原子性;2)mvcc解决行记录是否可见问题,也是从rollpoint的值来解决可见性问题。undolog是一种逻辑日志,记录的是修改的逻辑。
- redolog:类似wal(write-append-log)日志,在内存中的数据不会每次都刷盘,我们会累计一定的数量后才异步刷盘,redolog确保内存中的buffer pool数据是安全的,即使mysql宕机了,我们还未刷盘的数据不会丢失。redolog是一种物理日志,记录了磁盘的页位置和写了什么内容。
- binlog:用于备份\主从同步日志。
CURD执行过程

- 描述:当发起一条SQL语句时。Server层:首先通过连接器建立一条连接,接下来根据sql语句进行语法、词法分析生成语法树,接下来做执行计划,然后从多个执行计划中选择一个执行代价最小的准备通过执行器来执行,引擎层有api接口供执行器传入参数来交给引擎层具体执行。引擎层:首先通过read view和undolog确认该数据的可见性,当该数据可见时,接下来看数据是怎么样的索引。假设是聚集索引,假设目标页位于buffer pool中,找到数据判断数据是否冲突然后更新内存,假设目标页不在buffer pool中,需要将该页从磁盘读入buffer pool中,再更新数据。如果是辅助索引,假设目标页位于buffer pool中,找到数据判断数据是否冲突然后更新内存,假设该页不在buffer pool中,我们会先把数据写入到change buffer中,change buffer在一定时间内如果数据被加载到内存中,会尝试合并修改,如果超时没有加载,它会把数据异步刷入磁盘中。接下来写redolog(调用write系统调用),接下来写入binlog(调用write系统调用),两个log构成一个事务(要么都成功要么都不做),提交事务,先刷redolog盘(调用fsync),再刷binlog盘。
MySQL缓存策略
MySQL缓存用来做什么
- 缓存用户定义的热点数据,用户直接从缓存获取热点数据,降低数据库的读写压力。
- 与MySQL buffer pool缓存机制的差异:buffer pool是使用5/8的LRU算法构建old list和new list的方式进行缓存的,该缓存针对的是最近的读写mysql的频次。不是用户定义的热点,也不能预测未来一段时间某个热点数据。
- 举例:今天上午10点预约了一批用户,预约时间是下午6点,那么这些预约的用户将会是下午6点时的热点数据,但是到下午6点时,mysql的缓存极有可能缓存的是下午5点左右的数据,只有上午预约的用户才是用户定义的热点数据。
- 缓存策略应用场景:因为mysql非常安全,即每次读写都确保数据能够落盘,读写效率低,为了提高client端的响应性能,即提高server端的吞吐量,在server和mysql之间添加redis。
- 内存访问速度是磁盘访问速度10万倍(数量级)
- 读的需求远远大于写的需求
- mysql自身缓冲与业务无关
- mysql作为项目主要数据库,便于统计分析
- 缓存数据库作为辅助数据库,存放热点数据
还有哪些方式提升mysql访问性能(*)
- 读写分离
- 是什么?
- 会设置多个从数据库,从数据库可能会在多个机器中;
- 写操作依然在主数据库;
- 主数据库提供数据的主要依据;
- 解决什么问题
- 从数据库主要解决读压力;
- 原理是?
- 主从原理;
- 异步复制(MySQL是异步复制:从数据库主动从主数据库拉取数据,同步复制:主数据库向从数据库提交复制申请,一定会等待完成才返回成功,是强一致性的):1)最终一致性(最终能够保持一致,是弱一致性);2)主从之间数据会有差异;
- 如果读操作有一致性要求:读操作去读主数据库;
- 连接池
- 是什么?在服务端当中创建多个与数据库的连接;
- 解决了什么问题?
- 并发提升数据库访问性能;
- 同时复用连接,避免连接建立或断开,以及安全验证的开销;
- 原理是什么?
- mysql的网络模型:select、阻塞io模型;
- 特别注意:如果发送一个事务(多个sql语句),这个事务必须在一个连接中执行;
- 异步连接
- 是什么?在服务端创建一个连接,针对这个连接采用非阻塞io;
- 解决了什么问题?节省了网络传输时间;
- 原理是什么?使用了非阻塞io;
缓存方案是怎么做的?(*)
缓存和mysql一致性状态分析
- 读操作:server先去redis读,如果有直接返回,不访问mysql,如果没有再访问mysql;
- 针对用户定义的热点数据:
- mysql有,redis没有(允许存在,但是此次操作完需要将mysql的数据写入redis)
- mysql没有,redis有(不允许,脏数据)
- 都有,数据不一致(不允许)
- 都有,数据一致(允许)
- 都没有(允许)
读写策略
- 读策略:先去redis读,如果redis有,直接返回,不需要访问mysql,如果redis无,去mysql获取;1)mysql有,同步到redis;2)mysql无,说明数据不存在;
- 写策略:
- 安全角度:先把redis中的该热点数据删除,再去写mysql;效率代价:效率低;
- 效率角度:先修改redis当中的数据,先设置redis中key的过期时间(过期后该key会被删除),然后再去写mysql,再将mysql的数据同步到redis;安全代价:过期时间内可能会读到脏数据;
- 过期时间选择的依据:与mysql网络传输事件+mysql处理时间+mysql同步到redis的时间;
- 安全问题?因为限制特别多,首先是热点数据,其次mysql读写错误的概率非常低,所以综合考虑选择第二种。
数据同步方案
- 触发器 + UDF(user define function,mysql提供的扩展机制,mysql加载c/c++动态库调用函数)
- 当触发写操作的时候,触发代码,同步redis数据
- 不建议该方案。1)触发器具备事务性,所以触发器触发点和udf是一个事务,dml操作结束后还会等触发器结束才会返回,非常慢;2)触发器每次都要重新建立连接,操作完成后还要释放连接;
- canal中间件(阿里开源,适合分布式架构)
- go-mysql-transfer中间件;
mysql主从复制

- 原理:主数据库dml操作时会写binlog,从数据库有一个io线程不断读取主数据库的binlog,并写入中继日志relaylog,从数据库还有一个sql线程,不断从relaylog中replay复现主数据的sql操作;
同步中间件原理
- 伪装成mysql的从数据库和mysql主数据库建立连接(原理),开启io线程不断读取主数据库的binlog,但是不需要sql线程也不需要进行sql操作,直接将binlog中的操作同步给redis;
问题是否完全解决?
- 缓存穿透
- 问题:数据在缓存和mysql中都没有,但是一直读取不存在的数据(业务逻辑造成,黑客),造成mysql崩溃,大量请求堆积;
- 解决:1)redis缓存设置<key, nil>,server读到nil就不会读mysql了(缺点:占用内存空间);2)部署布隆过滤器,部署在redis中(布隆过滤器只能新增不能删除数据);
- 缓存击穿
- 问题:缓存无,mysql有数据,大量并发连接请求,造成mysql崩溃;造成:大量并发连接
- 解决:1)过热数据不过期;2)分布式锁;
- 缓存雪崩
- 问题:大量缓存数据集中失效,但是数据mysql存在,造成mysql崩溃;造成:大量缓存集中失效
- 解决:1)间隔设置过期时间;2)重启时,预先导入热数据到缓存(预热)
缓存方案弊端
- 不能处理多语句事务,因为redis不支持回滚,也不支持多语句事务,先写redis就不能这么写
- 造成redis、mysql不一致
redis和mysql总结
redis
- 基础:redis 5种基本数据类型和操作 综合多个数据结构实现业务
- redis是怎么保持高效的?dict 如何渐进式rehash 扩容 缩容 怎么挪数据 怎么分摊;skiplist 如何分析空间复杂度 理想跳表 增加层级后空间复杂度;
- 持久化方案 fork 写时复制 aof内核原理 page cache、write和fsync系统调用
mysql
- sql基本语句
- B+树,索引原理 -> 使用规则
- 事务 加锁 隔离级别RR gap lock、insert 死锁
- 缓存 综合应用
2024-03-12
该篇文章被 Cleofwine
归为分类:
服务端