缓存使用模式分为两大类:Cache-Aside和Cache As SoR 专业名词:
Cache-Aside:即业务代码围绕Cache编写,由业务代码维护缓存; 如:
data = cache.getIfPresent(key); if(data == null){ data = loadFromSoR(key); cache.put(key,data) } 先从缓存中获取,没有查询SoR,再放入缓存
并发更新问题与解决(多个缓存实例,同时更新自己里面的同样数据) 1、考虑使用中间件如Canal订阅binlog,进行增量更新分布式缓存,不会存在缓存数据不一致问题。但是会有延迟,我们可以调整合理的过期时间来容忍这个延迟 2、读服务,可以考虑一致性哈希,相同的操作负载均衡到同一个实例,从而减少并发几率。
即把Cache当做SoR,所有操作都是对Cache进行,然后Cache委托SoR进行数据的真实读写。即业务代码只看到Cache的操作,看不到关于SoR的代码;三种实现模式:read-through、 write-through、write-behind
应用级缓存:(数据一定不能是脏数据)【Map、Ehcache、Guava】 Mybatis:二级缓存Map if(map.get(1)){ return obj; }else{ queryFromDb } obj = cache; 缓存读取来的数据是否是改写安全; obj = cache; obj2 = new Obj(); BeanUtils.copyProperties(obj,obj2) obj2.compute(); //写时复制 obj = ObjHaha(); obj2 = new Obj(); BeanUtils.copyProperties(obj,obj2) map.put(k, obj2); obj.compute(); 分布式缓存:
缓存使用两种复制模式,注意。Copy-On-Read(读时复制)、Copy-On-Write(写时复制)。 有些进程内缓存很多是基于引用的,所以拿到缓存中的数据如果进行修改,可能发生不可预测的问题。 读时复制:读取到的缓存的值,复制内容封装一个新的对象。 写时复制:给缓存中写的值,复制一个新的对象写入