Redis系列6 - Redis事务 Bertha 。 2022-12-22 06:17 75阅读 0赞 **Redis事务的概念:** Redis 事务的本质是一组命令的集合。事务支持一次执行多个命令,一个事务中所有命令都会被序列化。在事务执行过程,会按照顺序串行化执行队列中的命令,其他客户端提交的命令请求不会插入到事务执行命令序列中。 总结说:redis事务就是一次性、顺序性、排他性的执行一个队列中的一系列命令。 **事务的特性** * 事务过程中的命令按顺序依次执行,执行过程不受其他客户端发出的命令影响,事务中的一组命令是一个与外界隔离的操作单元。 * 命令要么全部执行,要么全不执行。事务中命令的执行由EXEC命令触发。 **Redis事务没有隔离级别的概念:** 批量操作在发送 EXEC 命令前被放入队列缓存,并不会被实际执行,也就不存在事务内的查询要看到事务里的更新,事务外查询不能看到。 **Redis不保证原子性:** Redis中,单条命令是原子性执行的,但事务不保证原子性,且没有回滚。事务中任意命令执行失败,其余的命令仍会被执行。 **Redis事务的三个阶段:** * 开始事务 * 命令入队 * 执行事务 **Redis事务相关命令:** Redis使用MULTI, EXEC, DISCARD 和 WATCH 命令来实现事务功能。事务可以一次执行多个命令,并带有两个重要的保证: * 事务中的所有命令都被序列化并按顺序执行。Redis执行事务期间,不会被其它客户端发送的命令打断,事务中的所有命令都作为一个隔离操作顺序执行。 * Redis事务是原子操作,或者执行所有命令或者都不执行。EXEC 命令触发一个事务中所有命令的执行,所以,如果一个客户端断在调用EXEC 命令前丢失连接,那么所有的命令不会被执行,相反,如果EXEC 被调用,那么所有命令会被执行。当使用 append-only file 方式持久化时,Redis使用单个 write(2) 系统调用将事务写到磁盘上。但是,如果Redis服务器崩溃或被系统管理员以某种硬方式杀死,则可能只注册了部分操作。Redis重启的时候会检测到这种情况,并返回错误退出。使用 `redis-check-aof` 工具可以删除部分事务,这样Redis可以重新启动。 watch key1 key2 ... : 监视一或多个key,如果在事务执行之前,被监视的key被其他命令改动,则事务被打断 ( 类似乐观锁 ) multi : 标记一个事务块的开始( queued ) exec : 执行所有事务块的命令 ( 一旦执行exec后,之前加的监控锁都会被取消掉 ) discard : 取消事务,放弃事务块中的所有命令 unwatch : 取消watch对所有key的监控 **Redis事务使用案例:** 这些命令的使用方式如下: Copy `# 开启事务 MULTI command1 command2 # 触发事务 EXEC` `MULTI` 命令用于开启一个事务,它总是返回 `OK` 。`MULTI`执行之后, 客户端可以继续向服务器发送任意多条命令, 这些命令不会立即被执行, 而是被放到一个队列中。 `EXEC`命令负责触发并执行事务中的所有命令,`EXEC`命令的回复是一个数组, 数组中的每个元素都是执行事务中的命令所产生的回复。其中, 回复元素的先后顺序和命令发送的先后顺序一致。 当使用 AOF 方式做持久化的时候, Redis 会令将事务写入到磁盘中。然而,如果 Redis 服务器因为某些原因被管理员杀死,或者遇上某种硬件故障,那么可能只有部分事务命令会被成功写入到磁盘中。Redis 在重新启动时发现 AOF 文件出了这样的问题,那么它会退出,并汇报一个错误。使用 `redis-check-aof` 程序可以修复这一问题:它会移除 AOF 文件中不完整事务的信息,确保服务器可以顺利启动。 **(1)正常执行** ![31fe41238d44c1b074289624c60368f0.png][] **(2)放弃事务** ![20201118100616489.gif][] **(3)若在事务队列中存在命令性错误(类似于java编译性错误),则执行EXEC命令时,所有命令都不会执行** ![20201118100616490.gif][] **(4)若在事务队列中存在语法性错误(类似于java的1/0的运行时异常),则执行EXEC命令时,其他正确命令会被执行,错误命令抛出异常。** ![285fd9524c82487f0dac155d5a8df287.png][] **(5)使用watch** WATCH 命令可以为 Redis 事务提供 check-and-set (CAS)行为。 被 WATCH 的键会被监视,并会发觉这些键是否被改动过了。如果有至少一个被监视的键在 EXEC 执行之前被修改了, 那么整个事务都会被取消, EXEC 返回空来表示事务已经失败。 当发生被监控的键被改变时,程序需要做的就是不断重试这个操作, 直到没有发生碰撞为止。 案例一:使用watch检测balance,事务期间balance数据未变动,事务执行成功 ![5d5830b7d0faa4d6c2d414cba71edbbd.png][] 案例二:使用watch检测balance,在开启事务后(标注1处),在新窗口执行标注2中的操作,更改balance的值,模拟其他客户端在事务执行期间更改watch监控的数据,然后再执行标注1后命令,执行EXEC后,事务未成功执行。 ![20201118100616488.gif][] ![0e2ffaea00f8d7c4a6f9994c9634e741.png][] 一但执行 EXEC 开启事务的执行后,无论事务使用执行成功, WARCH 对变量的监控都将被取消。 故当事务执行失败后,需重新执行WATCH命令对变量进行监控,并开启新的事务进行操作。 ** 总结:** 通过上面的例子,可以看出Redis在执行事务命令的时候,在命令入队的时候, Redis 就会检测事务的命令是否正确,如果不正确则会产生错误。无论之前和之后的命令都会被事务所回滚,就变为什么都没有执行。 当命令格式正确,而因为操作数据结构引起的错误 ,则该命令执行出现错误,而其之前和之后的命令都会被正常执行。这点和数据库很不一样,这是需注意的地方。 对于一些重要的操作,我们必须通过程序去检测数据的正确性,以保证 Redis 事务的正确执行,避免出现数据不一致的情况。Redis 之所以保持这样简易的事务,完全是为了保证移动互联网的核心问题一----性能。 [31fe41238d44c1b074289624c60368f0.png]: /images/20221120/bf16614ebbd24ebfb911e0340feaeefb.png [20201118100616489.gif]: /images/20221120/df4e025c18a849038c2082260b98fa10.png [20201118100616490.gif]: /images/20221120/45551e45540a4027bb3df9f0c578920d.png [285fd9524c82487f0dac155d5a8df287.png]: /images/20221120/a0e8d516a8774f81ace8f5595b0a277a.png [5d5830b7d0faa4d6c2d414cba71edbbd.png]: /images/20221120/2d8a972c2eb34b4a89f8559c6ea44a47.png [20201118100616488.gif]: /images/20221120/70233a0a5a5e47208eb5ef878a91d56c.png [0e2ffaea00f8d7c4a6f9994c9634e741.png]: /images/20221120/3273ade5b67e4cccb7daade25cf12eb0.png
还没有评论,来说两句吧...