Redis之事务

简介: Redis之事务



前言

Redis事务命令(开启事务、提交事务、取消事务、监视)、乐观锁、悲观锁。


一、概述

Redis事务的本质是一组命令的集合

事务支持一次执行多个命令,一个事务中所有命令都会被序列化。

在事务执行过程,会按照顺序串行化执行队列中的命令,其他客户端提交的命令请求不会插入到事务执行命令序列中。

所以说:Redis 事务就是一次性、顺序性、排他性的执行一个队列中的一系列命令。

事务支持一次执行多个命令,一个事务中所有命令都会被序列化。

批量操作在发送 EXEC 命令前被放入队列缓存,并不会被实际执行。

Redis 事务不保证原子性

Redis中,单条命令是原子性执行的,但事务不保证原子性,且没有回滚。

事务中任意命令执行失败,其余的命令仍会被执行。

Redis事务的三个阶段

  • 开启事务
  • 命令入队
  • 执行事务

二、实例演示

1.正常执行事务

127.0.0.1:6379> multi  # 开启事务
OK
## 命令入队
127.0.0.1:6379(TX)> set k2 v2
QUEUED
127.0.0.1:6379(TX)> set k3 v3
QUEUED
127.0.0.1:6379(TX)> set k4 v4
QUEUED
127.0.0.1:6379(TX)> exec # 执行事务
OK
OK
OK

2.取消事务

127.0.0.1:6379> multi # 开启事务
OK
# 命令入队
127.0.0.1:6379(TX)> set k1 v1
QUEUED
127.0.0.1:6379(TX)> set k2 v2
QUEUED
127.0.0.1:6379(TX)> set k3 v3
QUEUED
127.0.0.1:6379(TX)> discard # 取消事务,事务队列中命令都不会执行
OK
127.0.0.1:6379> DBSIZE # 可以看出set命令未执行
0

3.编译型异常

若在事务队列中存在命令性错误(类似于java编译性错误),则执行 exec 命令时,所有命令都不会执行。

127.0.0.1:6379> flushall
OK
127.0.0.1:6379> multi
OK
# 命令入队
127.0.0.1:6379(TX)> set k1 v1
QUEUED
127.0.0.1:6379(TX)> set k2 v2
QUEUED
127.0.0.1:6379(TX)> getset k2 # 错误命令
ERR wrong number of arguments for 'getset' command
127.0.0.1:6379(TX)> set k3 v3  # 命令入队
QUEUED
127.0.0.1:6379(TX)> exec # 执行事务,报错 ,所有命令都不执行
EXECABORT Transaction discarded because of previous errors.

4.运行时异常

若在事务队列中存在语法性错误(类似于 Java 的的运行时异常),则执行exec命令时,其他正确命令会被执行,错误命令抛出异常。

127.0.0.1:6379> set k1 v1 # k1的值为字符串,无法实现增减
OK
127.0.0.1:6379> multi # 开启事务
OK
127.0.0.1:6379(TX)> incr k1 # 执行失败
QUEUED
127.0.0.1:6379(TX)> set k2 v2
QUEUED
127.0.0.1:6379(TX)> get k2
QUEUED
127.0.0.1:6379(TX)> exec 
ERR value is not an integer or out of range # 第一条命令报错,其他命令正常执行
OK
v2

5.监听

watch(乐观锁实现)

  • 悲观锁
    悲观锁(Pessimistic Lock),顾名思义,就是很悲观。
    每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁。
    这样别人想拿到这个数据就会 block 直到它拿到锁。
    传统的关系型数据库里面就用到了很多这种锁机制,比如行锁,表锁等,读锁,写锁等,都是在操作之前先上锁。
  • 乐观锁
    乐观锁(Optimistic Lock),顾名思义,就是很乐观。
    每次去拿数据的时候都认为别人不会修改,所以不会上锁。
    但是在更新的时候会判断一下再此期间别人有没有去更新这个数据,可以使用版本号等机制。
    乐观锁适用于多读的应用类型,这样可以提高吞吐量。
    乐观锁策略:提交版本必须大于记录当前版本才能执行更新。

(1)事务过程未有数据改变

127.0.0.1:6379> set money 100 # 余额
OK
127.0.0.1:6379> set out 0 # 支出
OK
127.0.0.1:6379> watch money # 监视money
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379(TX)> DECRBY money 20 # 余额减20
QUEUED
127.0.0.1:6379(TX)> INCRBY out 20 # 支出金额多20
QUEUED
127.0.0.1:6379(TX)> exec # 提交事务,成功执行
1) (integer) 80
2) (integer) 20

(2)事务过程其他线程改变数据

利用多线程测试

窗口1:

127.0.0.1:6379> watch money
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379(TX)> DECRBY money 10
QUEUED
127.0.0.1:6379(TX)> INCRBY out 10
QUEUED

窗口2:

127.0.0.1:6379> get money
"80"
127.0.0.1:6379> set money 200
OK

窗口1:

127.0.0.1:6379(TX)> exec # 事务提交,执行失败
(nil)

在窗口1事务提交前,窗口2修改了money的值。所以窗口1提交事务,执行失败。

解决:

窗口1:

127.0.0.1:6379> unwatch # 执行失败就先解除监听
OK
127.0.0.1:6379> watch money # 获取新值,重新监听,开启事务
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379(TX)> DECRBY money 10
QUEUED
127.0.0.1:6379(TX)> INCRBY out 10
QUEUED
127.0.0.1:6379(TX)> exec # 提交事务,执行成功(对比监视的值是否发生变化,没有则执行成功,否则失败)
1) (integer) 190
2) (integer) 30

总结

  • 一旦执行exec开启事务后,无论事务是否执行成功, watch 对变量的监听都将被取消。
  • 当事务执行失败后,需重新执行 watch 命令对变量进行监听,并开启新的事务进行操作。
  • watch 指令类似于乐观锁,在事务提交时,如果 watch 监控的多个 key 中任何 key 的值已经被其他客户端更改。则使用 exec 执行事务时,事务队列将不会被执行,同时返回 (nil) 应答以通知调用者事务执行失败。
相关文章
|
NoSQL Redis 数据库
10- 你们用过Redis的事务吗 ? 事务的命令有哪些 ?
```markdown Redis事务包括MULTI、EXEC、DISCARD、WATCH四个命令。虽具备事务功能,但在实际开发中使用较少。 ```
200 7
|
NoSQL Redis 数据库
什么是Redis的事务?
Redis事务提供原子性和顺序性,确保命令按顺序执行且不被打断。核心概念包括原子性、顺序性、隔离性和持久性。关键指令有MULTI、EXEC、DISCARD和WATCH,用于事务的开始、执行、取消和监视。这保障了命令的完整性,防止并发操作导致的数据不一致。
150 2
|
缓存 NoSQL 数据处理
Redis事务悄然而至:命令的背后故事
Redis事务悄然而至:命令的背后故事
134 0
|
缓存 NoSQL Redis
Redis 事务
10月更文挑战第18天
142 1
|
NoSQL Redis
Redis事务:保证数据操作的一致性和可靠性
Redis事务:保证数据操作的一致性和可靠性
280 0
|
4月前
|
监控 NoSQL 关系型数据库
Redis:事务(Transactions)
Redis事务支持将多个命令打包执行,但与MySQL不同,它不保证原子性、一致性、持久性和隔离性。Redis事务的核心在于“打包”命令,避免其他客户端插队,通过MULTI、EXEC、DISCARD等命令实现。此外,Redis提供WATCH和UNWATCH机制,用于监控键变化,实现类似“乐观锁”的功能,提升并发操作的安全性。
|
负载均衡 NoSQL 算法
一天五道Java面试题----第十天(简述Redis事务实现--------->负载均衡算法、类型)
这篇文章是关于Java面试中Redis相关问题的笔记,包括Redis事务实现、集群方案、主从复制原理、CAP和BASE理论以及负载均衡算法和类型。
一天五道Java面试题----第十天(简述Redis事务实现--------->负载均衡算法、类型)
|
NoSQL Redis
Redis事务长什么样?一文带你全面了解
Redis事务是一组命令的有序队列,通过MULTI、EXEC、WATCH和DISCARD等命令实现原子性操作。事务中的命令在EXEC执行前不会实际运行,而是先进入队列,确保所有命令要么全部成功,要么全部失败。此外,Redis还支持Lua脚本实现类似事务的操作,通常更简单高效。事务适用于购物车结算、秒杀活动、排行榜更新等需要保证数据一致性的场景。
162 0
|
SQL 分布式计算 NoSQL
大数据-42 Redis 功能扩展 发布/订阅模式 事务相关的内容 Redis弱事务
大数据-42 Redis 功能扩展 发布/订阅模式 事务相关的内容 Redis弱事务
154 2
|
NoSQL 关系型数据库 Redis
Redis6入门到实战------ 九、10. Redis_事务_锁机制_秒杀
这篇文章深入探讨了Redis事务的概念、命令使用、错误处理机制以及乐观锁和悲观锁的应用,并通过WATCH/UNWATCH命令展示了事务中的锁机制。
Redis6入门到实战------ 九、10. Redis_事务_锁机制_秒杀