Redis 事务

Redis事务

Redis的事务是一组命令的集合。事务同命令一样都是Redis的最小执行单元,一个事务中的命令,要么全部执行,要么都不执行。

Redis事务的原理

事务的原理是将一个事务的命令发送给Redis,然后在让Redis依次执行这些命令。

127.0.0.1:6379> multi
OK
127.0.0.1:6379> sadd user:1:following 2
QUEUED
127.0.0.1:6379> sadd user:2:followers 1
QUEUED
127.0.0.1:6379> exec
1) (integer) 1
2) (integer) 1

首先multi命令告诉Redis, 下面我发送给你的命令属于同一事务,你先不要执行,而且先把他们暂存起来。
当把所有要在同一事务中执行的命令都发送给Redis后, 我们使用exec告诉Redis将等待执行的事务队列的所有命令按照发送顺序依次执行
Redis保证同一事务的所有命令,要么全部执行,要么都不执行。如果在发送exec命令前客户端断了,则Redis会清空事务队列,事务中的所有命令都不执行,一旦客户端发送了exec命令,所有的命令都会被执行,即使客户端断线也没关系,因为Redis已经记录所有要执行的命令。
Redis还能保证一个事务内的命令依次执行,不会被其他命令插入。

Redis事务错误处理

如果一个事务中的某个命令出错了,Redis会怎么处理?
1、语法错误。语法错误指命令不存在或者参数的个数不对。只要有一个命令有语法错误, 执行exec命令后Redis就会直接返回错误,连正确语法的命令都不会执行。
2、运行错误。运行错误指命令在执行时出现错误,比如使用散列类型的命令执行集合类型的键,这种错误在实际执行之前Redis是无法发现的,所以在事务中这样的命令会被Redis接受并执行。如果事务中的一条命令出现运行错误,事务的其他命令会依然执行。
3、Redis事务没有关系型数据库提供的回滚功能,故开发者必须在事务执行出错后收拾自己的烂摊子(将数据库复原到事务执行前的状态)

watch命令

watch命令可以监控一个或多个键,一旦其中的一个键被修改或删除,之后的事务就不会执行,监控一致持续到exec命令(事务命令是在exec命令后执行的,所以multi命令后可以修改watch监控的键值)

127.0.0.1:6379> set key 1
OK
127.0.0.1:6379> watch key
OK
127.0.0.1:6379> multi 
OK
127.0.0.1:6379> set key 3
QUEUED
127.0.0.1:6379> exec
1) OK
127.0.0.1:6379> get key
"3"

我们知道一个事务中只有当所有命令都一次执行完后才能得到每个结果的返回值,但是在某些情况下,需要先获得一条命令的返回值,然后根据这个值执行下一条命令, 如incr命令使用get和set命令自己实现incr命令会出现竞态条件,伪代码如下

def incr($key):
    $value = get $key
    if not $value
        $value = 0
    $value = $value + 1
    set $key $value
    return $value

为了解决这个问题,Redis事务的另一个命令watch
执行了exec后会取消对所有键的监控,如果不想执行事务中的命令,也可以使用unwatch命令来取消监控。

posted @ 2020-08-14 11:09  phper-liunian  阅读(112)  评论(0编辑  收藏  举报