【redis】spring-cache使用指南
使用
- 查:第一次从数据库中查询并生成缓存,后面缓存未失效前走缓存。
- 删改:使缓存失效
key为:SPEL表达式(spring的SPEL表达式,这里只涉及到简单的,因为不是重点,所以就不展开说了)
//查询到则缓存,如果返回结果为null则不缓存
@Cacheable(cacheName="user", key="#p0+'_'+#p1", unless="null==#result")
public User getUser(long cid, long uid) {
//此处的的cid是租户id,uid是用户id
xxx
}
//每次访问都重建缓存
@CachePut(cacheName="user", key="#p0+'_'+#p1")
public User getUser(long cid, long uid){
//此处的的cid是租户id,uid是用户id
xx
}
//使对应缓存失效
@CacheEvit(cacheName="user", key="#p0+'_'+#p1")
public void update(long cid, long uid){
//此处的的cid是租户id,uid是用户id
xxx
}
//使对应缓存失效
@CacheEvit(cacheName="user", key="#p0+'_'+#p1")
public void delete(long cid, long uid){
//此处的的cid是租户id,uid是用户id
xxx
}
//多个同时使用,使多个缓存失效
@Caching(
evict = {
@CacheEvit(cacheName="user", key="#p0+'_'+#p1"),
@CacheEvit(cacheName="userList", key="#p0")
}
}
public void update(long cid, long uid) {
xxx
}
更多细节
缓存之间的关系
public List<User> listUser(long cid) {
xxx
}
Question:想要获取这个List上面user缓存用的上吗?
Answer:用不上,因为是两个缓存。不要考虑用keys,很容易你就炸了,想要keys,要自己搞个Set把要的key存起来,用的时候取。况且,我们要的是简单操作,所以为什么不新建一个呢?(如果缓存数量特别大的时候,要考虑一些二级索引设计)
首先:这里新建了一个userList的cache
@Cacheable(cacheName="userList", key="#p0")
public List<User> listUser(long cid) {
xxx
}
然后考虑有哪些情形影响这个缓存的正确性。然后发现以下情况会影响到List缓存的正确性:新增用户,删除用户,更新用户,于是有:
//新增只删除对应的userList缓存
@CacheEvit(cacheName="userList", key="#p0")
public void add(long cid, long uid){
xx
}
//更新要删除user/userList两个缓存
@Caching(
evict = {
@CacheEvit(cacheName="user", key="#p0_#p1"),
@CacheEvit(cacheName="userList", key="#p0")
}
)
public void update(long cid, long uid){
xxx
}
//删除要删除user/userList两个缓存
@Caching(
evict = {
@CacheEvit(cacheName="user", key="#p0_#p1"),
@CacheEvit(cacheName="userList", key="#p0")
}
)
public void delete(long cid, long uid){
xxx
}
所以在定义接口的时候
- 方法功能定义应当清晰,要做到单一职责,否则缓存后面会很难搞。
- 参数要尤为注意,因为key是从参数中取来的。
- 相同的cache操作应当在一个service里,如果写到了别的地方,那么考虑一下代码是不是写的有问题了。
批量处理
如果逻辑复杂,编码去完成,没有什么好的办法。