前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >面试官问:Redis的操作如何与数据库事务保持一致

面试官问:Redis的操作如何与数据库事务保持一致

作者头像
IT大咖说
发布2019-12-17 15:12:57
3K0
发布2019-12-17 15:12:57
举报
文章被收录于专栏:IT大咖说IT大咖说
  • redis如何与数据库保持一致性的问题?

场景:如果我们在开发过程中遇到这样的一种情况,我们删除 redis中token 的同时 也需要修改数据库中 储存的 token 的状态为不可用的状态。如果这个时候我们不做处理的话,通常是先删除redis中的token,然后在进行数据库的修改。但是如果这个时候redis中的token删除成功了,但是在执行数据库操作之气程序报错了。那这个时候redis中的token已经被删除了,但是数据库中的token状态还是可用的状态,这个时候就导致了数据不一致的问题。

这时候我们需要使用统一的事务来进行解决这个问题,.但是如果只是单纯的使用数据库事务并不能解决这个问题,因为这个操作也涉及到了redis,所以这个时候我们应该使用 redis事务+数据库的事务 来保证事务一致性的问题。

如果只是单纯添加了 @Transactional(声明式事务)只能保证数据库的数据一致性问题,但是是无法控制redis中的事务的。redis中也是存在事务的。

解决方案:

我们可以使用自定义方法使用编程式事务 我们使用 begin(即控制reids事务也控制数据库事务)、commit、rollback 都需要实现控制redis事务和数据库事务。

下面直接上代码 ,

  • 这个类包装了redis事务和数据库事务,一起开启事务,一起提交事务,一起回滚事务
  • redisUtils相关代码:
  • 在写业务代码时 大致这样写

代码如下 自己copy用:

RedisDataSoureceTransaction 代码:

代码语言:javascript
复制
@Component
@Scope(ConfigurableListableBeanFactory.SCOPE_PROTOTYPE)
public class RedisDataSoureceTransaction {
 @Autowired
 private RedisUtil redisUtil;
 /**
 * 数据源事务管理器
 */
 @Autowired
 private DataSourceTransactionManager dataSourceTransactionManager;
 /**
 * 开始事务 采用默认传播行为
 *
 * @return
 */
 public TransactionStatus begin() {
 // 手动begin数据库事务
 TransactionStatus transaction = dataSourceTransactionManager.getTransaction(new DefaultTransactionAttribute());
 redisUtil.begin();//
 return transaction;
 }
 /**
 * 提交事务
 *
 * @param transactionStatus
 * 事务传播行为
 * @throws Exception
 */
 public void commit(TransactionStatus transactionStatus) throws Exception {
 if (transactionStatus == null) {
 throw new Exception("transactionStatus is null");
 }
 // 支持Redis与数据库事务同时提交
 dataSourceTransactionManager.commit(transactionStatus);
 redisUtil.exec();
 }
 /**
 * 回滚事务
 *
 * @param transactionStatus
 * @throws Exception
 */
 public void rollback(TransactionStatus transactionStatus) throws Exception {
 if (transactionStatus == null) {
 throw new Exception("transactionStatus is null");
 }
 dataSourceTransactionManager.rollback(transactionStatus);
 redisUtil.discard();
 }

redisutil相关代码:

代码语言:javascript
复制
/**
 * 开启Redis 事务
 *
 * @param isTransaction
 */
public void begin() {
 // 开启Redis 事务权限
 stringRedisTemplate.setEnableTransactionSupport(true);
 // 开启事务
 stringRedisTemplate.multi();
}
/**
 * 提交事务
 *
 * @param isTransaction
 */
public void exec() {
 // 成功提交事务
 stringRedisTemplate.exec();
}
/**
 * 回滚Redis 事务
 */
public void discard() {
 stringRedisTemplate.discard();
}

业务的大致模板代码:

代码语言:javascript
复制
@authwared
private RedisDataSoureceTransaction manualTransaction

TransactionStatus transactionStatus = null;
try {
 // // ####开启手动事务
 transactionStatus = manualTransaction.begin();
 
 // 删除或者更新数据库的数据
 ...........(业务代码省略)

 // 删除或者更新redis的值
 .............(业务代码省略)

 // #######提交事务
 manualTransaction.commit(transactionStatus);
 
} catch (Exception e) {
 try {
 // 回滚事务
 manualTransaction.rollback(transactionStatus);
 } catch (Exception e1) {
 }
 
}
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-12-11,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 IT大咖说 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
云数据库 Redis
腾讯云数据库 Redis(TencentDB for Redis)是腾讯云打造的兼容 Redis 协议的缓存和存储服务。丰富的数据结构能帮助您完成不同类型的业务场景开发。支持主从热备,提供自动容灾切换、数据备份、故障迁移、实例监控、在线扩容、数据回档等全套的数据库服务。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档