2022/08/25 day10:Redis 事务

本文详细介绍了Redis的事务机制,包括事务的开启、执行和取消,以及事务中遇到错误的处理方式。此外,还探讨了在并发场景下如何使用锁来确保特定条件的事务执行,如分布式锁的实现和超卖问题的解决方案。
摘要由CSDN通过智能技术生成

目录

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-52s3egvf-1661511029228)(en-resource://database/5237:1)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZNWo2Plu-1661511029229)(en-resource://database/5239:1)]

事务简介

乱入的小朋友

收银员查数的过程被小朋友打乱了
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uRv2u1oq-1661511029229)(en-resource://database/5241:1)]

解决办法:让她在安静的环境下做就行了。

什么是事务
【问题】Redis执行过程中,多条连续执行的指令被干扰,打断,插队
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-arVtn6Wl-1661511029230)(en-resource://database/5243:1)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9zf1CzxT-1661511029230)(en-resource://database/5245:1)]
这个问题当然要解决,就依赖事务。

Redis事务就是一个命令执行的队列,将一系列预定义命令包装成一个整体(一个队列)。当执行时,一次性按照添加顺序依次执行,中间不会被打断或者干扰。

事务基本操作

事务的边界
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GKwdsDKy-1661511029230)(en-resource://database/5247:1)]

事务的基本操作

  • 开启事务:multi

  • 作用

    • 设定事务的开启位置,此指令执行后,后续的所有指令均加入到事务中
  • 执行事务:exec

  • 作用

    • 设定事务的结束位置,同时执行事务。与multi成对出现,成对使用。
  • 注意

    • 加入事务的命令暂时进入到队列中,并没有立即执行,只要执行exec命令才开始执行。

(已经常见的虚拟机文件是以.vmx结尾)
演示:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-i7C5QQIw-1661511029231)(en-resource://database/5249:1)]

  • 准备阶段
    • 查看进程
      • ps -ef | grep redis-
    • 杀死进程
      • kill -s 9 4155
    • 重启进程
      • redis-server conf/redis-6379.conf
    • 查看进程
      • ps -ef | grep redis-
  • 事务
    • 连接redis
      • redis-cli
    • [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CLdONbGw-1661511029231)(en-resource://database/5251:1)]

【疑问】事务定义过程中发现出了问题,怎么办?

  • 取消事务:discard
  • 作用
    • 终止当前事务的定义,发生在multi之后,exec之前
  • 演示
    • [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Pejy5nbJ-1661511029231)(en-resource://database/5253:1)]

事务的工作流程

set–>multi–>set–>exec–>discard
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tnic5yV2-1661511029232)(en-resource://database/5255:1)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FH6PITRO-1661511029232)(en-resource://database/5257:1)]

事务的注意事项

  1. 【疑问】定义事务的过程中,命令格式输入错误怎么办?
  • 语法错误

    • 指命令书写格式错误
  • 处理错误

    • 如果定义的事务中所包含的命令存在语法错误,整体事务中所有命令均不会执行。包括那些语法正确的命令。
  • 演示

    • 清楚redis客户端中所有数据
      • flushdb
    • 来查看一下
      • keys * 现在什么都没有了
    • 事务中有命令错误一次,事务就不存在了,让你再重新开一个事务(命令中有命令存在语法错误,那么本次事务中所有命令都不得执行)
      • [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JNxx2AB4-1661511029232)(en-resource://database/5259:1)]
  1. 【疑问】定义事务的过程中,命令执行出现错误怎么办?
  • 运行错误
    • 指命令格式正确,但是无法正确执行。例如对list进行incr操作
    • 语法上没问题,是否是逻辑错误?
  • 处理结果
    • 能够正确运行的命令会执行,运行错误的命令不会执行。也就是正确的命令执行,错误的不执行。
  • 演示
    • 重新开一个事务
      • multi
    • 事务中,语法都不错,逻辑正确的执行,逻辑错误的不执行
      • [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lKwGQaRg-1661511029233)(en-resource://database/5261:1)]
  • 注意
    • 已经执行完毕的命令对应的数据不会自动回滚,需要程序员自己在代码中实现回滚。
      • 其他数据库中的回滚:事务中只要存在错误,就会回滚命令到开启事务之前,所谓是“一‘招’回到解放前”。
    • 这个问题是本应该避免掉的:你不可能这个程序不测试就上线跑。但如果出现,应该怎么解决呢?【手动代码回滚–鸡肋】
      • [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gN9KKae0-1661511029233)(en-resource://database/5265:1)]

基于特定条件的事务执行——锁

业务场景

天猫双十一,热卖过程中,对已经售罄的货物追加补货,4个业务员都有权限进行补货。补货的操作可能是一系列的操作,牵扯到多个连续操作,如何保障不会重复操作?

  • 问题来了:他们四个人能不能同时补货?不行,只能一个人补;
    • 如果小张补完货了,小凯再补的时候,发现补好了,他就不用操作了。
    • 那么怎么实现这个操作呢?–业务分析

业务分析

  • 多个客户端有可能同时操作同一组数据,并且该数据一旦被操作修改后,将不适用于继续操作
  • 在操作之前要操作的数据,一旦发生变化,终止当前的操作
  • 解决办法:就是客户端对数据进行监控。如果key发生了变化,我就执行,没变化就不执行。

解决方案

  • 对key添加监视锁,在执行exec前如果key发生了变化,终止事务的执行

    • watch key1 [key2…]
  • 取消对所有key的监视

    • unwatch
  • 演示

    • 为了我们实验效果不被影响,我们所有数据全都清掉
      • flushdb
    • 来查看一下
      • keys * 现在什么都没有了
    • 设置两个值,用来监控
      • set name 123
      • set age 321
    • 监控一个
      • watch name
      • 监控的东西一旦发生改变,下面定义的事务就不会再执行了
        • [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LrXcJV5L-1661511029233)(en-resource://database/5271:1)]
      • 解释那四个业务员:一旦有人把货物改变了,那么此业务员的补货就不会再执行了(监控完了后,第一个人把它改变了,后面的人改变就不会执行了)
    • 注意:
      • 不能在事务里面watch(告诉你不行,会出现错误)
  • 取消事务,放弃执行事务块内的所有命令

    • discard
  • 监控name

    • watch name
    • get name
    • unwatch 取消所有的锁
    • 另一边改变name
    • exec 就可以执行了

tips 18:
redis应用基于状态控制的批量任务执行

基于特定条件的事务执行1

业务场景

天猫双11热卖过程中,对已经售罄的货物追加补货,且补货完成。客户购买热情高涨,3秒内将所有的商品购买完毕。本次补货已经将库存全部清空,如何避免最后一件商品不被多人购买?【超卖问题】

业务分析

  • 使用watch监控一个key有没有改变已经不能解决问题,此处要监控的是具体数据
  • 虽然redis是单线程的,但是多个客户端对同一数据同时进行操作时,如何避免不被同时修改?

解决方案

  • 使用setnx设置一个公共锁(公共厕所)
    • setnx lock-key valye
      利用setnx命令的返回值特征,有值则返回设置失败,无值则返回设置成功
    • 对于返回设置成功的,拥有控制权,进行下一步的具体业务操作‘’
    • 对于返回设置失败的,不具有控制权,排队或等待
      操作完毕通过del操作释放锁

注意:上述解决方案是一种设计概念,依赖规范保障,具有风险性。

  • 演示
    • 清空所有数据
      • flushdb
    • 查看数据
      • keys *
    • key一旦被锁上,就可以操作,则其他客户端redis不能操作。
      • [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2NJ1pbzv-1661511029233)(en-resource://database/5273:1)]

tips 19:
redis应用基于分布式锁对应的场景控制

基于特定条件的事务执行2

业务场景

依赖分布式锁的机制,某个用户操作时对应客户端宕机,且此时已经获取到锁。如何解决?(宕机前加锁,宕机后锁还在,此时求排队的人心理阴影)所以得给锁加个时效,也就是说你这个锁只能在时效内有效。那么你在厕所里睡觉,它的门还能自己给开了(不会?砸锁行不,不管你尴尬否))

业务分析

  • 由于锁操作由用户控制加锁解锁,必定会存在加锁后未解锁的风险
  • 需要解锁操作不能仅依赖用户控制,系统级别要给出对应的保底处理方案

解决方案

  • 使用expire 为锁key添加时间限定,到时不释放,则放弃锁(锁时效)(其实就是商场内的寄存空间/杜绝占着茅坑不拉屎的行为)

    • expire lock-key second 秒
    • pexpire lock-key milliseconds
      由于操作通常都是微秒级或毫秒级,因此该锁定时间不宜设置过大。具体时间需要业务测试后确认
    • 例如:持有锁的操作最长执行时间127ms,最短执行时间7ms
    • 测试百万次最长执行时间对应命令的最大耗时,测试百万次网络延迟平均耗时
    • 锁时间设定推荐:最大耗时* 120% + 平均网络延迟 * 110%
    • 如果业务最大耗时<<网络平均延迟,通常为2个数量级,取其中单个耗时较长即可
  • 演示

    • 清空所有数据
      • flushdb
    • 查看数据
      • keys *
    • 要求你在锁的时候,马上加上时限
      • set name 123
      • setnx lock-name 1
      • expire lock-name 20 20秒

总结

在这里插入图片描述

                                                                                 ——此文档为学习笔记!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值