Redis教程

Redis学习笔记——Redis事务__锁机制

本文主要是介绍Redis学习笔记——Redis事务__锁机制,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

七、Redis事务__锁机制

1、Redis事务的定义

  • Redis事务是一个单独的隔离操作:事务中的所有命令都会序列化、按顺序地执行。事务在执行的过程中,不会被其他客户端发送来的命令请求所打断。
  • Redis事务的主要作用就是串联多个命令防止别的命令插队。

2、Multi、Exec、discard

  • 从输入Multi命令开始,输入的命令都会依次进入命令队列中,但不会执行,直到输入Exec后,Redis会将之前的命令队列中的命令依次执行。
  • 组队的过程中可以通过discard来放弃组队。
  • image-20210806192831323
  • 案例
    • image-20210806193141286
    • 组队成功,提交成功
    • image-20210806193242240
    • 组队阶段报错,提交失败
    • image-20210806193252937
    • 组队成功,提交有成功有失败情况

3、事务的错误处理

  • 组队中某个命令出现了报告错误,执行时整个的所有队列都会被取消。
  • image-20210806193433349
  • 如果执行阶段某个命令报出了错误,则只有报错的命令不会被执行,而其他的命令都会执行,不会回滚。
  • image-20210806193457609

4、事务冲突的问题

  • 例子

    • 一个请求想给金额减8000
    • 一个请求想给金额减5000
    • 一个请求想给金额减1000
    • image-20210806193633571
  • 悲观锁

    • image-20210806193711049
    • 悲观锁(Pessimistic Lock), 顾名思义,就是很悲观,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会block直到它拿到锁。传统的关系型数据库里边就用到了很多这种锁机制,比如行锁表锁等,读锁写锁等,都是在做操作之前先上锁。
  • 乐观锁

    • image-20210806193742540
    • 乐观锁(Optimistic Lock), 顾名思义,就是很乐观,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,可以使用版本号等机制。乐观锁适用于多读的应用类型,这样可以提高吞吐量。Redis就是利用这种check-and-set机制实现事务的。
  • WATCH key [key …]

    • 在执行multi之前,先执行watch key1 [key2],可以监视一个(或多个) key ,如果在事务执行之前这个(或这些) key被其他命令所改动,那么事务将被打断。
    • image-20210806194057653
  • unwatch

    • 取消 WATCH 命令对所有 key 的监视。
    • 如果在执行 WATCH 命令之后,EXEC 命令或DISCARD 命令先被执行了的话,那么就不需要再执行UNWATCH 了。

5、事务的三大特性

  • 单独的隔离操作
    • 事务中的所有命令都会序列化、按顺序地执行。事务在执行的过程中,不会被其他客户端发送来的命令请求所打断。
  • 没有隔离级别的概念
    • 队列中的命令没有提交之前都不会实际被执行,因为事务提交前任何指令都不会被实际执行
  • 不保证原子性
    • 事务中如果有一条命令执行失败,其后的命令仍然会被执行,没有回滚

6、Redis分布式锁

  • 先拿setnx来争抢锁,抢到之后,再用expire给锁加一个过期时间防止锁忘记了释放。
  • 如果在setnx之后执行expire之前进程意外crash或者要重启维护了
    • 设置过期时间和占位必须是原子的。redis支持使用setnx ex 命令
  • 如果由于业务时间很长,锁自己过期了,我们 直接删除,有可能把别人正在持有的锁删除了。
    • 占锁的时候,值指定为uuid,每个人匹配是自己 的锁才删除。
  • 如果正好判断是当前值,正要删除锁的时候,锁已经过期, 别人已经设置到了新的值。那么我们删除的是别人的锁
    • 删除锁必须保证原子性。使用redis+Lua脚本完成
  • 如果业务时间比锁的时间长
    • edisson 锁的自动续期,如果宕机没有自动续期30s就解锁,也可指定时间解锁但不会自动续期,所以自动解锁时间一定要大于业务时间,差别在于底层的tryAcquire,
    • 如果指定了超时时间,就会发送lua脚本给redis执行,进行占锁过期时间是我们指定的时候。
    • 如果为指定超时时间,就使用看门狗的默认时间30s,只要占锁成功就会启动一个定时任务(重新给锁设置过期时间,新的过期时间是看门狗的默认时间),每隔看门狗的1/3时间就会重新设置
这篇关于Redis学习笔记——Redis事务__锁机制的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!