redis事务

发布时间:2024年01月18日

1.什么是事务

Redis的事务和MySQL的事务概念上是类似的.都是把一系列操作绑定成一组. 让这一组能够批量执行.
但是注意体会Redis的事务和MySQL事务的区别:
●弱化的原子性: redis没有"回滚机制".只能做到这些操作"批量执行".不能做到"一-个失败就恢复到
初始状态".
●不保证一致性:不涉及"约束".也没有回滚. MySQL的- -致性体现的是运行事务前和运行后,结果都,
是合理有效的,不会出现中间非法状态.
●不需要隔离性:也没有隔离级别,因为不会并发执行事务(redis单线程处理请求) .
●不需要持久性:是保存在内存的.是否开启持久化,是redis-server自己的事情,和事务无关.

Redis事务本质上是在服务器上搞了一个"事务队列".每次客户端在事务中进行一个个操作,都会把命令先发给服务器,放到"事务队列"中(但是并不会立即执行)
而是会在真正收到EXEC命令之后,才真正执行队列中的所有操作.
因此, Redis的事务的功能相比于MySQL来说,是弱化很多的.只能保证事务中的这几个操作是"连续
的",不会被别的客户端"加塞",仅此而已.

2.事务操作

MULTI
开启一个事务.执行成功返回OK.
实例

127.0.0.1:6379> MULTI
OK

EXEC
真正执行事务.
实例

127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> set k1 1
QUEUED
127.0.0.1:6379> set k2 2
QUEUED
127.0.0.1:6379> set k3 3
QUEUED
127.0.0.1:6379> EXEC
1) OK
2) OK
3) OK

每次添加一个操作,都会提示"QUEUED",说明命令已经进入客户端的队列了.
真正执行EXEC的时候,客户端才会真正把上述操作发送给服务器.
此时就可以获取到上述key的值了.

127.0.0.1:6379> get k1
"1"
127.0.0.1:6379> get k2
"2"
127.0.0.1:6379> get k3
"3"

DISCARD
放弃当前事务.此时直接清空事务队列,之前的操作都不会真正执行到.
实例

127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> set k1 1
QUEUED
127.0.0.1:6379> set k2 2
QUEUED
127.0.0.1:6379> DISCARD
OK
127.0.0.1:6379> get k1
(nil)
127.0.0.1:6379> get k2
(nil)

WATCH
在执行事务的时候,如果某个事务中修改的值,被别的客户端修改了,此时就容易出现数据不一致的问题.
实例

# 客?端1 先执?
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> set key 100
QUEUED
# 客?端2 再执?
127.0.0.1:6379> set key 200
OK
# 客?端1 最后执?
127.0.0.1:6379> EXEC
1) OK

此时,key的值是多少呢??
从输入命令的时间看,是客户端1先执行的set key 100.客户端2后执行的set key 200.
但是从实际的执行时间看,是客户端2先执行的,客户端1后执行的.

127.0.0.1:6379> get key
"100"

这个时候,其实就容易引起歧义.
因此,即使不保证严格的隔离性,至少也要告诉用户,当前的操作可能存在风险.
watch命令就是用来解决这个问题的. watch在该客户端上监控一组具体的 key.
●当开启事务的时候,如果对watch的key进行修改,就会记录当前key的"版本号". (版本号是个简单
的整数,每次修改都会使版本变大.服务器来维护每个key的版本号情况)
●在真正提交事务的时候,如果发现当前服务器上的key的版本号已经超过了事务开始时的版本号,就会让事务执行失败. (事务中的所有操作都不执行).

实例.
客户端1先执行

127.0.0.1:6379> watch k1 # 开始监控 k1
OK
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> set k1 100 # 进?修改, 从服务器获取 k1 的版本号是 0. 记录 k1 的版
QUEUED
127.0.0.1:6379> set k2 1000
QUEUED

只是入队列,但是不提交事务执行.

客户端2再执行

127.0.0.1:6379> set k1 200 # 修改成功, 使服务器端的 k1 的版本号 0 -> 1
OK

客户端1再执行

127.0.0.1:6379> EXEC # 真正执?修改操作, 此时对?版本发现, 客?端的 k1 的版本
(nil)
127.0.0.1:6379> get k1
"200"
127.0.0.1:6379> get k2
(nil)

此时说明事务已经被取消了.这次提交的所有命令都没有执行.

UNWATCH
取消对key的监控.
相当于WATCH的逆操作.此处不做演示.

文章来源:https://blog.csdn.net/qq_65307907/article/details/134702347
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。