详解Redis事务

redis的事务概念

Redis通过MULTI、EXEC、WATCH等命令来实现事务( transaction)功能。事务提供了一种将多个命令请求打包,然后一次性、按顺序地执行多个命令的机制,并且在事务执行期间,服务器不会中断事务而改去执行其他客户端的命令请求,它会将事务中的所有命令都执行完毕,然后才去处理其他客户端的命令请求。

以下是一个事务执行的过程,该事务首先以一个MULTI命令为开始,接着将多个命令放入事务当中,最后由EXEC命令将这个事务提交( commit)给服务器执行:
在这里插入图片描述

redis事务的三个阶段

一个事务从开始到结束通常会经历以下三个阶段:事务开始,命令入队,事务执行。

下面了解下redis事务的三个阶段的实现原理:

  1. 事务开始
    MULTI命令的执行标志着事务的开始,MULTI命令可以将执行该命令的客户端从非事务状态切换至事务状态,这一切换是通过在客户端状态的flags属性中打开REDIS_MULTI标识来完成的,MULTI命令的实现可以用以下伪代码来表示:
    在这里插入图片描述

  2. 命令入队
    当一个客户端处于非事务状态时,这个客户端发送的命令会立即被服务器执行,与此不同的是,当一个客户端切换到事务状态之后,服务器会根据这个客户端发来的不同命令执行不同的操作:

    • 如果客户端发送的命令为EXEC、DISCARD、WATCH、MULTI 四个命令的其中一个,那么服务器立即执行这个命令。
    • 如果客户端发送的命令为EXEC、DISCARD、WATCH、MULTI 四个命令的其中一个,那么服务器立即执行这个命令。
      与此相反,如果客户端发送的命令是EXEC、DISCARD、WATCH、MULTI四个命令以外的其他命令,那么服务器并不立即执行这个命令,而是将这个命令放人一个事务队列里面,然后向客户端返回QUEUED回复。

    事务队列是一个数组,事务队列以先进先出(FIFO)的方式保存入队的命令,较先入队的命令会被放到数组的前面,而较后人队的命令则会被放到数组的后面。

    服务器判断命令是该入队还是该立即执行的过程可以用下面流程图来描述。
    在这里插入图片描述

  3. 事务执行
    当一个处于事务状态的客户端向服务器发送EXEC命令时,这个EXEC命令将立即被服务器执行。服务器会遍历这个客户端的事务队列,执行队列中保存的所有命令,最后将执行命令所得的结果全部返回给客户端。

redis事务的四大特性(ACID)

  1. redis支持原子性吗?
    事务具有原子性指的是,数据库将事务中的多个操作当作一个整体来执行,服务器要么就执行事务中的所有操作,要么就一个操作也不执行。对于Redis 的事务功能来说,事务队列中的命令要么就全部都执行,要么就一个都不执行,因此,Redis的事务是具有原子性的。

  2. redis支持一致性吗?
    事务具有一致性指的是,如果数据库在执行事务之前是一致的,那么在事务执行之后,无论事务是否执行成功,数据库也应该仍然是一致的。redis事务支持一致性

  3. redis支持隔离性吗?
    事务的隔离性指的是,即使数据库中有多个事务并发地执行,各个事务之间也不会互相影响,并且在并发状态下执行的事务和串行执行的事务产生的结果完全相同。因为Redis使用单线程的方式来执行事务(以及事务队列中的命令),并且服务器保证,在执行事务期间不会对事务进行中断,因此,Redis的事务总是以串行的方式运行的,并且事务也总是具有隔离性的。

  4. redis支持持久性吗?
    事务的耐久性指的是,当一个事务执行完毕时,执行这个事务所得的结果已经被保存到永久性存储介质(比如硬盘)里面了,即使服务器在事务执行完毕之后停机,执行事务所得的结果也不会丢失。
    因为Redis的事务不过是简单地用队列包裹起了一组Redis命令,Redis并没有为事务提供任何额外的持久化功能,所以Redis事务的耐久性由Redis所使用的持久化模式决定:

    1. 当服务器在无持久化的内存模式下运作时,事务不具有耐久性:一旦服务器停机,包括事务数据在内的所有服务器数据都将丢失。
    2. 当服务器在RDB持久化模式下运作时,服务器只会在特定的保存条件被满足时,才会执行BGSAVE命令,对数据库进行保存操作,并且异步执行的BGSAVE不能保证事务数据被第一时间保存到硬盘里面,因此RDB持久化模式下的事务也不具有耐久性。
    3. 当服务器运行在AOF持久化模式下,并且 appendfsync选项的值为always时,程序总会在执行命令之后调用同步( sync)函数,将命令数据真正地保存到硬盘里面,因此这种配置下的事务是具有耐久性的。
    4. 当服务器运行在AOF持久化模式下,并且 appendfsync选项的值为everysec时,程序会每秒同步一次命令数据到硬盘。因为停机可能会恰好发生在等待同步的那一秒钟之内,这可能会造成事务数据丢失,所以这种配置下的事务不具有耐久性。
    5. 当服务器运行在AOF持久化模式下,并且 appendfsync选项的值为no时,程序会交由操作系统来决定何时将命令数据同步到硬盘。因为事务数据可能在等待同步的过程中丢失,所以这种配置下的事务不具有耐久性。
  5. redis事务支持回滚吗?
    不支持

redis中的watch命令了解吗?

WATCH命令是一个乐观锁( optimistic locking ),它可以在EXEC命令执行之前,监视任意数量的数据库键,并在EXEC命令执行时,检查被监视的键是否至少有一个已经被修改过了,如果是的话,服务器将拒绝执行事务,并向客户端返回代表事务执行失败的空回复。

举个例子:
在这里插入图片描述watch命令的原理:
每个Redis数据库都保存着一个watched_keys字典,这个字典的键是某个被WATCH命令监视的数据库键,而字典的值则是一个链表,链表中记录了所有监视相应数据库键的客户端;通过执行WATCH命令,客户端可以在watched_keys字典中与被监视的键进行关联。

具体的watch命令的实现原理请参考《redis设计与实现》

总结

  • 事务提供了一种将多个命令打包,然后一次性、有序地执行的机制。多个命令会被入队到事务队列中,然后按先进先出(FIFO)的顺序执行。
  • 事务在执行过程中不会被中断,当事务队列中的所有命令都被执行完毕之后,事务才会结束。
  • 带有WATCH命令的事务会将客户端和被监视的键在数据库的watched_keys字典中进行关联,当键被修改时,程序会将所有监视被修改键的客户端的REDISDIRTY_CAS标志打开。
  • 只有在客户端的REDIS_DIRTY_CAS标志未被打开时,服务器才会执行客户端提交的事务,否则的话,服务器将拒绝执行客户端提交的事务。
  • Redis 的事务总是具有ACID中的原子性、一致性和隔离性,当服务器运行在AOF持久化模式下,并且 appendfsync选项的值为always时,事务也具有耐久性。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值