• 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 }

    有问题欢迎指出交流;

  • 相关阅读:
    fixed 和 fixed
    SVN命令概要
    项目目录的划分
    作用域(scope), 定义空间(declaration space) 和 生存期(lifetime)
    可伸缩性最佳实践:来自eBay的经验(转)
    TCP连接可用性检测
    面向对象设计
    如何截取Http请求
    eBay架构
    .net3.5下的Socket通信框架
  • 原文地址:https://www.cnblogs.com/hb-liang/p/13738146.html
Copyright © 2020-2023  润新知