给个网站好人有好报2021,中国建设银行信用卡,建筑网入口,深圳方维网络目录 0.什么是事务#xff1f;1.Redis 事务本质2.Redis 事务意义3.事务操作1.MULTI2.EXEC3.DISCARD4.WATCH5.UNWATCH 0.什么是事务#xff1f;
Redis的事务和MySQL的事务概念上是类似的#xff0c;都是把一系列操作绑定成一组#xff0c;让这一组能够批量执行Redis事务和M… 目录 0.什么是事务1.Redis 事务本质2.Redis 事务意义3.事务操作1.MULTI2.EXEC3.DISCARD4.WATCH5.UNWATCH 0.什么是事务
Redis的事务和MySQL的事务概念上是类似的都是把一系列操作绑定成一组让这一组能够批量执行Redis事务和MySQL的区别 弱化的原子性Redis没有”回滚机制”只能做到这些操作”批量执行”不能做到”一个失败就恢复到初始状态” 如果事务中若干个操作存在有失败的那就失败吧不会有回滚操作 不保证一致性不涉及”约束”也没有回滚事务执行过程中如果某个修改操作出现失败就可能引起不一致的情况 MySQL的一致性体现的是运行事务前后运行后结果都是合理有效的不会出现中间非法状态 不需要隔离性也没有隔离级别因为不会并发执行事务(Redis单线程处理请求)不需要持久型是保存在内存的是否开启持久化是redis-server自己的事情和事务无关 Redis如果按照集群模式部署就不支持事务 1.Redis 事务本质
Redis事务**本质**上是在服务器上搞了一个”事务队列”每次客户端在事务中进行一个操作都会把命令先发给服务器放到”事务队列”中(但是不会立即执行)而是会在真正收到EXEC命令之后才真正执行队列中的所有操作 因此Redis事务的功能相比于MySQL来说是弱化很多的只能保证事务中的这几个操作是”连续的”不会被别的客户端”加塞”仅此而已 综上 Redis事务的意义就是为了打包避免其他客户端的命令插队到中间此处的不被插队不是先抢占位置而是先让出位置 2.Redis 事务意义
Redis的事务为啥就搞的这么简单为啥不设计成和MySQL一样强大呢 MySQL的事务在背后付出了很大的代价 空间上要花费更多的空间来存储更多的数据时间上也要有更大的开销 正是因为MySQL有上述的问题才有了Redis的用武之地 什么时候需要使用到Redis事务呢 需要把多个操作打包进行使用Redis事务比较合适 示例商品抢购 典型写法如果不加上任何限制就可能会出现线程安全问题 在多线程中通过加锁的方式来避免插队 if(count 0)
{// 下单成功count--
}在Redis中直接使用事务即可# 开启事务
get count
if count 0decr count
# 执行事务
# Redis服务器收到执行事务操作的时候才会真正执行说明 Redis原生命令中不支持条件判定但是Redis支持lua脚本可以通过lua实现可以认为lua脚本的实现方式是Redis事务的进阶版本 3.事务操作
1.MULTI
功能开启一个事务执行成功返回OK当开启事务并且向服务器发送若干个命令之后此时服务器重启此时的这个事务怎么办 此时的效果相当于DISCARD 2.EXEC
功能真正执行事务 每次添加一个操作都会提示”QUEUED”说明命令已经进入服务端的队列了真正执行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) OK127.0.0.1:6379 get k1
1
127.0.0.1:6379 get k2
2
127.0.0.1:6379 get k3
33.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
OK127.0.0.1:6379 get k1
(nil)
127.0.0.1:6379 get k2
(nil)4.WATCH
情景在执行事务的时候如果某个事务中修改的值被别的客户端修改了此时就容易出现数据不一致的问题此时key的值是多少呢 从输入命令的时候看是客户端1先执行的set key 100客户端2后执行的set key 200但是从实际的执行时间看是客户端2先执行的客户端1后执行的# 客⼾端 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# 结果查询
127.0.0.1:6379 get key
100这个时候其实很容易引起歧义因此即使不保证严格的隔离性至少也要告诉用户当前的操作可能存在风险 watch命令就是用来解决这个问题的watch在该客户端上监控一组具体的key 当开启事务的时候如果对watch的key进行修改就会记录当前key的”版本号”在真正提交事务的时候如果发现当前服务器上的key的版本号已经超过了事务开始时的版本号就会让事务执行失败 watch本质上是给exec加了个判定条件属于乐观锁示例# 客户端1先执行
127.0.0.1:6379 watch k1
OK
127.0.0.1:6379 MULTI
OK
127.0.0.1:6379 set k1 100
QUEUED
127.0.0.1:6379 set k2 1000
QUEUED
# 只是入队列但是不提交事务执行# 客户端2后执行
127.0.0.1:6379 set k1 200
OK# 客户端1再执行
127.0.0.1:6379 EXEC
(nil)
127.0.0.1:6379 get k1
200
127.0.0.1:6379 get k2
(nil)
# 此时说明事务已经被取消了这次提交的所有命令都没有执行5.UNWATCH
功能取消对key的监控相当于WATCH的逆操作