redis6事务和锁机制
Posted 知道什么是码怪吗?
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了redis6事务和锁机制相关的知识,希望对你有一定的参考价值。
目录
事务
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利用其单线程的特性,用任务队列的方式解决了多任务并发问题。
以上是关于redis6事务和锁机制的主要内容,如果未能解决你的问题,请参考以下文章