Redis事务和锁操作

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/zmh458/article/details/89511609


叙述

redis事务

Redis中的事务(transaction)是一组命令的集合。事务同命令一样都是Redis最小的执行单位,一个事务中的命令要么都执行,要么都不执行。Redis事务的实现需要用到 MULTI 和 EXEC 两个命令,事务开始的时候先向Redis服务器发送 MULTI 命令,然后依次发送需要在本次事务中处理的命令,最后再发送 EXEC 命令表示事务命令结束。
Redis的事务是下面4个命令来实现:
1.multi,开启Redis的事务,置客户端为事务态。
2.exec,提交事务,执行从multi到此命令前的命令队列,置客户端为非事务态。
3.discard,取消事务,置客户端为非事务态。
4.watch,监视键值对,作用时如果事务提交exec时发现监视的监视对发生变化,事务将被取消。


redis事务保证

MULTI, EXEC, DISCARD 和WATCH命令是Redis事务操作的基础 。他们可以让Redis在一个步骤里执行一组命令,且能做到如下2个重要保证:

  • 事务中的所有命令都是序列化且都是按顺序执行的。在一个客户端执行Redis事务的过程中,不会接收其他任何客户端对它发出的请求。这保证了这些命令是作为一个单独的独立操作执行的。
  • 所有的命令要么都被一起处理,要么全都没有被处理,所以Redis事务是原子的。EXEC会命令触发事务中所有命令的执行。当正在使用AOF时,Redis会使用一个简单的write(2)系统级调用来确保把事务写入到磁盘。但是,如果Redis服务崩溃,或者被系统管理员以某种强制的方式杀死,那么可能只有部分命令被写入到磁盘。Redis在重新启动时会检测这种情况,并报错,然后退出。使用 redis-check-aof工具可以检查AOF,并移除那不完整的事务,使服务可以再次启动

一个事务从开始到执行会经历以下三个阶段:
事务开始(以MULTI为标志) -> 命令入队(命令一次进入队列) -> 事务执行(通过EXEC执行)

  • 开始事务。
  • 命令入队。
  • 执行事务。

用法

使用 MULTI 命令进入事务模式.这个命令只会返回OK。这个时候,用户就可以发出多个要一起执行的命令了。 Redis暂时不会执行这些命令,而是把它们放进队列。 当 EXEC 被调用时,所有的命令才会被一次性执行.

相反的,如果调用了 DISCARD 命令,则会清除事务队列中的所有命令,然后退出事务.
在这里插入图片描述

为什么Redis不支持回滚

Redis命令在事务中可能会执行失败,但是Redis事务不会回滚,而是继续会执行余下的命令。如果您有一个关系型数据库的知识,这对您来说可能会感到奇怪,因为关系型数据在这种情况下都是会回滚的。

Redis这样做,主要是因为:

  • 只有当发生语法错误(这个问题在命令队列时无法检测到)了,Redis命令才会执行失败, 或对keys赋予了一个类型错误的数据:这意味着这些都是程序性错误,这类错误在开发的过程中就能够发现并解决掉,几乎不会出现在生产环境。
  • 由于不需要回滚,这使得Redis内部更加简单,而且运行速度更快。

乐观锁(check-and-set)

WATCH 命令为事务提供一个check-and-set (CAS) 行为。

WATCH 可以用来监听事务中的队列中的命令,在EXEC之前,一旦发现有一个命令被修改了的 , 那么整个事务就会终止, EXEC返回一个 Null ,提示用户事务失败了。

例如, 我们要自动的递增一个key (假设Redis还没有实现 INCR命令).
如果在同一时间,只有一个客户端在执行上面的操作,那么上面的操作是可靠的。但如果同时有多个用户执行上面的操作的话,那结果就是不可靠的了

我们可以使用 WATCH 来很好的解决这个问题:

使用以上的代码,当有另一个用户在我们调用WATCH 和 EXEC之间,修改了mykey的值val,那么这个事务就会失败。这种形式的锁称为乐观锁,是一种非常强大的锁。

WATCH 说明

WATCH 到底是什么意思呢? 这个命令使得 EXEC 命令的执行必须满足一个条件:如果被WATCH的 keys 没有一个被更改(但它们可以在事务中被修改),则执行事务;不然,就不会执行这个事务。(注意,如果你 WATCH了一个有生命周期的key,并且这个key过期了, EXEC 依然会执行)

WATCH 可以被多次调用。所有的WATCH 调用都会在 EXEC 调用之前起作用。WATCH可以接收任意多的key 。

当 EXEC 被调用后, 所有的keys都将UNWATCH,不管这个事务会不会终止。同样,当一个客户端链接关闭后, 一切都将UNWATCH。

可以使用UNWATCH (没有参数)命令来刷新所有被WATCH的keys。有时会这样操作,我们乐观地锁定了几个keys,因为可能我们需要执行一个事务来修改这些keys,但是在读取了keys的当前内容之后,我们不想继续处理了。那么这个时候,我们就可以调用UNWATCH。


小结

  • 事务提供了一种将多个命令打包,然后一次性、有序地执行的机制。
  • 多个命令会被入队到事务队列中,然后按先进先出(FIFO)的顺序执行。
  • 事务在执行过程中不会被中断,当事务队列中的所有命令都被执行完毕之后,事务才会结束。
  • 带有WATCH命令的事务会将客户端和被监视的键在数据库的watched keys字典中进行关联,当键被修改时,程序会将所有监视被修改键的客户端的REDIS_ DIRTY CAS标志打开。
  • 只有在客户端的REDIS_DIRTY_CAS标志未被打开时,服务器才会执行客户端提交的事务,否则的话,服务器将拒绝执行客户端提交的事务。
  • Redis的事务总是具有ACID中的原子性、一致性和隔离性,当服务器运行在AOF持久化模式下,并且appendfsync选项的值为aiways时,“事务也具有耐久性。
    感谢您的阅读~~

猜你喜欢

转载自blog.csdn.net/zmh458/article/details/89511609