缓存一致性产生背景
如果每次频繁的访问数据库的时候,虽然查询底层使用B+树索引 但还会做磁盘的IO操作,可能会对数据库的压力非常大。
所以为了能够减轻数据库的访问压力,会使用一些缓存实现减轻数据库的压力。
比如 Redis、es、ehcache、oscache等。
多级缓存架构设计
首先在jvm内置缓存ehcache、oscache底层基于HashMap实现 ,如果服务集群的情况下数据同步采用rmi实现性能可能不是很好。
补充:rmi就是 jvm与jvm之间通讯
设计模式采用装饰模式。
Mysql与Redis缓存一致性原理
Mysql与nosql之间数据一致性问题:
Mysql与redis/es/mongdb 都是相同的。
(相同key)
第一次查询:
1. 查询二级缓存Redis,redis如果没有该缓存数据,则开始查询mysql;
2. 在查询mysql,如果mysql中存在数据的情况下,就将该数据缓存到Redis中
第二次查询:
1. 查询到redis中如果存在该数据的情况下,则不会查询mysql。
能够减轻数据库访问压力。
重点解决方案:
1. 对mysql增量做写的操作的时候,都会同步到Redis。
如果insetdb ,insetredis
如果update ,将redis中该key删除。---懒加载。
如果update ,直接修改redis。---增量同步。
如果delete ,将redis中该key删除。---增量同步。
如果数据库数据发生变化,如何同步给Redis
1. 直接清除Redis缓存;(适合于小项目)基于接口形式实现同步
2. 基于MQ形式异步同步 (适合于中小项目)基于接口形式实现同步
3. 基于canal+mq异步同步 (推荐)基于源头binlog二进制文件实现同步。
基于canal同步的原理:
1. Canal服务器端伪装成一个mysql从节点,订阅mysql主节点的binlog二进制文件
2. Canal服务器端收到binlog文件,就会转换成json的格式发送给Canal客户端。
3. Canal客户端会将该数据同步给nosql缓存 redis
流程:
第一次请求流程:
1. 先请求查询redis缓存,如果redis缓存没有数据则查询mysql数据库,如果mysql数据库存在数据,则将该数据缓存到Redis中。
第一次请求流程:
2. 先请求查询Redis缓存,如果redis缓存存在数据的话,则不会查询mysql数据
从而实现减轻数据库访问压力。
优化:Canal接收到mysqlbinlog文件,将该消息缓存到kafka中,再开启多个消费者
异步地获取消息同步到Redis中,能够提高同步的效率。
如果数据库数据发生变化,如何同步给Redis
方案1:直接删除Redis缓存;
方案2: 基于MQ异步同步更新
方案3: 基于canal订阅binlog同步
http://127.0.0.1:8081/insert?name=mayikt&age=22
http://127.0.0.1:8081/getUser?id=6
http://127.0.0.1:8081/updateUser?userId=9&name=meite6666
基于canal订阅binlog同步 实现原理
1. canal服务器模拟伪装成mysql从节点,订阅mysql 主节点的binlog文件;
2. 当mysql主节点binlog文件发生变化的时候,会通知给canal服务器端;
3. Canal服务器端在将该binlog文件转换为json格式数据发送给canal客户端监听者。
4. canal客户端,在将该数据异步写入到redis中;