redis那点事2: 事务篇

116 阅读3分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

我们先来回顾一下redis的优势:

    速度快!    数据类型丰富!    支持事务!    特性丰富!

    那我们就就来聊一聊redis的事务, 首先我们先聊一下概念性的问题, 再进行测试!

redis的事务是什么?

     事务是一个单独的隔离操作, 开启事务后所有的命令都会序列化, 按顺序的执行, 在事务执行过程中

     不会被其他客户端发送来的命令打断, 这保证了命令是作为一个独立的单位执行的, redis的事务是原子操作

redis事务涉及到的命令:

    MULTI        开启事务

    EXEC         执行事务

    DISCARD  取消执行事务

    WATCH      对某个key加锁 如果这个key被其他客户端修改了 则导致事务失败

    UNWATCH 释放锁

redis锁的工作流程:

     在修改某个变量前可以对变量进行加锁, 如果其他客户端修改了该变量, 会导致本客户端修改失败

redis的锁和传统锁有什么区别?

     加锁的客户端允许其他客户端修改, 但是本客户端会报错

测试1: 测试事务的执行

    首先我们先查询一下所有的key:   ​, 现在redis是没有数据的

    执行事务  ​, 可以看到都是ok, 再来看一下所有的key: ​, 

    再开启一个事务, 进行set和incr操作, ​, 这里因为incr了一个 string的数据,

    所以会报错,  再来看一下所有的key,  ​, 从这里可以看出 d还是被set了

    得出结论: 如果操作在加入到事务队列时没有问题的, 那么事务是会执行的, 事务不能保证原子性

 测试2: 测试事务的执行

    执行事务 ​, 这里keys下, 查看事务是否插入成功

    ​,  可以看出, 事务是没有执行的

    得出结论: 如果事务相关的命令中, 中间有语法错误, 则事务最终不会得到执行

 测试3: 测试事务的取消

     执行事务 ​, 这里keys一下, ​, 可以看出事务被取消了, 

     再执行事务 ​, 可以看出命令错误, 但是取消还是执行了, 

    这里再keys一下, ​, 发现还是没有数据

    得出结论: 事务的DISCARD返回肯定是OK, 绝对执行成功, 不会失败

测试4: 测试加锁不开启事务 其他客户端修改

    先set一个值, 然后对这个key加锁 ​, 这里看到修改成功了, 这时其他客户端修改, 

    ​, 可以看到修改成功了, 这时本机修改看看是否报错, 

    ​, 没有报错并且执行成功

    得出结论: 单独的使用 watch 命令是没有作用的

测试5: 测试事务加锁 其他客户端不修改

    对a加锁, 开启事务修改a, ​, 可以看出 非常的正常, 就算没有 watch 和预期结果也是一样的

    得到结论: 事务可以不用依赖watch

测试6: 测试事务加锁 其他客户端修改

    对a加锁, 开启事务修改a但不执行, ​, 其他客户端修改a, ​,

    可以看到a被修改了, 这时执行事务 ​, 发现返回nil

    这里查看一下a的值, ​, 可以看出事务未执行

    得出结论: 对一个key加锁, 如果其他客户端修改了, 那么事务不会执行

测试7: 测试事务加锁 事务中释放锁 其他客户端修改

    对a加锁, 开启事务在第一行释放锁并且修改a但不执行, ​, 其他客户端修改a   

    ​,  可以看到a已经被修改, 执行事务 ​,

    get 下 a ​, 可以看出值未修改

    得出结论: 在事务中释放锁是不成立的

测试8: 测试事务不加锁 其他客户端修改

    开启事务修改a但不执行, ​, 其他客户端修改a, ​,

    可以看出修改成功, 执行事务, ​ , 可以看出还是修改成功了

    得出结论: 事务不依赖锁, 但是锁依赖事务, 不加锁其他客户端修改数据事务还是会执行的

总结:

    1. redis的事务不拥有原子性! ACID是关系型数据库特有的

    2. 如果事务中命令有误, 事务最终是不会执行的

    3. 事务不一定加锁

    4. 如果加了锁, 其他客户端修改数据, 事务一定不会执行

    5. 在事务中释放锁是不成立的

    6. discard命令一定会执行成功

结束

  这就是我对redis事务篇的总结   感觉有用就点个赞吧 如果有错误或更好的方法评论区请多多指出  相互学习共同进步