• redis——事务


    一、Redis事务的基本用法

     1 127.0.0.1:6379> set int 0
     2 OK
     3 127.0.0.1:6379> multi        //begin  事务开始
     4 OK
     5 127.0.0.1:6379> incr int
     6 QUEUED                       //QUEUE  指令已经被服务器缓存到队列里了
     7 127.0.0.1:6379> incr int
     8 QUEUED
     9 127.0.0.1:6379> exec         //commit 事务提交 
    10 1) (integer) 1
    11 2) (integer) 2
    12 127.0.0.1:6379> multi        //begin  事务开始
    13 OK
    14 127.0.0.1:6379> incr int
    15 QUEUED
    16 127.0.0.1:6379> incr int
    17 QUEUED
    18 127.0.0.1:6379> discard      //discard  事务丢弃
    19 OK
    20 127.0.0.1:6379> get int
    21 "2"

     二、redis没有保证事务的的原子性

    事务四大特性:原子性、隔离性、持久性、一致性

    由于redis是单线程的,保证事务的隔离性,一致性,每个指令的原子性,redis持久性也能保持事务的持久性。但是redis没有保证多个指令的原子性,无法保证事务的原子性。

     1 127.0.0.1:6379> multi
     2 OK
     3 127.0.0.1:6379> set books java
     4 QUEUED
     5 127.0.0.1:6379> incr books
     6 QUEUED
     7 127.0.0.1:6379> set bookss golang
     8 QUEUED
     9 127.0.0.1:6379> exec
    10 1) OK  //执行成功
    11 2) (error) ERR value is not an integer or out of range //执行失败
    12 3) OK  //执行成功
    13 127.0.0.1:6379> get books
    14 "java"  //没有回退rollback
    15 127.0.0.1:6379> get bookss
    16 "golang" //没有回退rollback

     三、优化

    redis事务的每个指令到事务缓存队列时都要经过一次网络读写,所以通常Redis的客户端在执行事务时都会结合pipeline一起使用,可以将多次IO操作压缩为单次IO操作。

     1 public class TransactionTest {
     2 
     3     public static void main(String[] args){
     4         Pipeline pipeline = RedisUtils.pipelined();
     5         pipeline.multi();
     6         pipeline.incr("int");
     7         pipeline.incr("int");
     8         Response<List<Object>> response = pipeline.exec();
     9         pipeline.close();//get前需要关闭管道
    10         System.out.println(response.get());
    11         RedisUtils.close();
    12     }
    13 }

    四、watch

    watch在事务开始之前盯住一个或多个变量,当事务执行时,也就是服务器收到exec指令要顺序执行缓存的事务队列,Redis会检查关键变量自watch之后是否被修改。如果关键变量被修改过,exec指令就会返回NULL回复告知客户端事务执行失败。

     1 127.0.0.1:6379> watch int    //watch int
     2 OK
     3 127.0.0.1:6379> get int       
     4 "10"
     5 127.0.0.1:6379> incr int     //watch期间int被修改了
     6 (integer) 11
     7 127.0.0.1:6379> multi        //开启事务
     8 OK
     9 127.0.0.1:6379> incr int     
    10 QUEUED
    11 127.0.0.1:6379> exec         //执行事务
    12 (nil)                        //执行失败 返回null

     注意:

    ①禁止在multi与exec之间执行watch指令,必须在multi之前执行,否则会报错

    ②multi后exec前,不能关闭redis连接,否则会抛错ERR EXE without MULTI

    ③watch与multi与exec必须是同一个redis连接实例,否则不会生效。

    public class WatchTest {
    
        public static void main(String[] args){
            RedisUtils.CallWithRedis caller = new RedisUtils.CallWithRedis() {
                @Override
                public Object call(Jedis jedis) {
                    for (;;){
    //                    RedisUtils.watch("int");//watch multi exec必须是一个jedis实例
                        jedis.watch("int");
                        int value = Integer.parseInt(jedis.get("int"));
                        System.out.println("int : " + value);
    //                    RedisUtils.incr("int");//这里修改操作可以是不同的连接
                        jedis.incr("int");
    //                    Transaction transaction = RedisUtils.multi();//里面包含redis自动关闭连接,会导致exec报错
                        Transaction transaction = jedis.multi();
                        transaction.set("int","0");
                        List<Object> res = transaction.exec();
                        if(res != null){
                            System.out.println("transaction success");
                            break;
                        }
                        System.out.println("watchError!");
                    }
                    return 0;
                }
            };
            RedisUtils.watch(caller);
            RedisUtils.close();
        }
    }

    RedisUtils.java
    public static Object watch(CallWithRedis caller){
    return RedisUtils.execute(caller);
    }
     
  • 相关阅读:
    类型转换
    struts2默认拦截器
    struts2自定义拦截器
    struts2之I18N
    代理模式
    抽象类 abstract class 接口
    java基础题
    final
    内部类
    tomcat 端口占用问题解决
  • 原文地址:https://www.cnblogs.com/wqff-biubiu/p/12299209.html
Copyright © 2020-2023  润新知