事务
1、定义:
Redis事务是一个单独的隔离操作
①事务中所有的命令都会被序列化、按照顺序执行
②事务在执行过程中不会被其他客户端发送来的命令请求打断
2、作用:
串联多个命令防止别的命令插队
multi:输入开始命令
exec:执行命令
discard:放弃组队(删除掉)
3、注意事项:
1、multi 命令不能嵌套使用,如果已经开启了事务的情况下,再执行 multi 命令,会提示如下错误:
127.0.0.1:6379> multi
OK
127.0.0.1:6379> multi
(error) ERR MULTI calls can not be nested //这里报错不会使事务终止
127.0.0.1:6379> set a 100
QUEUED
127.0.0.1:6379> exec
1) OK
但是这个错误不会使事务终止
2、 如果在组队中出现了报告错误,执行时整个队列都会被取消掉(当前事务就会终止), 比如multi嵌套就是组队的时候报告错误
3、 如果在执行阶段某个命令出现错误,只有报错的命令不会被执行,其他的命令照常执行,不会回滚
127.0.0.1:6379> multi //开启事务
OK
127.0.0.1:6379> set a 123
QUEUED
127.0.0.1:6379> lpop a //使用list命令操作set类型
QUEUED
127.0.0.1:6379> exec //执行
1) OK //正常的命令执行成功
2) (error) WRONGTYPE Operation against a key holding the wrong kind of value //错误的命令执行失败
4、悲观锁:
.
每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁 ,这样别人想拿这个数据就会block(阻塞)直到他拿到锁
传统的关系型数据库里面就是用到了很多这样的锁机制 (行锁、表锁、读锁、写锁都是在操作之前先上锁)
乐观锁:
每次去拿数据的时候都认为别人不会修改,所以不会上锁 ,但是在更新的时候会判断一下在此期间别人会不会更新这个数据,可以用版本号等机制
.
例:
比如当前有一个人,想修改一张5000块的银行卡,卡的版本名为v1,他修改完成后顺便将银行卡改个版本名字叫v2,那么当另外一个人来修改这个版本名为v1这张卡的时候,就发现没有v1这张卡,不是不存在,是因为已经被上一个人将版本名v1改为v2了。
.
乐观锁适用于多读的应用类型,提高吞吐量
Redis就是利用这种check-and-set机制实现事务的
5、常用命令:
WATCH key [key…] :
在执行multi之前,先执行watch key1 【key2】,可以监视一个或者多个key,如果在事务执行之前这个(或这些)key被其他命令所改动,那么事务将被打断,(但是,相同的客户端可能会在事务内部修改这些键,此时这个事务不会中止运行。)否则,Redis根本就不会进入事务。类似于乐观锁得机制,我不上锁,但是你修改不了,只能我自己改,我自己改,毫无影响,你要硬来改,我就报错。
.UNWATCH
取消WTACH命令对所有key的监视,如果在执行WATCH命令之后,EXEC命令或者DISCARD命令先被执行了的话,那么就不需要再执行UNWATCH命令了
6、Redis事务三大特性:
.
1、单独的隔离操作:事务中的所有命令都会序列化、按顺序地执行。事务在执行的过程中,不会被其他客户端发送来的命令请求所打断。
.
2、没有隔离级别的概念:队列中的命令没有提交之前都不会实际的被执行,因为事务提交前任何指令都不会被实际执行,也就不存在”事务内的查询要看到事务里的更新,在事务外查询不能看到”这个让人万分头痛的问题
.
3、不保证原子性:redis同一个事务中如果有一条命令执行失败,其后的命令仍然会被执行,没有回滚
7、Redis事务秒杀场景问题
秒杀
1、解决超卖问题:主要是通过 watch 监视 ,利用watch的特性,监视的值发生变化,事务就终止
.
2、库存遗留问题:利用LUA脚本