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 }
有问题欢迎指出交流;