转载

SpringDataRedis事务处理

本文主要讲述如何在java里头使用redis进行cas操作。其实呢,redis不像memcached那样显示地支持cas操作,不过它有事务的概念。

准备

  • redis的docker搭建

  • SpringBoot应用之分布式缓存

redis的乐观锁支持

Redis通过使用WATCH, MULTI, and EXEC组成的事务来实现乐观锁( 注意没有用DISCARD ),Redis事务没有回滚操作。在SpringDataRedis当中通过RedisTemplate的SessionCallback中来支持( 否则事务不生效 )。discard的话不需要自己代码处理,callback返回null,成的话,返回非null,依据这个来判断事务是否成功( 没有抛异常 )。

实例

@Test     public void cas() throws InterruptedException, ExecutionException {         String key = "test-cas-1";         ValueOperations<String, String> strOps = redisTemplate.opsForValue();         strOps.set(key, "hello");         ExecutorService pool  = Executors.newCachedThreadPool();         List<Callable<Object>> tasks = new ArrayList<>();         for(int i=0;i<5;i++){             final int idx = i;             tasks.add(new Callable() {                 @Override                 public Object call() throws Exception {                     return redisTemplate.execute(new SessionCallback() {                         @Override                         public Object execute(RedisOperations operations) throws DataAccessException {                             operations.watch(key);                             String origin = (String) operations.opsForValue().get(key);                             operations.multi();                             operations.opsForValue().set(key, origin + idx);                             Object rs = operations.exec();                             System.out.println("set:"+origin+idx+" rs:"+rs);                             return rs;                         }                     });                 }             });         }         List<Future<Object>> futures = pool.invokeAll(tasks);         for(Future<Object> f:futures){             System.out.println(f.get());         }         pool.shutdown();         pool.awaitTermination(1000, TimeUnit.MILLISECONDS);     }

输出

set:hello2 rs:null set:hello3 rs:[] set:hello1 rs:null set:hello4 rs:null set:hello0 rs:null

查看该值

127.0.0.1:6379> get test-cas-1 "/"hello3/""

SessionCallback

没有在SessionCallback里头执行watch、multi、exec,而是自己单独写

与数据库事务的混淆

template.setEnableTransactionSupport(true);

这个应该是支持数据库的事务成功才执行的意思。

/**      * Gets a Redis connection. Is aware of and will return any existing corresponding connections bound to the current      * thread, for example when using a transaction manager. Will create a new Connection otherwise, if      * {@code allowCreate} is <tt>true</tt>.      *       * @param factory connection factory for creating the connection      * @param allowCreate whether a new (unbound) connection should be created when no connection can be found for the      *          current thread      * @param bind binds the connection to the thread, in case one was created      * @param enableTransactionSupport      * @return an active Redis connection      */     public static RedisConnection doGetConnection(RedisConnectionFactory factory, boolean allowCreate, boolean bind,             boolean enableTransactionSupport) {          Assert.notNull(factory, "No RedisConnectionFactory specified");          RedisConnectionHolder connHolder = (RedisConnectionHolder) TransactionSynchronizationManager.getResource(factory);          if (connHolder != null) {             if (enableTransactionSupport) {                 potentiallyRegisterTransactionSynchronisation(connHolder, factory);             }             return connHolder.getConnection();         }          if (!allowCreate) {             throw new IllegalArgumentException("No connection found and allowCreate = false");         }          if (log.isDebugEnabled()) {             log.debug("Opening RedisConnection");         }          RedisConnection conn = factory.getConnection();          if (bind) {              RedisConnection connectionToBind = conn;             if (enableTransactionSupport && isActualNonReadonlyTransactionActive()) {                 connectionToBind = createConnectionProxy(conn, factory);             }              connHolder = new RedisConnectionHolder(connectionToBind);              TransactionSynchronizationManager.bindResource(factory, connHolder);             if (enableTransactionSupport) {                 potentiallyRegisterTransactionSynchronisation(connHolder, factory);             }              return connHolder.getConnection();         }          return conn;     }

不要跟本文的乐观锁说的事务混淆在一起。

参考

  • Redis-Transactions-via-Spring-Data-Redis

  • Spring-data-redis 第二天(事务)

原文  http://segmentfault.com/a/1190000004393573
正文到此结束
Loading...