• Redis 事务,和传统的关系型数据库ACID并不同,别搞混了


    十年河东,十年河西,莫欺少年穷

    学无止境,精益求精

    首先说下,我的 Redis 系列博客如下:

    [置顶] 高并发时,使用Redis应注意的问题【缓存穿透、缓存击穿.、缓存雪崩】

    windows环境下配置Redis主从复制-一主二仆,薪火相传、反客为主、哨兵模式

    Redis 持久化技术 ,大名鼎鼎的Rdb和Aof,你会选谁呢?

    简单介绍下Redis消息队列,实际生产环境中,大数据高并发时,不建议使用Redis做消息队列中间件

    Redis 事务,和传统的关系型数据库ACID并不同,别搞混了

    Redis常用配置redis.conf介绍,别把默认配置部署到到服务器,否则,会被领导骂的

    C# Nuget程序集StackExchange.Redis操作Redis 及 Redis 视频资源 及 相关入门指令 牛逼不,全都有

    Redis 的基础数据类型

    Window环境下安装Redis 并 自启动Redis 及 Redis Desktop Manager

    进入正文

    1、Redis事务是什么

    首先需要说的是,Redis事务不同于传统关系型数据库的事务,也不存在ACID属性,传统关系型数据库事务对操作结果的强一致性要求很严格,事务中的操作要么全做,要么全不做。

    而,Redis事务则没有那么严格的强一致性,Redis事务是将一系列的指令加入到队列中,具有一致性,排他性的执行,但在执行过程中并不保证每条指令都成功,他可能是部分成功,部分不成功,也可能是全部不成功,或者全部成功。因此,这点和传统的关系型数据库差别还是很大的。

    2、Redis事务的相关指令

    Redis事务有五个指令,分别为:MULTI 、 EXEC 、 DISCARD 、 WATCH、UNWATCH

    用法

    MULTI 命令用于开启一个事务,它总是返回 OK

    MULTI 执行之后, 客户端可以继续向服务器发送任意多条命令, 这些命令不会立即被执行, 而是被放到一个队列中, 当 EXEC 命令被调用时, 所有队列中的命令才会被执行。

    另一方面, 通过调用 DISCARD , 客户端可以清空事务队列, 并放弃执行事务。

    WATCH 使得 EXEC 命令需要有条件地执行: 事务只能在所有被监视键都没有被修改的前提下执行, 如果这个前提不能满足的话,事务就不会被执行。

    如果你使用 WATCH 监视了一个带过期时间的键, 那么即使这个键过期了, 事务仍然可以正常执行, 关于这方面的详细情况,请看这个帖子: http://code.google.com/p/redis/issues/detail?id=270

    WATCH 命令可以被调用多次。 对键的监视从 WATCH 执行之后开始生效, 直到调用 EXEC 、DISCARD、UNWATCH 为止。

    用户还可以在单个 WATCH 命令中监视任意多个键。

    另外, 当客户端断开连接时, 该客户端对键的监视也会被取消。

    使用无参数的 UNWATCH 命令可以手动取消对所有键的监视。 对于一些需要改动多个键的事务, 有时候程序需要同时对多个键进行加锁, 然后检查这些键的当前值是否符合程序的要求。 当值达不到要求时, 就可以使用 UNWATCH 命令来取消目前对键的监视, 中途放弃这个事务, 并等待事务的下次尝试。

    redis> WATCH key1 key2 key3
    OK

    另外, 当客户端断开连接时, 该客户端对键的监视也会被取消。

    当执行 DISCARD 命令时, 事务会被放弃, 事务队列会被清空, 并且客户端会从事务状态中退出,监视的Key也会取消。

    使用无参数的 UNWATCH 命令可以手动取消对所有键的监视。 对于一些需要改动多个键的事务, 有时候程序需要同时对多个键进行加锁, 然后检查这些键的当前值是否符合程序的要求。 当值达不到要求时, 就可以使用 UNWATCH 命令来取消目前对键的监视, 中途放弃这个事务, 并等待事务的下次尝试。

     OK,说了这么多理论,我来点示例来说明Redis事务。

    Redis示例,【以银行信用卡场景进行模拟,总额度:Total_M,剩余额度:SY_M,账单金额:ZD_M】

    首先进行各参数初始化:总额度10000元,账单金额0元,剩余额度10000元

    127.0.0.1:6379> set Total_M 10000
    OK
    127.0.0.1:6379> set ZD_M 0
    OK
    127.0.0.1:6379> set SY_M 10000
    OK
    127.0.0.1:6379>     

    1、正常执行【带女票吃饭,花了500元,EXEC】

    127.0.0.1:6379> MULTI
    OK
    127.0.0.1:6379> set SY_M 9500
    QUEUED
    127.0.0.1:6379> set ZD_M 500
    QUEUED
    127.0.0.1:6379> EXEC
    1) OK
    2) OK
    127.0.0.1:6379> get SY_M
    "9500"
    127.0.0.1:6379> get ZD_M
    "500"
    127.0.0.1:6379>   

    2、放弃事务【交易时,脑子一箱,这东西女友不喜欢,我不买了,DISCARD】

    127.0.0.1:6379> MULTI
    OK
    127.0.0.1:6379> set SY_M 9000
    QUEUED
    127.0.0.1:6379> set ZD_M 500
    QUEUED
    127.0.0.1:6379> discard
    OK
    127.0.0.1:6379> get SY_M
    "9500"
    127.0.0.1:6379> get ZD_M
    "500"
    127.0.0.1:6379>    

    3、全体连坐【语法上有一个错误的,全部不执行】

    127.0.0.1:6379> MULTI
    OK
    127.0.0.1:6379> set k1 v1
    QUEUED
    127.0.0.1:6379> set k2 v2
    QUEUED
    127.0.0.1:6379> get k2
    QUEUED
    127.0.0.1:6379> set k3 v3
    QUEUED
    127.0.0.1:6379> getset k2  ---语法上系统直接报错了,因此会全部不执行。
    (error) ERR wrong number of arguments for 'getset' command
    127.0.0.1:6379> exec
    (error) EXECABORT Transaction discarded because of previous errors.
    127.0.0.1:6379> 

    4、冤有头债有主【语法上系统不报错,但实际执行时行不通的】

    127.0.0.1:6379> MULTI
    OK
    127.0.0.1:6379> set K1 aa
    QUEUED
    127.0.0.1:6379> incr K1  ----K1是字符串类型,针对字符串做加一的操作,是行不通的,因此,Redis会跳过此指令而执行其他指令,
    QUEUED
    127.0.0.1:6379> set K2 22
    QUEUED
    127.0.0.1:6379> get K2
    QUEUED
    127.0.0.1:6379> exec
    1) OK
    2) (error) ERR value is not an integer or out of range
    3) OK
    4) "22"
    127.0.0.1:6379> 

    5、WATCH 监控【监控一个或多个Key,当监控时,如果有外部线程更改了监控Key的值,则事务不会执行】

    127.0.0.1:6379> WATCH Total_M  1、监控Total_M
    OK
    127.0.0.1:6379> Multi          2、开启一个事务
    OK
    127.0.0.1:6379> set SY_M 8000  3、修改剩余额度为8000
    QUEUED
    127.0.0.1:6379> set ZD_M 2000  4、修改账单为2000
    QUEUED
    127.0.0.1:6379> get SY_M         
    QUEUED
    127.0.0.1:6379> get ZD_M
    QUEUED
    127.0.0.1:6379> Exec           5、在最后执行之前,有外部线程修改了监控的Total_M的值,这一步相当于银行给你提升额度。
    (nil)                          6、由于外部进程修改了监控的Key的值,因此事务执行失败。
    127.0.0.1:6379>                                                                                                                           
    在最后执行之前,有外部线程修改了监控的Total_M的值,如下:
    C:Userschenwolong>redis-cli
    127.0.0.1:6379> ping
    PONG
    127.0.0.1:6379> set Total_M 20000
    OK
    127.0.0.1:6379>

    6、UnWATCH 放弃事务【使用无参数的 UNWATCH 命令可以手动取消对所有键的监视】

    127.0.0.1:6379> WATCH Total_M
    OK
    127.0.0.1:6379> Watch SY_M ZD_M
    OK
    127.0.0.1:6379> UNWatch
    OK
    127.0.0.1:6379>   

    以上便是Redsi事务,能看到这里小虎斑都是棒棒哒

    @天才卧龙的博客

  • 相关阅读:
    Installing Oracle Database 12c Release 2(12.2) RAC on RHEL7.3 in Silent Mode
    周四测试
    假期生活
    《人月神话》阅读笔记三
    《人月神话》阅读笔记二
    《人月神话》阅读笔记一
    软件进度7
    软件进度6
    软件进度5
    软件进度4
  • 原文地址:https://www.cnblogs.com/chenwolong/p/14562505.html
Copyright © 2020-2023  润新知