31 | 事务机制:Redis能实现ACID属性吗?

122 阅读3分钟

事务 ACID 属性的要求

  • 事务执行时,会有专门属性的保证:原子性,一致性,隔离性和持久性

    • 原子性:事务中的多个操作要么都完成,要么都不执行
    • 一致性:数据库数据在事务执行前后是一致的
    • 隔离性:其他事务无法存取到正在执行的事务(读数据上锁,保证串行执行)
    • 持久性:将事务执行数据持久化,保证重启后可恢复
  • redis怎么实现事务(MULTI、EXEC 两个命令)

    • 使用MULTI开启事务
    • 执行具体指令,这些指令会缓存到一个命令队列中,不会立即执行
    • 使用EXEC 命令提交事务,执行队列中的操作

原子性

  • 正常情况:如果事务正常执行,不会发生错误

  • 异常情况

    • 1.在执行 EXEC 命令前,操作命令有错误(语法错误)

      • 后续的redis指令仍然可以继续提交

      • 执行了 EXEC 命令后,redis会拒绝\

      • 可以保证原子性

    • 2.命令和操作的数据类型不匹配,但 Redis 实例没有检查出错误

      • 会忽略错误命令,并正确的命令执行完\

      • 不提供回滚机制

      • 不能保证原子性,DISCARD可以清空队列命令,主动放弃本次事务

    • 3.redis实例发生故障,导致事务执行失败

      • AOF是指令文件

      • 开启AOF的情况下:只会有部分的事务操作被记录到 AOF 日志中,可以通过redis-check-aof 工具将未完成事务从AOF文件中去除,可以保证原子性\

      • 未开启AOF日志,无法保证原子性

  • 小结

    • 命令入队时就报错,会放弃事务执行,保证原子性
    • 命令入队时没报错,实际执行时报错,不保证原子性
    • EXEC 命令执行时实例故障,如果开启了 AOF 日志,可以保证原子性**
      **

一致性

  • 异常情况:错误命令、实例故障

  • 异常情况

    • 1.命令入队时报错,放弃执行,可以保证一致性

    • 2.命令入队时没有报错,实际执行时报错。错误命令不执行,正确命令执行,保证数据库一致性

    • 3.EXEC命令执行实例发生故障

      • 没有开启 RDB 或 AOF数据丢失,保证一致性\

      • 使用RDB  事务还未执行,所有数据丢失,保证一致性

      • 使用AOF  如果记录了部分事务操作,可以通过redis-check-aof 清除事务中已经完成的操作,可以保证数据一致性

隔离性

  • 不同情况下

    • 并发操作在 EXEC 命令前执行:使用 WATCH 机制保证隔离性\

    • 并发操作在 EXEC 命令后执行:可以保证隔离性 redis使用单线程处理指令,是串行的\

  • Watch

    • 作用:监控一个或多个键的值变化,当事务调用EXEC命令执行时,WATCH 机制会先检查监控的键是否被其它客户端修改了

使用watch的情况

不使用watch的情况

串行执行保证了隔离性

\

持久性

  • 完全取决于Redis持久化配置

    • 不开启AOF和RDB,事务持久化得不到保证
    • RDB不能保证
    • AOF在三种模式也不能保证
  • 结论,redis无法保证数据的持久性,会丢失

总结

  • 学习MULTI,EXEC,DISCRD和Watch指令
  • 事务只针对所有的写操作,不支持读操作
  • redis事务可以保证一致性和隔离性,但是无法保证持久性
  • 原子性需要看实际场景