关于redis:解决redis多表更新的事务一致性问题

1次阅读

共计 1778 个字符,预计需要花费 5 分钟才能阅读完成。

前言

因为对接的零碎越来越多,接口拜访并发量日渐减少,遂决定在我的项目中退出 redis。

意识 redis

redis 做为一个缓存中间件常常被用于进步接口并发量来应用。你能够把他看做数据库的缓存来应用,相似于上次咱们说的 mybatis 的缓存机制。也能够把他作为一个高性能数据库来应用,反对长久化。
类比于 mybatis 的缓存机制不同的是,咱们应用 redis 作为缓存不会呈现查一次做批改不保留再去查就是新值的问题,也比 mybatis 的缓存机制可操作性更强。比方当更新一个表时,mybatis 本人会把所有缓存全副清空,保障时效性。而 redis 更新一个表时,你能够去只更新对应的一条数据,可操作性更强,同时反对设置生效工夫,如 10 分钟,10 分钟后主动删除。

redis 外部将 key-value 保留到了内存中,查问时,通过 key 返回 value 值。解决 value,也就是 String 类型,还反对同时还提供 list,set,zset,hash 等数据结构的存储。最罕用的就是 String 类型。
认为保留在内存中,所以比数据库读写速度快。

装置能够参考菜鸟教程装置。他的应用相似于 mysql,提供命令行操作,反对可视化软件链接。

应用 redis

springboot 我的项目接入 redis,同样须要引入 redis 包,在 yaml 文件中退出配置连贯。

我的项目中应用 redis 两种形式,一种是应用缓存注解模式,一种是应用 RedisTemplate 的办法操作。
注解模式
首先在我的项目启动类上退出 @EnableCaching 注解示意启用缓存

@Cacheable 注解,在查询方法上增加,调用此办法前先通过 key 查问缓存,若查不到,则再执行此办法,并将返回后果和 key 保留到缓存中。若查失去,间接返回 value,不在执行此办法。其中参数 cacheNames 指定缓存组件名,此名字在 yaml 文件中定义,key 代表 key-value 中的 key,应用 spEL 表达式去编写,如果入参是对象,可写作key = "#user.usrNo"

@Cacheable(cacheNames = "XXX", key = "#usrNo")
public User queryByUsrNo(String usrNo) {}

须要留神的是,这里的 key 是不辨别表的,如果两个表的 key 值雷同,那么就会产生抵触,所以咱们的 key 值前要加上表明前缀,格局为 表名:key, 写作key = "'user:' + '#usrNo'" 。这里的: 号有分组的意思,相似于文件门路的 /, 这个能够在可视化 redis 工具中看到。

@CachePut 注解,在变更办法上增加,在执行完指标办法后,缓存中的数据也会更新。

@CacheEvict 注解,删除缓存,在执行完指标办法后,革除对应的 key-value。

代码模式
以上性能手动在代码中增加,应用 RedisTemplate 中的办法实现。
例如须要手动在查询方法上加查询数据库的判断操作和查问完数据库的保留操作。

解决 redis 多表更新的事务一致性问题

redis 反对事务,然而跟 mysql 的事务并不一样,redis 事务没有回滚机制。那么如果一个变更交易更新两个表,当更新第一个表时 mysql 胜利更新,redis 也更新,当更新第二个表时报错 mysql 回滚,第一个表还是原来的数据,然而 redis 无奈回滚之前的数据,导致数据不统一的问题。

解决这个问题其实咱们要保障 redis 在所有表都胜利更新后再去对立更新。这个我想到了前段时间接触的 spring event 机制。其中有一个公布多个事件,监听事件者能够在事务提交后执行。利用此原理。切面数据库更新删除办法,每当更新删除一个表时,把 key 公布进来。同时设置一个监听者,退出 @TransactionalEventListener 注解,当整个事务提交时,删除公布的所有 key-value。
具体可参考 spring event 机制
这里须要咱们着重留神一下 key 的设置,咱们须要给每一个表设置一个业务因素。业务因素能够简略了解为咱们查问次数最多的条件。如学生表的话就是学生编号,学生班级关联表也是学生编号。这样保障每一个表的 key 对应的字段雷同,删除缓存时才不会漏删。

总结

redis 实用于一些不常常变的数据或者对变动时效性要求不高的数据缓存,如果对时效性要求高并且又不得不加 redis,能够应用我上边提到的解决办法。

正文完
 0