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

Posted IT大咖说

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了面试官问:Redis的操作如何与数据库事务保持一致相关的知识,希望对你有一定的参考价值。

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

  • redis如何与数据库保持一致性的问题?

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

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

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

解决方案:

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

下面直接上代码 ,

  • 这个类包装了redis事务和数据库事务,一起开启事务,一起提交事务,一起回滚事务

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


  • redisUtils相关代码:

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


  • 在写业务代码时 大致这样写

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

代码如下 自己copy用

RedisDataSoureceTransaction 代码:


@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相关代码:

/**
* 开启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();
}

业务的大致模板代码:

@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) {
}

}




来都来了,走啥走,留个言呗~


 IT大咖说  |  关于版权 

感谢您对IT大咖说的热心支持!



相关推荐


推荐文章



最近活动




点击【阅读原文】更多IT技术圈

以上是关于面试官问:Redis的操作如何与数据库事务保持一致的主要内容,如果未能解决你的问题,请参考以下文章

Redis 如何与数据库事务保持一致

字节跳动面试官问:微服务下如何保证分布式事务的最终一致性?

面试官问:如何优化高并发相关的业务,你能回答的上来吗?

面试官问:微服务下有几种保证分布式事务最终一致性的方案?

面试官问:MySQL锁与事物隔离级别你知道吗?

147期面试官问:你讲讲分布式事务问题的几种方案?