redis的事务

来源:互联网 发布:gitlab windows 编辑:程序博客网 时间:2024/05/17 22:28
事务
为了保证多条命令组合的原子性,Redis提供了简单的事务以及集成Lua脚本来解决这个问题.


熟悉关系型数据库的开发者应该对事务比较了解,简单地说,事务表示一组动作,要么全部成功,要不全部不成功.例如在在电商网站中用户购买商品A那么需要将商品A的库存-1,并创建一个订单.这两个操作要么远不执行成功,要么全部执行不成功,否则会出现数据不一致的情况.


Redis提供了简单的功能,将一组需要一起执行的命令放到multi和exec两个命令之间.multi命令代表事务的开始,exec命令代表事务结束,他们之间的命令是原子顺序执行的.
例如上述的用户购买商品问题:


    127.0.0.1:6379> multi
    OK
    127.0.0.1:6379> hincrby commodity:a:detail stock -1
    QUEUE
    127.0.0.1:6379> rpush user:1:orders {"commodity":'a',..}
    QUEUE
可以看到数据操作命令返回的结果是QUEUE,代表命令并没有真正执行,而是暂时保存在Redis中.如果此时另一个客户端执行llen user:1:orders返回结果为0.


    127.0.0.1:6379> llen user:1:orders
    (integer) 0
只有当exec执行后,用户购买商品的行为才算完成,如下两个结果对应hincrby和rpush命令.


    127.0.0.1:6379> exec
    1) (integer) 4  # 商品原库存为5
    2) (integer) 1
    127.0.0.1:6379> llen user:1:orders
    (integer) 1
如果要停止事务的执行,可以使用discard命令替代exec命令即可.


    127.0.0.1:6379> discard
    OK
    127.0.0.1:6379> llen user:1:orders
    (integer) 0
如果事务中的命令出现错误,Redis的处理机制也不尽相同.


1.命令错误
例如下面操作错将set写成了sett,属于语法错误,会造成整个事务无法执行,key和counter的值未发生变化:


    127.0.0.1:6379> mget key counter
    1) "hello"
    2) "100"
    127.0.0.1:6379> multi
    OK
    127.0.0.1:6379> sett key world
    (error) ERR unknown command 'sett'
    127.0.0.1:6379> incr counter
    QUEUE
    127.0.0.1:6379> exec
    (error) EXECABORT Transaction discarded because of previous errors.
    127.0.0.1:6379> mget key counter
    1) "hello"
    2) "100"
2.运行时错误
例如用户购买商品,误把rpush写成了zadd


    127.0.0.1:6379> multi
    OK
    127.0.0.1:6379> hincrby commodity:a:detail stock -1
    QUEUED
    127.0.0.1:6379> zadd user:1:orders {"commodity":'a',..}
    QUEUED
    127.0.0.1:6379> exec
    1) (integer) 1
    2) (error) WRONGTYPE Operation against a key holding the wrong kind of value.
    127.0.0.1:6379> hget commodity:a:detail stack
    (integer) 3
原创粉丝点击