点赞再看,养成习惯,听说微信搜《Java鱼仔》会让自己的技术更上一层楼
(一)事务的概念
谈到数据库的高级应用,不可避免会谈到事务。熟悉mysql的朋友们对事务肯定不陌生,简单来讲事务就是控制一个数据库操作序列要么全部执行要么全部不执行。今天我们就来了解redis中的事务是如何执行和使用的。
(二)redis事务的操作
在mysql中,事务的执行通过以下三步:
begin 开启事务 commit 提交事务 rollback 回滚操作
而在redis中,事务的执行也主要有三步
multi 开启事务 设定事务的开启位置,后续的所有指令均加入到该事务中 exec 执行事务 设定事务的结束位置,同时开始执行事务 discard 取消事务 取消该事务,放在multi和exec之间
网络异常,图片无法展示
|
可以看到,当exec执行之后,事务中的所有指令才开始执行。 但是redis的事务并不保证原子性,我们在multi中开启事务,如果在执行事务之前的代码中有一条语句是报错的,那么这条错误指令不会执行,其他指令依旧正常执行。
(三)锁
加锁是实现数据库并发控制的一个非常重要的技术,redis中同样存在锁机制。
3.1 监视锁:
//加锁 watch key1 key2... //解锁 unwatch
对key添加监视锁,在执行exec之前如果key发生了变化,就会终止事务执行: 在一个客户端中增加监视锁:
网络异常,图片无法展示
|
此时在另一个客户端中修改name的值
网络异常,图片无法展示
|
再执行事务会发现事务已经被终止了
网络异常,图片无法展示
|
3.2 分布式锁:
使用setnx设置一个公共锁
设置锁 setnx lock-key value 解锁 del lock-key
对一个key设置公共锁之后,除了设置锁的人之外,其他人只能在外面等待,只有当解锁之后,其他人才能同样再去加锁。
3.3 死锁的解决方案
当加锁之后由于宕机的问题没法解锁时,其他人就只能一直等待了。为了解决这个方案,我们可以为锁设置时间限定,如果时间到了还没释放锁,就由系统删除这把锁:
expire lock-key second pexpire lock-key milliseconds
由于操作通常是毫秒或者微秒级别的,所以锁时间不能设置太长。在实际的开发过程中,我们会在设置分布式锁的同时给他添加生命周期。