Redis实现分布式锁

本文主要分享一下redis的分布式锁;

  可直接使用到项目中的,正常使用的;

先讲解一下 redis setIfAbsent的使用

如果为空就set值,并返回1
如果存在(不为空)不进行操作,并返回0

很明显,比get和set要好。因为先判断get,再set的用法,有可能会重复set值。

setIfAbsent 和 setnx

setIfAbsent 是java中的方法
setnx 是 redis命令中的方法

setnx 例子

redis> SETNX mykey "Hello"
(integer) 1
redis> SETNX mykey "World"
(integer) 0
redis> GET mykey
"Hello"

setIfAbsent 例子

 1 BoundValueOperations boundValueOperations = this.redisTemplate.boundValueOps(redisKey);
 2 flag = boundValueOperations.setIfAbsent(value); // flag 表示的是否set
 3 boundValueOperations.expire(seconds, TimeUnit.SECONDS);
 4 
 5 if(!flag){ // 重复
 6     repeatSerial.add(serialNo);
 7     continue;
 8 }else{// 没有重复
 9     norepeatSerial.add(serialNo);
10 }

了解上面所述以后 直接看代码;

 1 package com.example.demo.controller;
 2 
 3 import org.junit.Test;
 4 import org.junit.runner.RunWith;
 5 import org.slf4j.Logger;
 6 import org.slf4j.LoggerFactory;
 7 import org.springframework.beans.factory.annotation.Autowired;
 8 import org.springframework.boot.test.context.SpringBootTest;
 9 import org.springframework.data.redis.core.RedisTemplate;
10 import org.springframework.data.redis.core.script.DefaultRedisScript;
11 import org.springframework.test.context.junit4.SpringRunner;
12 
13 import java.util.Collections;
14 import java.util.concurrent.TimeUnit;
15 
16 /**
17  * Description: RedisDemo <br>
18  *
19  * @author Mr.Liang
20  * Date: 2020/9/27 10:25 <br>
21  */
22 @SpringBootTest
23 @RunWith(SpringRunner.class)
24 public class RedisDemo {
25 
26     private static Logger log = LoggerFactory.getLogger(RedisDemo.class);
27 
28     @Autowired
29     private RedisTemplate redisTemplate;
30 
31     /**
32      * 锁时间 秒
33      */
34     private static final int LOCK_TIME = 60;
35 
36     @Test
37     public void testLock() {
38 
39         String key = "demo";
40         String value = "Lock";
41         try {
42             setLock(key, value, LOCK_TIME);
43         } catch (Exception e) {
44             //锁异常
45             log.error("加锁异常{}", e);
46         } finally {
47             //释放锁
48             releaseLock(key, value);
49         }
50     }
51 
52     /**
53      * redis加分布式锁
54      *
55      * @param key
56      * @param value
57      * @param seconds 秒
58      * @return
59      */
60     public boolean setLock(String key, Object value, long seconds) {
61         boolean result = false;
62         try {
63             result = redisTemplate.opsForValue().setIfAbsent(key, value, seconds, TimeUnit.SECONDS);
64         } catch (Exception e) {
65             log.error("setLock发生异常", e);
66         }
67         return result;
68     }
69 
70 
71     /**
72      * 释放锁
73      *
74      * @param lockKey
75      * @param value
76      * @return
77      */
78     public boolean releaseLock(String lockKey, String value) {
79         //lua脚本
80         String script = "if redis.call('get', KEYS[1]) == ARGV[1] " +
81                 "then return redis.call('del', KEYS[1]) else return 0 end";
82         DefaultRedisScript<Long> redisScript = new DefaultRedisScript<>(script, Long.class);
83         Long result = (Long) redisTemplate.execute(redisScript, Collections.singletonList(lockKey), value);
84         return result == 1;
85     }
86 }

有问题欢迎指出交流;

原文地址:https://www.cnblogs.com/hb-liang/p/13738146.html