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

前言

因为对接的零碎越来越多,接口拜访并发量日渐减少,遂决定在我的项目中退出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,能够应用我上边提到的解决办法。

【腾讯云】轻量 2核2G4M,首年65元

阿里云限时活动-云数据库 RDS MySQL  1核2G配置 1.88/月 速抢

本文由乐趣区整理发布,转载请注明出处,谢谢。

您可能还喜欢...

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据