【Redis】redis事物与管道
Redis 事务(Transaction)
事务概念
- 事务:是一组操作的集合,是不可分割的工作单元。
- Redis 事务特点:
- 一个事务可以一次执行多个命令。
- 所有命令都被顺序化,形成一个队列。
- 所有命令在执行
EXEC
时一次性、顺序执行。
与 MySQL 事务的区别
特点 | Redis | MySQL |
---|---|---|
提交前执行情况 | 命令只入队,执行 EXEC 前不实际执行 | 执行前可能已部分生效 |
原子性保障 | 不保证所有指令成功或失败(无回滚) | 支持回滚 |
执行过程 | 命令顺序执行,期间不被其它命令插入 | 依赖事务隔离级别 |
Redis 保证事务内命令顺序执行:
1 -> 2 -> 3
,不会变成1 -> 2 -> 被插队 -> 3
事务使用示例
1. 正常事务执行
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379(TX)> set k1 1
QUEUED
127.0.0.1:6379(TX)> set k2 2
QUEUED
127.0.0.1:6379(TX)> set k3 3
QUEUED
127.0.0.1:6379(TX)> EXEC
1) OK
2) OK
3) OK
2. 放弃事务
127.0.0.1:6379> MULTI
127.0.0.1:6379(TX)> set k1 11
127.0.0.1:6379(TX)> set k2 22
127.0.0.1:6379(TX)> DISCARD
OK
事务出错
1. 语法错误
在命令入队阶段就报错,事务无法执行:
127.0.0.1:6379> MULTI
127.0.0.1:6379(TX)> set k2
(error) ERR wrong number of arguments for 'set' command
127.0.0.1:6379(TX)> EXEC
(error) EXECABORT Transaction discarded because of previous errors.
2. 逻辑错误
命令入队成功,但某条命令在执行时失败,不影响其他命令:
127.0.0.1:6379> set name luobozi
127.0.0.1:6379> MULTI
127.0.0.1:6379(TX)> INCR name # name 是字符串,不能自增
127.0.0.1:6379(TX)> set k1 12
127.0.0.1:6379(TX)> EXEC
1) (error) ERR value is not an integer
2) OK
Redis 锁机制:乐观锁
Watch 命令
- 使用
WATCH
对某个 key 进行监控。 - 如果事务执行前该 key 被修改,
EXEC
执行失败,事务不会生效。
下面演示了Watch 对num施加了乐观锁,最后EXEC提交前修改了num导致事务失败
乐观锁 vs 悲观锁
类型 | 描述 |
---|---|
乐观锁 | 假设不会发生冲突,提交前检查(如 Redis WATCH ) |
悲观锁 | 假设总会冲突,使用互斥锁机制控制访问 |
Redis 管道(Pipeline)
原因
- TCP 通信频繁读写会造成性能瓶颈。
- 多次发送命令、等待响应效率低。
管道原理
- 一次性发送多条命令 到 Redis。
- Redis 执行完后 一次性返回结果。
- 不具有事务的隔离和原子性。
使用示例
# test.txt 文件内容:
get k1
set k2 v2
set k3 v3
# 使用管道批量执行
cat test.txt | redis-cli -a 123456 --pipe
注意:
- 管道命令执行失败,不会影响后续命令执行。
- 命令过多会导致客户端阻塞过久。
事务 VS 管道
特性 | 事务(Transaction) | 管道(Pipeline) |
---|---|---|
原子性 | 有部分原子性,顺序执行,不可插队 | 无原子性 |
并发控制 | 会阻塞其它命令插入(顺序执行) | 不阻塞其他命令 |
发送方式 | 多条命令逐条发送,最后 EXEC 执行 | 多条命令一次性发送 |
执行方式 | 统一入队后执行 | 服务端逐条执行后统一返回 |
错误处理 | 语法错误直接终止事务 | 失败命令不影响后续命令 |