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:\Users\chenwolong>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事务,能看到这里小虎斑都是棒棒哒

@天才卧龙的博客

 

posted @ 2021-03-21 14:08  天才卧龙  阅读(218)  评论(0编辑  收藏  举报