• 【Redis】聊一下Redis事务以及watch机制


    我们知道熟悉MySQL的同学,一定了解ACID属性。ACID分别对应四种属性,但是Redis的事务和ACID属性有什么不一样的地方嘛,我们来深入探讨下。

    Redis事务和MySQL事务的区别

    ACID的本质是保证了事务执行前后对结果的保证,以及数据状态变化的保证。MySQL通过日志、MVCC、隔离级别、锁等机制实现ACID。
    但是Redis并不是传统意义上的事务级别,Redis的事务本质是可以一次执行多条命令、并且在这个事务中会序列化执行,按照顺序串行化执行而不会被其他命令插入,不许加塞。

    Redis事务原理

    具体命令
    在这里插入图片描述
    执行流程

    • 1.客户端会显示的使用MULTI声明事务开始,
    • 2.客户端发送对数据的操作,增删改查,然后Redis服务端接受之后会暂存到一个命令队列中,这个时候并不会执行。
    • 3.当客户端发送EXEC命令之后,服务端会从命令队列中按照顺序取出来,执行。

    正常执行

    127.0.0.1:6379> MULTI 
    OK
    127.0.0.1:6379(TX)> set key1 v1
    QUEUED
    127.0.0.1:6379(TX)> set key2 v2
    QUEUED
    127.0.0.1:6379(TX)> EXEC
    1) OK
    2) OK
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    原子性

    上面在正常的情况下,MUTI 和 EXEC 都会被正常执行可以保证原子性。
    1.在提交命令的时候,如果命令本身就是错误的
    显然执行之后,直接抛出错误,可以保证原子性

    127.0.0.1:6379> MULTI 
    OK
    127.0.0.1:6379(TX)> put het 1
    (error) ERR unknown command `put`, with args beginning with: `het`, `1`, 
    127.0.0.1:6379(TX)> set key3 v3
    QUEUED
    127.0.0.1:6379(TX)> EXEC
    (error) EXECABORT Transaction discarded because of previous errors.
    127.0.0.1:6379> 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    2.提交命令时,命令和数据类型不符合,在执行的时候异常
    在对key1 进行减1操作的时候执行出错,但是后续的命令却成功了,显然这没有保证原子性。属于一半执行成功,一半执行失败。
    在MySQL中,提供了回滚操作,但是在Redis中虽然提供了DISCARD 主动放弃事务,把命令队列清空,起不到数据回滚的作用。

    127.0.0.1:6379> MULTI
    OK
    127.0.0.1:6379(TX)> DECR key1
    QUEUED
    127.0.0.1:6379(TX)> set key6 v6
    QUEUED
    127.0.0.1:6379(TX)> EXEC
    1) (error) ERR value is not an integer or out of range
    2) OK
    127.0.0.1:6379> 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    3.在执行事务exec Redis实例发生了故障,导致事务执行失败
    如果Redis故障了,我们开启了AOF机制,那么可以通过AOF恢复实例宕机之前的数据,但是如果没有开启,无法保证原子性。

    • 命令入队就出错的话,会放弃整个事务,可以保证原子性。
    • 命令入队在执行的时候出错的话,不保证原子性
    • EXEC命令执行故障,开启AOF日志,可以保证原子性。

    一致性

    数据一致性其实就在执行前后,是否会保证数据状态的一致性,而上述原子性中,可以发现,出了对出现错误的命令不会执行,剩下情况其实是可以保证数据一致性的。

    隔离性

    事务的隔离性与事务并发修改数据有关系,而事务执行时机又可以分为命令入队(EXEC执行前),命令执行后(EXEC执行后)

    • 并发操作在EXEC执行前,需要使用WATCH机制进行保证,否则隔离性无法保证。
    • 并发操作在EXEC执行后,隔离性可以保证。

    第一种情况
    我们知道当命令在队列中时,是没有执行命令,这个时候如果有别的线程修改对应的队列中命令字段对应的数据值,就无法保证隔离性。但是使用WATCH机制可以保证,WATCH机制的原理是通过在命令入队之前,监控对应的键是否修改,如果修改,那么在EXEC执行时就会异常。
    在这里插入图片描述
    具体就是EXEC值执行发现WATCH监听的数据有修改,就是放弃执行。但是如果没有WTCH机制,exec队列中命令也会读取最新的值,但是这样其实没有办法保证隔离性。

    第二种方式,exec执行之后
    因为redis是单线程执行,所以会先保证把命令队列中所有命令执行完,所以这种方式也不会破坏事务的隔离性。
    在这里插入图片描述

    持久性

    持久性其实就依赖于Redis的AOF和RDB机制,而不同的持久化方式,也无法完全百分百保证数据一定会被持久化,RDB有一定的频率执行,而Redis虽然可以使用always模式,但是如果正好写入内存的数据没有刷到pageCache中,也没有办法进行数据持久化。

    总结

    本篇主要介绍了Redis的事务在ACID中不同的实现,综合分析,我们可以得出一个结论,Redis事务只保证了一致性和隔离性,但是无法保证持久性,并且Redis是一个缓存中间件,大多数的时候,业务上其实可以容许出现数据丢失的情况。
    在这里插入图片描述

  • 相关阅读:
    爱上开源之golang入门至实战第三章-性能分析-分析数据
    Python网络编程
    Linux嵌入式I2C协议笔记
    回溯法实现全排列(leetcode46)
    鸿蒙原生应用元服务-访问控制(权限)开发应用权限列表三
    韩顺平--多人在线通信系统
    在Ubuntu18.04系统下搭建redis 一主(服务器)多从
    2022联想创新科技大会--数字底座筑基行业智能
    用python写MapReduce函数——以WordCount为例
    linux设置IP地址与换源
  • 原文地址:https://blog.csdn.net/jia970426/article/details/130836549