Redis事务

1.Redis中事务 

前面在有一篇文章中讲到了MySQL中的事物,以及隔离等级等一系列有关于事物的内容,要是有兴趣可以去找找。这里主要讲Redis中的事物操作。
谈到事物,肯定就是提到事物的几个特性,在MySQL中事务有

  • 原子性:把事务的多个操作打包到了一起
  • 一致性:在事务执行前或后,保证了数据的可靠
  • 持久性:事务中做出的修改都会存硬盘
  • 隔离性:事务并发执行时的一些操作(涉及脏读,幻读等内容)

我们这里讲的Redis的事物,和MySQL比起来的话,差距肯定是非常非常大的。

Redis中事务最原本的含义是:将多个操作打包到一起进行执行。要么全部执行,要么全部不执行。请注意这里的事物仅仅只是执行,也就是说,我只是负责将事务打包到一起,但是具体的事物中的内容执行成功也好,失败也好,我只管全部执行就好了,要是有失败就失败吧。MySQL中的事物要是有失败存在的话,是会进行一个回滚操作的,而Redis中要是事物失败了,是没有回滚这样一个操作的。

redis事务最主要存在的意义就是防止其他客服端发送的请求,进行一个插队。

redis中实现事务,是引入了一个队列(每个客户端都有一个这样的队列) 就将要操作的内容保存在这个队列中就等于一个事物。
开始事务的时候,客户端输入的命令,就会发给服务器并进入这个队列中,而不是立即执行,而是当遇到了"执行事务"的命令的时候,此时就会把队列中的事物按照顺序依次执行。

1.1Redis中事务的使用场景

因为Redis的事物功能本来不算太强大,所以适用场景相对来说也较少。比较经典的一个适用场景就是购物的秒杀。

在我们平时在一些商场进行购物的时候,很多时候都会有商品是需要我们去抢的,当然不止我们,黄牛肯定也会去抢的。emmm理论上我们是可以写程序帮我们抢商品的,但是黄牛肯定也有程序啊,而且他的程序肯定打磨很多年了,比较靠谱.....扯远了  

 

在一般进行商品抢购的环节,比如一个商品发布了数量为count5000个商品 然后我们此时写程序就是

  • if(count >0){
  • 抢购成功;
  • count--;
  • };

理论的话应该是上述的逻辑吧,但是我们在实际编程的过程中肯定是使用多线程去进行操作,要是2个线程同时执行上述的操作,当商品最后还剩一个的时候,一个线程进行了判断发现商品数量是大于0的于是进了分支中,当还没来得及执行count--的时候,另外一个线程也进行了操作,发现商品也大于0也进入了分支中,于是乎最后count的数量就变成了-1,也就意味着本来只有5000件的商品,但是有5001人购买,并且还购买成功了。此时我们常规的解决方式就是,对上述代码进行一个加锁操作。

但如果我们使用Redis的事物的话 就可以很好的解决这个问题并且不用加锁

  • 开启事物
  • get count
  • if(count > 0){
  • decr count
  • }
  • 执行事物

Redis中开始了事物并不会立即执行,而且会进入一个队列中,(详细见块引用的文字),当客户端调用执行事物的命令后,此时Redis服务器就会对上述的一个购买操作进行一个打包执行,所以同时收到其他执行事物的命令时,每次获取的count就是前一次执行结束后的count

就不会出现count出现负数的情况了。说成大白话,就是将每一次的购买操作都打包成一个事物。

但是在redis中如何进行 if 判断呢 redis程序本身的话是不支持 if 这样的判定条件的。但是redis支持Lua脚本,可以进行lua脚本的编写来达到上述目的。

1.2 Redis中操作事物先关指令

  • 开启事物  MULTI
  • 执行事物 EXEC
  • 放弃当前事物 DISCARD

可以看到开启事物后,后面输入的命令,都是不会实际去进行执行的,而是会进入队列中,要是没有输入EXEC,是不会执行上述几条指令的,其他客户端也无法查询到相应的数据。 上述的命令DISCARD 输入后,会将等待队列中现有的命令进行丢弃。也就是会清空对应客户端队列中的命令

同时要是在执行事物的过程中,要是在还未进行EXEC操作前 服务器崩溃了,也就等同于DISCARD的效果,队列中的所有内容都会被清空

关于redis中事务还有一个命令 watch 因为在一个事物中可能涉及到对value值的一个修改

也就是比如我在8点创建了一个事务,其中有一条操作就是 set key 111但此时我并没有执行EXEC操作也就是这条操作被保存在了队列中等待执行。 此时另外一个客户端在8点30的时候,对key发起了修改 也就是执行了一条操作 set key 222 此时将key的值改为了222 但是9点的时候,那个线程突然执行EXEC方法了,按道理来说 因为set key 111这条任务是8点创建的 而 set key 222的操作是8点30执行的,按理来说是不会改变其中value的值的,但是在Redis中,此时key的值会被重新赋值回111.

所以watch的作用是,对某一个key进行一个监视的作用,看看一个key的value在MULTI和EXEC之间的时间内是否被其他线程修改了

要是未被修改返回结果本来应该是yes 但是被修改后 返回的结果是nil了 

nwctch 取消对一个key的监控

1.2.1 watch的实现原理

watch是通过类似于版本号这样的机制来实现了“乐观锁”,一旦对某一个key加上了watch进行监督以后,redis会对这个数添加一个版本号这样的设定,一旦数被修改,对应的版本号也会随之变大。在执行EXEC这个命令的时候,redis就会对被watch监视的数进行一次判断,判断这个版本号和最初的版本号是否是一致,要是不一致的话就等于 放弃EXEC的操作,所以要是修改后执行EXEC会返回一个nil,大白话来讲,就是对EXEC这个命令添加了一个限制条件,要是数被修改了就无法执行EXEC这个命令了 Java中CAS的ABA问题就可能会涉及 这个ABA问题我也给忘了,后面单独写一篇关于这个的文章。

相关推荐

  1. Redis 事务

    2024-03-18 10:08:02       34 阅读
  2. Redis 事务

    2024-03-18 10:08:02       23 阅读
  3. Redis事务

    2024-03-18 10:08:02       19 阅读
  4. Redis事务

    2024-03-18 10:08:02       14 阅读
  5. redis事务

    2024-03-18 10:08:02       11 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-03-18 10:08:02       18 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-03-18 10:08:02       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-03-18 10:08:02       18 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-03-18 10:08:02       20 阅读

热门阅读

  1. 处理Centos 7 中buff/cache高的问题

    2024-03-18 10:08:02       19 阅读
  2. CSP - 2022 普及组初赛试题及解析

    2024-03-18 10:08:02       24 阅读
  3. 关于static关键字

    2024-03-18 10:08:02       22 阅读
  4. C语言自学笔记8----C语言Switch语句

    2024-03-18 10:08:02       18 阅读
  5. C语言自学笔记11----C语言指针

    2024-03-18 10:08:02       16 阅读
  6. 单元测试、集成测试、系统测试区别

    2024-03-18 10:08:02       21 阅读
  7. 单词接龙~~

    2024-03-18 10:08:02       18 阅读
  8. 51单片机与ARM单片机的区别

    2024-03-18 10:08:02       19 阅读