10.Redis实现分布式锁

重要的命令:
SETNX命令(SET if Not eXists)
语法:
SETNX key value
功能:
当且仅当 key 不存在,将 key 的值设为 value ,并返回1;若给定的 key 已经存在,则 SETNX 不做任何动作,并返回0。

GETSET命令
语法:
GETSET key value
功能:
将给定 key 的值设为 value ,并返回 key 的旧值 (old value),当 key 存在但不是字符串类型时,返回一个错误,当key不存在时,返回nil。


实现思路: 主要是使用了redis 的setnx命令,缓存了锁.
reids缓存的key是锁的key,所有的共享, value是锁的到期时间(注意:这里把过期时间放在value了,没有时间上设置其超时时间)

执行过程:

    1. setnx(lockkey, 当前时间+过期超时时间) ,如果返回1,则获取锁成功;如果返回0则没有获取到锁,转向2。
    1. get(lockkey)获取值oldExpireTime ,并将这个value值与当前的系统时间进行比较,如果小于当前系统时间,则认为这个锁已经超时,可以允许别的请求重新获取,转向3。
    1. 计算newExpireTime=当前时间+过期超时时间,然后getset(lockkey, newExpireTime) 会返回当前lockkey的值currentExpireTime。
    1. 判断currentExpireTime与oldExpireTime 是否相等,如果相等,说明当前getset设置成功,获取到了锁。如果不相等,说明这个锁又被别的请求获取走了,那么当前请求可以直接返回失败,或者继续重试。
    1. 在获取到锁之后,当前线程可以开始自己的业务处理,当处理完毕后,比较自己的处理时间和对于锁设置的超时时间,如果小于锁设置的超时时间,则直接执行delete释放锁;如果大于锁设置的超时时间,则不需要再锁进行处理。

@RestController
14 @Slf4j
15 public class OrderController {
16 
17     @Autowired
18     private StringRedisTemplate stringRedisTemplate;
19 
20     @PostMapping(value = "/createOrder", produces = "application/json;charset=utf-8")
21     public String createOrder(@RequestBody OrderRequest request) {
22 
23         String json = JsonUtils.objectToJson(request);
24         String md5 = DigestUtils.md5DigestAsHex(json.getBytes()).toUpperCase();
25 
26         /*
27          * setIfAbsent <=> SET key value [NX] [XX] [EX <seconds>] [PX [millseconds]]
28          * set expire time 5 mins
29          */
30         Boolean flag = stringRedisTemplate.opsForValue().setIfAbsent(md5, "1", 60 * 5, TimeUnit.SECONDS);
31         if (flag) {
32             // lock success, start to handle business
33             log.debug("{} lock success, start to handle business", md5);
34             try {
35                 //mock to handle business
36                 Thread.sleep(1000 * 10);
37             } catch (InterruptedException e) {
38                 e.printStackTrace();
39             }
40             //end to handle business, need to unlock
41             stringRedisTemplate.delete(md5);
42             log.debug("{} unlock success,end to handle business", md5);
43             return "SUCCESS";
44         } else {
45             log.debug("{} lock failure", md5);
46             return "try again later";
47         }
48     }
49 }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值