zoukankan      html  css  js  c++  java
  • Redis事务

    一:Redis的事务

      Redis通过MULTIEXECDISCARD 和 WATCH 命令来实现事务的支持,通过它们我们可以一步操作执行一组命令,而且确保了两个重要的特征如下

    1.所有的命令在一个事务中可确保顺序执行,切不会被其它线程打断(插入其它指令)。

    2.确保所有的命令要么全部执行要么一个也不执行。注意并不能保证每个任务都执行成功,而且失败的命令也不能回滚事务。

    二:使用方法

    步骤1: 开启事务   MULTI

    步骤2: 执行命令   command1 command2 ....

    步骤3: 执行事务   EXEC  或 DISCARD

    127.0.0.1:6379> MULTI
    OK
    127.0.0.1:6379> INCR foo
    QUEUED
    127.0.0.1:6379> INCR bar
    QUEUED
    127.0.0.1:6379> exec
    1) (integer) 1
    2) (integer) 1

    备注:exec返回一个数组对象,数组的每个对象顺序对应每个执行的命令

    三:事务的失败分析

      通常一个事务的失败原因主要可分为两类

    类1:命令如队(queue)失败,即在EXEC命令调用之前失败,失败的原因多为命令-参数错误,或者是内存溢出

    127.0.0.1:6379> MULTI
    OK
    127.0.0.1:6379> incr a b c
    (error) ERR wrong number of arguments for 'incr' command

    类2:EXEC命令调用之后失败。注意一组命令其中一个命令失败,并不会影响该命令后的其它命令的执行。

    127.0.0.1:6379> MULTI
    OK
    127.0.0.1:6379> set a abc
    QUEUED
    127.0.0.1:6379> lpop a
    QUEUED
    127.0.0.1:6379> exec
    1) OK
    2) (error) WRONGTYPE Operation against a key holding the wrong kind of value

    四:WATCH命令实现乐观锁

          WATCH通过check-and-set (CAS) 即检查然后设置的机制来实现事务的回滚特性,即被WATCHed的属性在执行事务之前会检查该属性值是否被其它线程改变,如果改变事务执行失败,否则继续。

    通过例子分析:有如下业务

    val = GET mykey  //步骤1:先获取属性值  若此时mykey的值为1
    val = val + 1    //步骤2:给值加1 
    SET mykey $val //步骤3:重新赋值熟悉

    若有2个线程同时执行以上代码,其结果mykey的值只能加1即值为2,(两个线程应该为3??)

    我们可以通过WATCH命令监控mykey,即当其它或当前线程修改了mykey属性的值,事务执行失败

    127.0.0.1:6379> set mykey 2
    OK
    127.0.0.1:6379> get mykey
    "2"
    127.0.0.1:6379> WATCH mykey   #监控mykey
    OK
    127.0.0.1:6379> get mykey     #查看mykey
    "2"
    127.0.0.1:6379> incr mykey    #重新赋值mykey  加1
    (integer) 3
    127.0.0.1:6379> MULTI         #开启事务
    OK
    127.0.0.1:6379> set mykey 4   #重新赋值mykey
    QUEUED
    127.0.0.1:6379> exec          #执行事务
    (nil)                         #执行失败
    127.0.0.1:6379> get mykey
    "3"

    备注:官方文档上说当前连接对watched属性操作不会影响事务,好像不是,这里有对这个疑问的讨论https://github.com/antirez/redis-doc/issues/734

    备注:UNWATCH指令,顾名思义即WATCH对立指令,即停止对某个属性的监控,exec和discard指令都会调用unwatch指令,我们也可以手动调用该指令。

    思考:WATCH是什么?它是EXEC命令执行的条件,即被监控的属性没有被修改过为TURE,否则为FALSE

    五:Redis脚本和事务

      Redis script(Redis脚本)是事务定义的,所以任何在事务中做的事情你都可以通过脚本完成,而且脚本更快和简单

    六:SpringBoot与Redis事务

    /**
         * 设置string类型的数据
         * 
         * @param key   健
         * @param value 值
         * @return   
         */
        public String setStringKey(String key, String value) {
            return redisTemplate.execute((RedisCallback<String>) con -> {
                //开启事务
                con.multi();
                con.set(key.getBytes(), value.getBytes());
                //执行事务
                con.exec();
                return new String("OK");
            });
        }
        /**
         * 测试redis事务的乐观锁--watch
         * @param key   健
         * @param value 值
         * @return   
         */
        public String checkWatch(String key) {
            return redisTemplate.execute((RedisCallback<String>) con -> {
                Integer integer = new Integer(1);
                //预备数据
                con.set(key.getBytes(), "1".getBytes());
                //锁定key
                con.watch(key.getBytes());
                //开启事务
                con.multi();
                con.incr(key.getBytes());
                //执行事务
                List<Object> exec = con.exec();
                Assert.notNull(exec,String.format("数据key=%s已被修改,请确认", key));
                for (Object object : exec) {
                    System.out.println(object);
                }
                return new String("OK");
            });
        }

    参考:https://redis.io/topics/transactions

  • 相关阅读:
    同一电脑登录多个github账号
    如何用HAProxy+Nginx实现负载均衡
    Windows10下 tensorflow-gpu 配置
    机器学习数据处理时label错位对未来数据做预测
    机器学习经典模型简单使用及归一化(标准化)影响
    学机器学习,不会数据处理怎么行?—— 二、Pandas详解
    版本控制系统 git 之基础讲解
    学机器学习,不会数据处理怎么行?—— 一、NumPy详解
    Reinforcement Learning 的那点事——强化学习(一)
    读研 or 工作?对计算机类专业学习的看法
  • 原文地址:https://www.cnblogs.com/jinliang374003909/p/13160879.html
Copyright © 2011-2022 走看看