业务里为什么要使用分布式锁
在上面的商城业务中,由于没有进行发货的校验,且数据库使用的是mongodb并不支持事务,所以导致会出现两次发货请求
如何解决此问题
利用redis实现分布式锁
那么问题来了,如何利用redis实现分布式锁:
redis数据结构
- 字符串
- 列表
- hash
- zset
- 集合 这里面先介绍下redis的字符串数据结构,说到字符串其实是最常见和最长使用的数据机构够,无论是在编程语言(java)还是数据库中都有用到,也是作者比较熟悉的数据结构
如何使用
- 首先使用redis 设置一个key
示例: setnx key value
-
设置一个过期时间
Q1:为什么要设置一个过期时间
A1:理论上使用setnx命令已经可以实现一个分布式锁了,但是这里存在一个问题, 对于分布式锁来说如果不进行解锁那么就会陷入死锁,导致业务逻辑出现问题。例如当一笔订单发货失败后,如果一直没有解锁,那么这笔订单就算是丢单了。但是解锁如果失败了也会出现同样的问题。所以给当前的key设置一个过期时间是很重要的。
Q2:过期时间设置多久
A2:我们业务里的过期时间是3秒。
-
使用lua脚本设置
Q1: 为什么使用lua脚本设置 A1: 首先setnx 和过期时间的设置不是事务的,也就是说可能过期时间没有设置成功。这样会导致死锁,redis支持使用lua脚本来实现redis的事务。
实践
if (redis.call('setnx',KEYS[1],ARGV[1]) < 1) then return 0; end; redis.call('expire',KEYS[1],tonumber(ARGV[2])); return 1;
解锁
解锁的实现基本和加锁一样,同样是使用lua脚本来删除key的
if (redis.call('get', KEYS[1]) == ARGV[1])
then return redis.call('del', KEYS[1])
else return 0
end
最后
微信公众号地址