一、Redis事务
什么是事务
举一个烂大街的例子:银行转账。当我们要在银行进行转账的时候,它的操作可以分为两部分:一先扣除你账户的金额1000RMB,二把被转账人的账户金额加1000RMB。但是如果在把你的钱扣除了然后系统发生了故障(比如断电),并没有把被转账人的金额增加。这样你不就损失了1000,而银行赚了1000。这是就需要事务来控制。在转账开始前开启一个事务,结束后关闭事务。如果中间发生了错误那这个事务就认为是无效的。在错误在前作的事情需要在退回去(回滚)。
事务特性
事务具备四个特性:ACID
- 原子性(Automatic):事务是一个原子操作(做小的操作),事务要么做了要么没做。不能只完成一部分。
- 一致性(Consistency):事务完成前后数据完整性没有改变
- 隔离性(Isolation):一个事务在执行的过程中不应该受其他事务的干扰
- 持久性(Durability):事务一旦结束数据就要保存到磁盘上
Redis事务用法
multi # 开启事务,同MySQL的begin或start transaction
discard # 中断事务,同MySQLrollback
exec # 结束事务,同MySQLcommit
正常执行一个事务
中断一个事务,可以看到数据并未被修改
事务工作流程(截屏偷传智黑马班的-_-)
事务的锁
watch key [key]
对key添加监视锁,在执行exec前,监视的对象发生了变化则终止事务执行。
unwatch
取消所有监视对象。
对name进行监视
在执行exec操作之前先执行,在另一个客户端先执行下面的操作。会发现提交事务后返回nil,事务没有执行。查找aa返回nil。
上面的watch只能监视key的值有没有发生变化,不能解决多个客户端在秒杀的时候的并发问题。所以使用
setnx lock-key value # 对key加锁
如果多次设置锁,则不成功返回0.
上面设置的锁均需要手动释放。而如果一个客户端在拿到锁之后,发生了宕机之类的事件,我们就需要使用定时来设置锁了。
下面两条指令分别针对秒和毫秒级设置锁
expire lock-name second
pexpire lock-name millisecond
首先执行下面这张图片的客户端的操作,给name设置了一个锁,然后设定了一个期限10秒
然后执行下面图片客户端操作,可以看到一开始不成功,当10秒后,设置锁就成功了。
对于设置锁和设置期限,这是两个操作,我们必须让他们是原子操作,这样才能达到我们的目的。可以用脚本语言设置原子操作。
注:文章内容均是观看视频后自己写的笔记,部分图片是视频截图。原视频链接