本文概览:介绍通过redis实现分布式锁。

分布锁还有一个作用就是实现频控,假设超时是2s,如果不释放锁就相当于2s只能操作一次。

1 介绍

1.1  应用场景

用户在进行购买操作时,在某一个时刻,只容许用户进行一次购买,此时可以按照用户维度添加一个分布式锁来实现。

1.2 相关的redis命令

1setnx

setnx的命令实现了 key 的值设为 value ,当且仅当 key 不存在功能,所以可以通过setnx来实现锁

命令格式为:

举例:

2del

可以用来实现释放锁

del命令格式为

3exipire

可以用来实现对一个锁进行设置到期时间。

命令格式如下:

4. cad

CAD(Compare And Delete),查看目标key的value是否等于指定的value值,如果相等,删除该key;不相等则不删除。

说明
该命令仅适用于操作Redis String类型的数据。

2 实现

实现一个简单的锁:如下代码

1、保证超时和上锁在一个事务。超时为了防止上锁的线程在释放锁时突然中断,导致释放锁失败加入一个key的过期时间。

在getLock的逻辑中,对于如下两个操作:

可以通过如下操作来实现(从 Redis 2.6.12 版本开始)。参考 http://doc.redisfans.com/string/set.html

此时修改为

2、如何避免释放别人的锁

key可以通过uuid来生成,在释放锁的时候可以通过如下代码

也可以通过cad来实现。CAD(Compare And Delete),查看目标key的value是否等于指定的value值,如果相等,删除该key;不相等则不删除。

3 应用

释放锁的场景有两种:finnally中释放(成功或者异常都释放) 和  只有执行成功之后释放。对于只有成功之后释放锁的场景,如果失败了,只能等到锁过期自动释放了。

以在finnaly中释放为例:

在砸金蛋活动接口中用到了分布式锁,因为每次砸蛋都需要更新用户砸蛋次数,为了避免用户并发砸蛋,需要使用分布式锁。如下

4 问题

A:如果加锁超时,返回失败,进行删除自己锁时,如何保证删除自己加的锁。

Q: 设置value为UUID,然后删除之前,判断下value的值是否为UUID。 可以使用Resis的cad命令代替del命令

(全文完)

分类&标签

发表评论

电子邮件地址不会被公开。 必填项已用*标注