缓存-分布式锁-缓存一致性解决
1.使用Redisson改自己业务代码
@Autowired
RedissonClient redisson;
//使用Redisson锁
public Map<String, List<Catelog2Vo>> getCatalogJsonFromDbWithRedissonLock() {
//1.锁的名字。锁的粒度,越细越快。
//锁的粒度:具体缓存的是某个数据,11-号商品;product-11-lock product-12-lock
RLock lock = redisson.getLock("catalogJson-lock");
lock.lock();
Map<String,List<Catelog2Vo>> dataFromDb;
try{
dataFromDb = getDataFromDb();
}finally {
lock.unlock();
}
return dataFromDb;
}
1.注入RedissonClient
2.加锁RLock lock = redisson.getLock("catalogJson-lock");
lock.lock();
3.lock.unlock();
2.问题1
当你修改三级分类时候,会存在mysql数据库与redis缓存的数据不一样
解决方法:
1.双写模式 把数据库改完 就把缓存也改了;缺点:修改完数据,再将最新的数据放到redis缓存里面;脏数据的问题;
2.失效模式 把数据库改完 就把缓存删除掉;
双写模式:出现暂时性 脏数据解决方法
1.加锁:第一个人操作完,解开锁,才让第二个人执行
2.看数据的重要性:如果数据不是太过于重要的,设置过期时间,让数据过期失效;
失效模式:出现操作数据库与缓存比较慢,读到了老的数据;还是脏数据问题;
1.加锁:系统就会变的笨重
2.数据是否经常需要修改?实施性比较高了,就存入mysql;
缓存数据一致性-解决方案
一.无论是双写模式还是失效模式,都会导致缓存不一致问题,即多个示例同时更新会出事,怎么办?
1.如果是用户纬度数据(订单数据、用户数据),这种并发几率非常小,不用考虑这个问题,缓存数据加上过期时间,每隔一段时间触发读的主动更新即可
2.如果是菜单,商品介绍等数据,也可以去使用canai订阅binlog等方式.
3.缓存+过期时间也足够解决大部分业务对于缓存等要求.
3.通过加锁保证并发读写,写写的时候按顺序排好队,读读无所谓.所以适合使用读写锁.(业务不关心脏数据,允许临时脏数据可忽略);
二.总结
1.我们能放入缓存的数据根本就不应该是实时性、一致性要求超高的,所以缓存数据的时候加上过期时间,保证每天拿到当前最新数据即可.
2.我们不应该过度设计、增加系统的复杂性
3.遇到实时性、一致性要求高的数据,就应该差数据库,即使慢点;
3.解决
缓存数据一致性解决-Canal
Canal:是阿里的产品,只要mysql数据库有数据改变了,Canal就像是伪装成一个从服务器.
它其实是用来解决数据异构的:比如你访问京东,你是一个数码爱好者,它就会在首页给你经常展示数码产品;
我们系统的一致性解决方案:
1.缓存的所有数据都有过期时间,数据过期下一次查询触发主动更新
2.读写数据的时候,加上分布式的读写锁.