• Redis


    Redis的事务基于四个命令:

    • MULTI
    • EXEC
    • DISCARD
    • WATCH

    创建事务

    Redis的事务从一个MULTI命令开始,MULTI总会命令返回"ok"。
    接着就可以开始输入操作数据,每一条操作命令都会进入队列。
    最后执行EXEC,在队列中的命令得到执行。

    比如这样:

    > MULTI
    OK
    > INCR foo
    QUEUED
    > INCR bar
    QUEUED
    > EXEC
    1) (integer) 1
    2) (integer) 1
    


    如果事务中出现错误怎么办?
    首先我们将事务中的错误分为两类:

    • 进入队列前发现错误,比如命令的语法错误。
    • EXEC执行后发现错误,比如对同一个key执行的两次不同数据类型的操作。

    第一种很好理解,就像上面给出的例子中,成功进入队列后会立马返回"QUEUED"。
    如果没能进入队列,则整个事务都会失效,提示"Transaction discarded because of previous errors."

    关于EXEC执行后出现的错误,凡是成功进入队列的都会被执行,即便同一事物中有执行失败的命令,其余的命令都会得到执行

    这让那些用过关系型数据库的人们感到诧异, 为什么Redis不支持roll back?
    对此官网的两点说法:

    • Redis commands can fail only if called with a wrong syntax (and the problem is not detectable during the command queueing), or against keys holding the wrong data type: this means that in practical terms a failing command is the result of a programming errors, and a kind of error that is very likely to be detected during development, and not in production.

    • Redis is internally simplified and faster because it does not need the ability to roll back.

    有人说不支持roll back会引发各种bug。但需要明白的是,roll back不是用来解决编程层面上的错误的。
    而且,导致命令失败只有两种可能:

    • 语法错误
    • 执行了与key的数据类型不匹配的操作

    鉴于此,roll back几乎没有任何意义,Redis更倾向于不支持roll back而是保持简洁和高效。

    丢弃事务

    DISCARD可以用作丢弃当前事务,并将连接状态恢复为正常状态。
    使用方法如下:

    > SET foo 1
    OK
    > MULTI
    OK
    > INCR foo
    QUEUED
    > DISCARD
    OK
    > GET foo
    "1"
    

    原子性

    check-and-set(CAS)之类的操作往往会出现竟态条件。
    Redis提供了WATCH用于观察key的变化。
    当一个被观察的key在EXEC执行前变化时,整个事务会终止并返回Nil,对该key的观察也会结束。
    刚接触WATCH的时候,感觉这种处理方式很晦涩。不能加个显示锁什么的吗?
    好在官网给出了充分的说明,先假设Redis没有提供INCR,我们现在要模拟一个递增操作:

    val = GET mykey
    val = val + 1
    SET mykey $val
    

    一个client进行该操作时是没有问题,但多个client一起进行该操作时会出现竟态条件。
    比如A和B两个client同时进行了GET mykey,得到的都是10,因此两次执行的结果是11而不是12。
    而加入WATCH后:

    WATCH mykey
    val = GET mykey
    val = val + 1
    MULTI
    SET mykey $val
    EXEC
    

    如果WATCH和EXEC之间有其他的什么东东改变了被观察的key,该事务则会失败。
    如果希望本次事务执行成功则需要在循环中执行,当然,这也是一种locking方式。
    事实上,多个client访问同一key的冲突并不常见,看具体情况进行操作吧。

    相应地,也有UNWATCH可以用于释放所有被观察的key。

    比如下面的例子中,事务内的INCR会成功执行:

    
    WATCH key
    UNWATCH key
    MULTI
    INCR key
    EXEC

    关于WATCH,需要注意的一点是:设置了生存时间(EXPIRE)的key不会因为到期而被WATCH当作以改变。

  • 相关阅读:
    【个人笔记】MySQL聚合函数、子查询
    artTemplate的使用总结
    【学习笔记】node.js入门基础
    【知了堂学习笔记】SQL查询基础语句(单表查询、多表查询)
    浅谈java final关键字
    3D魔幻旋转
    3分钟实现星空图
    深入浅出,谈谈面向对象几大特征
    html,css常用标签
    java中常用集合的理解
  • 原文地址:https://www.cnblogs.com/kavlez/p/4133579.html
Copyright © 2020-2023  润新知