Redis事务

Redis 事务可以一次执行多个命令, 并且带有以下两个重要的保证:

  • 事务是一个单独的隔离操作:事务中的所有命令都会序列化、按顺序地执行。事务在执行的过程中,不会被其他客户端发送来的命令请求所打断。
  • 事务是一个原子操作:事务中的命令要么全部被执行,要么全部都不执行。但中间发生错误不会回滚,错误命令前后的其他命令都会被执行。

一个事务从开始到执行会经历以下三个阶段:

  • 开始事务。
  • 命令入队。
  • 执行事务。

当一个client在一个连接中发出multi命令有,这个连接会进入一个事务上下文,该连接后续的命令并不是立即执行,而是先放到一个队列中。当从此连接受到exec命令后,redis会顺序的执行队列中的所有命令。并将所有命令的运行结果打包到一起返回给client.然后此连接就结束事务上下文。执行discard命令取消事务,放弃执行事务块内的所有命令,结束事务上下文。例子:

    redis> multi
    OK
    redis> incr a
    QUEUED
    redis> incr b
    QUEUED
    redis> exec
    1. (integer) 1
    2. (integer) 1

watch命令
在执行命令的过程中,其他client如果修改这些(被watch的)值,那么exec就会执行失败,返回(nil)即此事务中所有命令执行失败。
例子:在图1watch和exec之间执行图2。


Redis事务_第1张图片
图1
图2

exec,discard,unwatch命令都会清除连接中的所有监视。

jedis例子:

    @Test
    public void jedisTransaction() throws Exception{
        Jedis jedis = JedisUtils.getJedis();
        String watch = jedis.watch("a","b");
        Transaction multi = jedis.multi();

        System.out.println(Thread.currentThread().getId()+"--"+watch);
        //dosomething
        multi.set("a","999");
        multi.set("b","888");
        try {
            Thread.sleep(30000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        List exec = multi.exec();
        System.out.println("---"+exec);
        jedis.unwatch();
    }

    @Test
    public void jedisTransactionAnotherClient() throws Exception{
        Jedis jedis = JedisUtils.getJedis();
        String watch = jedis.watch("a");
        Transaction multi = jedis.multi();

        System.out.println(Thread.currentThread().getId()+"--"+watch);
        //dosometing
        multi.set("a","777");


        List exec = multi.exec();
        System.out.println("---"+exec);
        jedis.unwatch();
    } 

                            
                        
                    
                    
                    

你可能感兴趣的:(Redis事务)