当前位置:网站首页>redis6事务和锁机制

redis6事务和锁机制

2022-07-05 13:28:00 知道什么是码怪吗?

目录

事务

基本操作

错误机制

悲观锁

乐观锁

Redis事务三特性

秒杀案例

超卖问题

连接超时问题

库存遗留问题


事务

        Redis事务是一个单独的隔离操作:事务中的所有命令都会序列化、按顺序地执行。事务在执行的过程中,不会被其他客户端发送来的命令请求所打断。

        Redis事务的主要作用就是串联多个命令防止别的命令插队。

基本操作

        multi指令进行组队,接下来输入的指令都会依次进入命令队列中,但不会执行,直到输入exec后,Redis会将之前的命令队列中的命令依次执行。

如下所示:

 

 如果想放弃组队,只需要输入discard即可。

错误机制

组队时出现错误,执行时所有的任务都会被取消。

如下所示:

执行时出现错误,只有报错的命令不会被执行,其他命令都会执行,不会回滚。 

如下所示:

悲观锁

        每次拿数据时都会进行上锁,这样其他人拿数据时就会阻塞直到解锁。传统的关系型数据库里边就用到了很多这种锁机制,比如行锁,表锁等,读锁,写锁等,都是在做操作之前先上锁

乐观锁

        每次拿数据时不会上锁,但是在更新时会判断一下在此期间别人有没有去更新这个数据,可以使用版本号等机制来控制。乐观锁适用于多读的应用类型,这样可以提高吞吐量。Redis就是利用这种check-and-set机制实现事务的。

监视 key

在执行multi之前,先执行watch key1 [key2],可以监视一个(或多个) key ,如果在事务执行之前这个(或这些) key 被其他命令所改动,那么事务将被打断。

watch <key>

取消监视 

取消 watch 命令对所有 key 的监视。

如果在执行 watch 命令之后,exec 命令或 discard 命令先被执行了的话,那么就不需要再执行unwatch 了。

unwatch

例子:

我们在一号和二号连接中同时对k1进行监视,并且都开启事务。一号连接中先执行加100的操作,可以发现,一号连接执行成功,返回结果:200,然后在二号连接当中实现加200的操作,返回的结果是nil,原因是因为k1的数据已经被修改了,导致事务被打断。

 

Redis事务三特性

单独的隔离操作:事务中的所有命令都会序列化、按顺序地执行。事务在执行的过程中,不会被其他客户端发送来的命令请求所打断。

没有隔离级别的概念:队列中的命令没有提交之前都不会被执行,因为事务提交前任何指令都不会被实际执行。

不保证原子性:事务中如果有一条命令执行失败, 其后的命令仍然会被执行,没有回滚。

秒杀案例

超卖问题

购物网站进行商品秒杀活动时,并发的情况下,需要设置锁来避免超卖问题。比如说,一件商品有1000件,有10000个人在进行秒杀,10000个请求在没有锁的限制条件下,会出现超卖问题,最终商品的库存为负数。

解决方案

使用乐观锁来进行限制,当商品库存变化时,事务执行失败。

连接超时问题

很多个用户同时发送秒杀请求,会出现请求超时问题,需要设置超时时间。

解决方案

使用连接池来解决。

库存遗留问题

使用了乐观锁来杜绝了超卖问题,但是当一个用户秒杀成功后,和这个用户同一时间秒杀的人,并且程序中已经秒杀成功的人由于库存信息的变化,事务并不会执行。那么这一部分人虽然占了秒杀名额,但是实际上并没有购买到商品,商品库存没有减少,但是却占了秒杀名额。

解决方案

使用LUA脚本,将复杂的或者多步的redis操作写为一个脚本,一次提交给redis执行,减少反复连接redis的次数,提升性能。并且LUA脚本有一定的原子性,不会被其他命令插队。使用LUA脚本解决问题,实际上是redis利用其单线程的特性,用任务队列的方式解决了多任务并发问题。

原网站

版权声明
本文为[知道什么是码怪吗?]所创,转载请带上原文链接,感谢
https://blog.csdn.net/weixin_41746479/article/details/125585683