Redis 事务

Redis 事务

Redis事务的本质是一组命令的集合。事务支持一次执行多个命令,一个事务中所有命令都会被序列化。在事务执行过程,会按照顺序串行执行队列中的命令,其他客户提交的命令请求不会插入到事务执行命令序列中(不能加塞)。

什么事Redis事务

Redis 事务就是一次性、顺序性、排他性的执行一个队列中的一系列命名。

Redis事务相关命令

MULTI: 开启事务,redis会将后续的命令逐个放入队列中
EXEX: 执行事务中的所有操作命令
DISCARD: 取消事务,放弃执行事务块中的所有命令
WATCH: 监视一个或多个key,如果事务在执行前,这个key(或者多个key)被其他命令修改,则事务终端,不会执行事务的任何命令
UNWATCH:取消WATCH对所有key的监视

事务正常执行

    127.0.0.1:6379> set k1 v1
    OK
    127.0.0.1:6379> set k2 v2
    OK
    127.0.0.1:6379> MULTI
    OK
    127.0.0.1:6379(TX)> set k1 11
    QUEUED
    127.0.0.1:6379(TX)> set k2 22
    QUEUED
    127.0.0.1:6379(TX)> exec
    OK
    OK
    127.0.0.1:6379> get k1
    11
    127.0.0.1:6379> get k2
    22
    127.0.0.1:6379> 

事务取消

    127.0.0.1:6379> MULTI
    OK
    127.0.0.1:6379(TX)> set k1 33
    QUEUED
    127.0.0.1:6379(TX)> set k2 34
    QUEUED
    127.0.0.1:6379(TX)> DISCARD
    OK
    127.0.0.1:6379> get k1
    11
    127.0.0.1:6379> get k2
    22

事务错误处理

语法错误(编译器错误)

开启事务后,修改k1、k2的值,由于k2语法错误,事务提交失败k1、k2保留原值(全体连坐)

    127.0.0.1:6379> set k1 v1
    OK
    127.0.0.1:6379> set k2 v2
    OK
    127.0.0.1:6379> MULTI 
    OK
    127.0.0.1:6379(TX)> set k1 11
    QUEUED
    127.0.0.1:6379(TX)> set k2 22
    QUEUED
    127.0.0.1:6379(TX)> setssss k2 22
    ERR unknown command 'setssss', with args beginning with: 'k2' '22' 
    127.0.0.1:6379(TX)> exec
    EXECABORT Transaction discarded because of previous errors.
    127.0.0.1:6379> get k1 
    v1
    127.0.0.1:6379> get k2
    v2

Redis类型错误(运行时错误)

开启事务后,修改k1、k2的值,由于将k2的类型作为List,在运行时检测类型错误,最终导致事务提交失败,此时事务并没有回滚,而是跳过错误命令继续执行, 结果k1值改变、k2保留原值(冤头债主)

    127.0.0.1:6379> set k1 v1
    OK
    127.0.0.1:6379> set k2 v2
    OK
    127.0.0.1:6379> MULTI
    OK
    127.0.0.1:6379(TX)> set k1 11
    QUEUED
    127.0.0.1:6379(TX)> lpush k2 22
    QUEUED
    127.0.0.1:6379(TX)> exec
    OK
    WRONGTYPE Operation against a key holding the wrong kind of value
    127.0.0.1:6379> get k1
    11
    127.0.0.1:6379> get k2
    v2

WATCH监控

WATCH命令可以为Redis事务提供 check-and-set(CAS)行为。
被WATCH的键会被监视,并会发觉这些键是否被改动过。如果有至少一个监视器的键在EXEC执行之前被修改,那么整个事务都会被取消,EXEC返回nil-reply来表示事务已经失败。
举个🌰

watch监视

    127.0.0.1:6379> set k1 v1
    OK
    127.0.0.1:6379> set k2 v2
    OK
    127.0.0.1:6379> watch k1 
    OK
    127.0.0.1:6379> multi
    OK
    127.0.0.1:6379(TX)> set k1 11
    QUEUED
    127.0.0.1:6379(TX)> set k2 22
    QUEUED
    127.0.0.1:6379(TX)> exec
    (nil)
    127.0.0.1:6379> get k1 
    "123123"
    127.0.0.1:6379> get k2
    "v2"

UNWATCH 取消监视

    127.0.0.1:6379> set k1 v1
    OK
    127.0.0.1:6379> set k2 v2
    OK
    127.0.0.1:6379> watch k1
    OK
    127.0.0.1:6379> set k1 11
    OK
    127.0.0.1:6379> unwatch
    OK
    127.0.0.1:6379> multi
    OK
    127.0.0.1:6379(TX)> set k1 12
    QUEUED
    127.0.0.1:6379(TX)> set k2 22
    QUEUED
    127.0.0.1:6379(TX)> exec
    1) OK
    2) OK
    127.0.0.1:6379> get k1
    "12"
    127.0.0.1:6379> get k2
    "22"
    127.0.0.1:6379> 

小结

一旦执行了EXEC 之后之前加的监控锁都会被取消掉,当客户端连接丢失的时候(如退出链接),所有东西都会取消监视

watch流程

事务回滚

Redis不支持事务回滚这种做法优点:
1.不需要对回滚进行支持,所以 Redis 的内部可以保持简单且快速
2.Redis 命令只会因为错误的语法而失败(并且这些问题不能在入队时发现),或是命令用在了错误类型的键上面:这也就是说,从实用性的角度来说,失败的命令是由编程错误造成的,而这些错误应该在开发的过程中被发现,而不应该出现在生产环境中

Redis事务和数据库事务

一般来说,事务有四个性质称为ACID,分别是原子性,一致性,隔离性和持久性。这是基础,但是很多文章对Redis 是否支持ACID有一些异议
原子性atomicity
Redis的事务不保证原子性,也就是不保证所有指令同时成功或同时失败,只有决定是否开始执行全部指令的能力,没有执行到一半进行回滚的能力
一致性consistencyredis
redis事务可以保证命令失败的情况下得以回滚,数据能恢复到没有执行之前的样子,是保证一致性的,除非redis进程意外终结。
隔离性Isolationredis
Redis会保证一个事务内的命令依次执行,而不会被其它命令插入
持久性Durabilityredis
事务是不保证持久性的,这是因为redis持久化策略中不管是RDB还是AOF都是异步执行的,不保证持久性是出于对性能的考虑。

posted @ 2023-04-24 09:44  古拉加斯·浩二  阅读(73)  评论(0)    收藏  举报