概述
数据库有哪些提升读写性能的方式?
- 连接池 阻塞io + 线程池
- 异步连接,非阻塞io
- sql执行出发:即时执行 + 预编译执行 prepare
- 读写分离
- 缓存方案
主从复制,是为了解决单点故障的问题
缓存可以用memcached、redis
针对与热点数据进行讨论,热点数据有哪些状态?
- mysql有,cache没有,通过策略避免它
- mysql没有,cache有,不正常需避免
- mysql和cache都有,数据不一致, 不正常需避免
- mysql和cache都有,数据一致,最终目标
- mysql和cache都没有,属于正常情况
读策略
- 先看cache是否有数据,如果有直接返回
- 如果cache没有,去访问mysql
- 如果mysql有,缓存数据到cache
- 如果mysql没有,就是没有
增删改的策略
- 删除时,先删除缓存,再去删除mysql
- 更新和插入时,可以直接删除缓存,再从mysql同步过来
- 还有一种方案是先修改缓存并设置过期时间(200ms),mysql再同步到cache,需要删除过期时间,这样性能会好些,避免请求直接涌入数据库。
读写分离一致性要求高的
- 主从半同步复制
- 读去主数据库读取
数据同步方案:
- 触发器+UDF,缺点是UDF不具备事务不能回滚,效率低
- 使用go-mysql-transfer,缺点是需要引入zk等实现高可用
- canal+canal客户端,缺点是比go-mysql-transfer多了一个流程,优点是高可用
第2和第3点,实现的原理是伪装成从数据库,和主库进行同步。
mysql主从复制
server层生成的binlog日志,每一行数据;引擎层生成redo日志,记录的是增删改时B+树对应的物理地址+偏移量+具体数据
- 主库更新事件(update、insert、delete)通过 io-thread 写到binlog;
- 从库请求读取 binlog,通过 io-thread 写入(write)从库本地 relay log(中继日志);
- 从库通过sql-thread读取(read) relay log,并把更新事件在从库中执行(replay)一遍;
复制流程:
- Slave上面的IO进程连接上Master,并请求从指定日志文件的指定位置(或者从最开始的日 志)之后的日志内容。
- Master接收到来自Slave的IO进程的请求后,负责复制的IO进程会根据请求信息读取日志指 定位置之后的日志信息,返回给Slave的 IO进程。返回信息中除了日志所包含的信息之外, 还包括本次返回的信息已经到Master端的bin-log文件的名称以及bin-log的位置。
- Slave的IO进程接收到信息后,将接收到的日志内容依次添加到Slave端的relay-log文件的最 末端,并将读取到的Master端的 bin-log的文件名和位置记录到master-info文件中,以便在 下一次读取的时候能够清楚的告诉Master从何处开始读取日志。
- Slave的Sql进程检测到relay-log中新增加了内容后,会马上解析relay-log的内容成为在 Master端真实执行时候的那些可执行的内容,并在自身执行。
缓存穿透 (不存在的key)
描述:访问一个缓存和数据库都不存在的 key,此时会直接打到数据库上,并且查不到数据,没法写缓存,所以下一次同样会打到数据库上。
解决:1、接口校验。2、缓存空值,标记这个key为nil并设置一个过期时间让下次访问key不再访问mysql。3、布隆过滤器。
缓存击穿 (某些热key过期)
描述:某一个热点 key,在缓存过期的一瞬间,同时有大量的并发请求打进来,由于此时缓存过期了,所以请求最终都会走到数据库,造成瞬时数据库请求量大、压力骤增,甚至可能打垮数据库。
解决: 1、加互斥锁(Redis 分布式锁)请求数据时获取锁,获取锁成功则操作访问redis再访问mysql,然后mysql同步到redis后再释放锁,后面的请求就去redis取 2、热点数据不过期。
缓存雪崩 (大量key过期)
描述:大量的热点 key 设置了相同的过期时间,导在缓存在同一时刻全部失效,造成瞬时数据库请求量大、压力骤增,引起雪崩,甚至导致数据库被打挂。
解决:1、过期时间随机打散。2、热点数据不过期。3、加互斥锁。
最后
以上就是活泼金鱼为你收集整理的mysql缓存方案的全部内容,希望文章能够帮你解决mysql缓存方案所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复