资讯专栏INFORMATION COLUMN

SpringDataRedis事务处理

nihao / 3208人阅读

摘要:准备的搭建应用之分布式缓存的乐观锁支持通过使用组成的事务来实现乐观锁注意没有用事务没有回滚操作。在当中通过的中来支持否则事务不生效。不要跟本文的乐观锁说的事务混淆在一起。参考第二天事务

本文主要讲述如何在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 strOps = redisTemplate.opsForValue();
        strOps.set(key, "hello");
        ExecutorService pool  = Executors.newCachedThreadPool();
        List> 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> futures = pool.invokeAll(tasks);
        for(Future 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 true.
     * 
     * @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 第二天(事务)

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/36154.html

相关文章

  • spring系列---SpringDataRedis使用

    摘要:官网介绍是一款开源的数据库,运行在内存中,由编写。企业开发通常采用来实现缓存。是大家族的一部分,提供了在应用中通过简单的配置访问服务,对底层开发包进行了高度封装,提供了各种操作异常处理及序列化,支持发布订阅,并对进行了实现。 SpringDataRedis简介 1项目常见问题思考 当每天大量流量访问系统的时候会对系统早上大量的压力 解决方式之一就是缓存,另一种是网页静态化。今天我先贴出...

    yagami 评论0 收藏0
  • redis的pipeline

    摘要:概要正常情况下,每个请求命令发出后通常会阻塞并等待服务端处理,服务端处理完后将结果返回给。当使用发送命令时,必须部分请求放到队列中使用内存执行完毕后一次性发送结果。 redis系列 redis的发布订阅功能 redis消息队列 redis的pipeline redis的scan操作 序 本文主要展示怎么在SpringDataRedis中使用pipeline。 pipeline概要 ...

    SimpleTriangle 评论0 收藏0
  • redis的scan操作

    摘要:语法之后返回两部分,第一部分是下次的参数,第二部分就是出来的项作用对象的额外参数指定每次取多少条匹配操作遍历数据库遍历遍历遍历参考用进行数据的迭代遍历迭代器遍历操作原理一基础 redis系列 redis的发布订阅功能 redis消息队列 redis的pipeline redis的scan操作 序 在redis的db存在大量key或者db里头的某个set、zset、hash里头的元素...

    springDevBird 评论0 收藏0
  • Spring嵌套事务是怎么回滚的?

    摘要:希望当注册课程发生错误时,只回滚注册课程部分,保证用户信息依然正常。期待结果是即便内部事务发生异常,外部事务俘获该异常后,内部事务应自行回滚,不影响外部事务。综上外层事务是否回滚的关键,最终取决于,该方法返回值正是在内层异常时设置的。 ...

    vboy1010 评论0 收藏0
  • spring事务处理

    摘要:声明式事务管理的事务管理是通过代理实现的。其中的事务通知由元数据目前基于或注解驱动。代理对象与事务元数据结合产生了一个代理,它使用一个实现品配合,在方法调用前后实施事务。 JDBC事务 1.获取连接 Connection con=DriverManager.getConnection(); 2.开启事务 con.setAutoCommit(true/fase); 3.执行CRUD 4....

    李文鹏 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<