自学内容网 自学内容网

redis:事务

在这里插入图片描述

个人主页 : 个人主页
个人专栏 : 《数据结构》 《C语言》《C++》《Linux》《网络》 《redis学习笔记》


事务

redis的事务和mysql的事务概念上是类似的,都是把一系列操作绑定成一组,让这一组能够批量执行;但redis的事务远远不如mysql的事务

  • 弱化的原子性:redis没有回滚机制,只能做到这些操作批量执行,不能做到一个失败就恢复到初始状态
  • 不具备一致性:redis没有约束,也没有回滚机制,事务执行过程中如果某个修改操作出现失败,就可能引起不一致的情况
  • 不具备持久性:redis本身就是内存数据库,数据是存储在内存中的,虽然redis也有持久化机制,但这里的持久化机制和事务没有直接关系
  • 不涉及隔离性:redis是一个单线程模型的服务器程序,所有的请求/事务,都是串行执行的

redis的事务为啥就这么简单,为什么不设计成mysql一样强大?mysql的事务,在背后付出了很大的代价,空间上,要花费更多的空间来存储更多的数据;时间上,要更多的执行开销。


redis的事务,主要意义是为了"打包",避免其它客户端的命令,插队插到中间。
redis中实现事务,是引入了队列(每个客户端都有一个),开启事务的时候,此时客户端输入的命令就会发给服务器并且进入这个队列中(不是立即执行),当遇到"执行事务"命令的时候,此时就会把队列中的这些任务按照顺序依次执行,redis主线程会把事务中的操作都执行完,再处理别的客户端


啥时候需要使用redis的事务?
如果我们需要把多个操作打包进行,使用事务是比较合适的。比如,为了保证买票时,不会多卖出几张票,就可以使用事务。
在这里插入图片描述
当用户B将要执行事务,然而用户A已经在执行事务,用户B就会等待,等到用户A执行事务命令结束;此时用户B执行事务时,获取的count已经是用户A自减之后的结果。

上图的条件判断可以通过lua脚本实现,redis支持lua脚本。

事务操作

  • MULTI:开启一个事物,执行成功返回OK
  • EXEC:真正执行事务
  • DISCARD:放弃当前事务,此时直接情况事务队列,之前的操作都不会真正执行到
  • WATCH:监控某个key是否在事务执行之前,发送改变

在这里插入图片描述
每添加一个操作,都会提示"QUEUED",说明命令已经进入客户端的队列了,此时在另一个客户端查询这几个key,是没有结果的
在这里插入图片描述
真正执行exec的时候,客户端才会真正把上述操作发送给服务器,此时就可以获取到上述key的值了


注意:
当开启事务,并给服务器发送若干个命令后,此时服务器重启,此时这个事务怎么样?这个效果约等于discard
在这里插入图片描述
在这里插入图片描述


在执行事务时,如果某个事务中修改的值,被其它的客户端修改了,此时容易出现数据不一致问题;
在这里插入图片描述
客户端1先执行multi,set key 222,客户端2再执行 set key 333命令,客户端1再执行exec,最后get key 的结果为 222。

在这个场景中,可以使用WATCH命令来监控这个key,看看这个key在事务的multi和exec之间,是否在外部被其它客户端修改了。此时,exxec在执行上述事务中的命令的时候,发现 key 在外部有修改,于是真正执行set key 时,就没有真正执行
在这里插入图片描述

watch必须搭配事务使用,并且必须在mutli之前使用


WATCH就相当于是基于 版本号 这样的机制,来实现"乐观锁"

  • 当开启事务时,如果对watch的key进行修改,就会记录当前key的版本号(版本号是一个简单的整数,每次修改都会使版本号变大,服务器来维护每个key的版本号情况)
  • 在真正提交事务的时候,如果发现当前服务器上的key的版本号已经超过了事务开始时的版本号,就会让事务执行失败

在这里插入图片描述

exec判断版本号一致,说明当前key在事务开启最终执行这个过程,没有别的客户端修改,真正执行命令;如果版本号不一致,说明key在其它客户端改过了,因此此处就直接丢弃事务中的操作,exec返回nil


总结

以上就是我的redis学习笔记

在这里插入图片描述


原文地址:https://blog.csdn.net/li209779/article/details/143751887

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!