简体   繁体   English

redis 事务与 jdbc 事务一起

[英]redis transaction alongside jdbc transaction

In our application we are using both MySQL server and Redis databases.在我们的应用程序中,我们同时使用 MySQL 服务器和 Redis 数据库。 we use Redis as a database and not just a cache.我们将Redis用作数据库而不仅仅是缓存。 we use both of them in a service method and I want to make the method @Transactional to let the spring manages my transactions.我们在服务方法中同时使用它们,我想让方法 @Transactional 让 spring 管理我的事务。 Hence if in the middle of an transactional method a RuntimeException is thrown all works on both Redis and MySQL are rolled back.因此,如果在事务方法的中间抛出 RuntimeException,Redis 和 MySQL 上的所有工作都将回滚。 I have followed the spring docs and configured my @SpringBootApplication class as following:我遵循了spring 文档并将我的 @SpringBootApplication 类配置如下:

@SpringBootApplication
@EnableTransactionManagement
public class TransactionsApplication {

    @Autowired
    DataSource dataSource;

    public static void main(String[] args) {
        SpringApplication.run(TransactionsApplication.class, args);
    }

    @Bean
    public StringRedisTemplate redisTemplate() {
        StringRedisTemplate template = new StringRedisTemplate(redisConnectionFactory());
        // explicitly enable transaction support
        template.setEnableTransactionSupport(true);
        return template;
    }

    @Bean
    public LettuceConnectionFactory redisConnectionFactory() {
        return new LettuceConnectionFactory(new RedisStandaloneConfiguration("localhost", 6379));
    }

    @Bean
    public PlatformTransactionManager transactionManager() throws SQLException, IOException {
        return new DataSourceTransactionManager(dataSource);
    }
}

and this is my service method:这是我的服务方法:

@Service
@RequiredArgsConstructor
@Slf4j
public class FooService {

   private final StringRedisTemplate redisTemplate;
   private final FooRepository fooRepository;

   @Transactional            
   public void bar() {

       Foo foo = Foo.builder()
               .id(1001)
               .name("fooName")
               .email("foo@mail.com")
               .build();
       fooRepository.save(foo);

       ValueOperations<String, String> values = redisTemplate.opsForValue();
       values.set("foo-mail", foo.getEmail());

   }

However after the test method of TestService is called there is no user in MySQL db and I think it's because there is no active transaction for it.Is there any solution for this problem?但是调用TestService的测试方法后,MySQL数据库中没有用户,我认为这是因为它没有活动事务。这个问题有什么解决方案吗? Should I use spring ChainedTransactionManager class and then how?我应该使用 spring ChainedTransactionManager类,然后如何使用? or I can only manage Redis transactions manually through MULTI ?或者我只能通过MULTI手动管理 Redis 事务?

After playing around with FooService class I found that using @Transactional in a service method that is intended to work with Redis and specially read a value from Redis (which I think most service methods are supposed to read some value from DB) is somehow useless since any read operation would result a null value and that is because Redis queues all operations of a transaction and executes them at the end.在玩过FooService类之后,我发现在旨在与 Redis 一起工作的服务方法中使用@Transactional并专门从 Redis 读取一个值(我认为大多数服务方法应该从 DB 读取一些值)在某种程度上是无用的,因为任何读取操作都会导致空值,这是因为 Redis 将事务的所有操作排队并在最后执行它们。 Summing up, I think using MULTI and EXEC operations is more preferable since it gives more control to use data in Redis.总而言之,我认为使用MULTIEXEC操作更可取,因为它可以更好地控制在 Redis 中使用数据。 After all, any suggestions to use Redis transactions is appreciated.毕竟,任何使用 Redis 事务的建议都值得赞赏。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM