Redis:对比一下Redis和MySQL的事务

QAQ。。水稻前两天研究完MySQL的事务,今天看到了Redis,也产生了兴趣。准备下手看看

菜瓜:哥,你在看啥呢,这么专注

水稻:在看Redis的事务,有点收获

菜瓜:真的吗?科普一下呗!

水稻:嗯,从与MySQL的不同点开始说,Redis的事务不支持事务的原子性,事务内的一组操作并不支持异常回滚。这里分为两种情况

  • 语法异常:类比java编译时异常,事务中出现语法错误,譬如set误写成sett等。在提交的时候就能检查出来,整个事务都不会执行
  • 业务异常:类比java的运行时异常,譬如将list的命令操作在string上。命令提交的时候检测不出来,可以正常提交,错误的命令不能执行,其他的命令正常执行,不会回滚

菜瓜:Redis为什么这么豪横

水稻:搜索官方文档可以发现

  • 根本原因可能还是Redis的定位是缓存。不加入回滚逻辑可以使它简洁,快速
  • 官方解释是:运行时的异常不应该发生在生产环境,就是Redis不应为程序员的bug买单
  • Redis可以以脚本的形式支持事务的执行。历史原因,先出现了事务,后出现的脚本。暂时不打算撤销事务的功能,它提供了无脚本也能支持简单事务的功能,但是如果随着后续脚本方案的流行可能会在后续版本移除事务功能

菜瓜:厉害了。我还听说过Discard和Watch命令?能说说吗

水稻:

  • Discard支持在事务内部主动撤销事务,该命令会清空事务队列。
  • Watch命令则是提供一种CAS乐观锁的机制,可以变相的支持事务的隔离性,可以事先监听关注的key,其他事务如果在当前事务执行前修改了监听的key,那么当前事务就会被取消。程序要做的就是监听到失败的结果,然后进行重试。
    • 举个栗子
    • 第一个客户端 开启事务multi get k1 ,set k2 aaa 
    • 第二个客户端 开启事务multi del k1 , exec  
    • 第一个客户端 提交事务exec , 会发现k2是可以set成功的
    • 如果在第一个客户端开启事务之前监听k1的变化,那么k2是会set失败的

菜瓜:懂了!!懂了 

    

总结:

  1. Redis事务不支持回滚操作,语法错误直接取消入队的所有命令。运行时错误不会执行错误后的操作。
  2. 要想做事务操作可以使用watch机制监听key失效事件,自己做cas操作。或者使用脚本执行完整事务

你可能感兴趣的:(Redis:对比一下Redis和MySQL的事务)