博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
RedisTemplate实现分布式锁
阅读量:5166 次
发布时间:2019-06-13

本文共 2965 字,大约阅读时间需要 9 分钟。

使用RedisTemplate的execute的回调方法,里面使用Setnx方法

Setnx就是,如果没有这个key,那么就set一个key-value, 但是如果这个key已经存在,那么将不会再次设置,get出来的value还是最开始set进去的那个value.

接下来我们用代码的形式展现:

package com.shuige.components.cache.redis; import org.springframework.beans.factory.annotation.Autowired;import org.springframework.data.redis.core.RedisCallback;import org.springframework.data.redis.core.RedisTemplate;import org.springframework.data.redis.core.ValueOperations;import org.springframework.stereotype.Component; import java.util.Objects;import java.util.concurrent.TimeUnit; /** * Description: 通用Redis帮助类 * User: zhouzhou * Date: 2018-09-05 * Time: 15:39 */@Componentpublic class CommonRedisHelper {    //锁名称    public static final String LOCK_PREFIX = "redis_lock";    //加锁失效时间,毫秒    public static final int LOCK_EXPIRE = 300; // ms     @Autowired    RedisTemplate redisTemplate;        /**     *  最终加强分布式锁     *     * @param key key值     * @return 是否获取到     */    public boolean lock(String key){        String lock = LOCK_PREFIX + key;        // 利用lambda表达式        return (Boolean) redisTemplate.execute((RedisCallback) connection -> {             long expireAt = System.currentTimeMillis() + LOCK_EXPIRE + 1;            Boolean acquire = connection.setNX(lock.getBytes(), String.valueOf(expireAt).getBytes());              if (acquire) {                return true;            } else {                 byte[] value = connection.get(lock.getBytes());                 if (Objects.nonNull(value) && value.length > 0) {                     long expireTime = Long.parseLong(new String(value));                     // 如果锁已经过期                    if (expireTime < System.currentTimeMillis()) {                        // 重新加锁,防止死锁                        byte[] oldValue = connection.getSet(lock.getBytes(), String.valueOf(System.currentTimeMillis() + LOCK_EXPIRE + 1).getBytes());                        return Long.parseLong(new String(oldValue)) < System.currentTimeMillis();                    }                }            }            return false;        });    }     /**     * 删除锁     *     * @param key     */    public void delete(String key) {        redisTemplate.delete(key);    } }

如何使用呢,导入工具类后:

CommonRedisHelper redisHelper = new CommonRedisHelper();
boolean lock = redisHelper.lock(key);
if (lock) {            // 执行逻辑操作            redisHelper.delete(key);        } else {            // 设置失败次数计数器, 当到达5次时, 返回失败            int failCount = 1;            while(failCount <= 5){                // 等待100ms重试                try {                    Thread.sleep(100l);                } catch (InterruptedException e) {                    e.printStackTrace();                }                if (redisHelper.lock(key)){                   // 执行逻辑操作                    redisHelper.delete(key);                }else{                    failCount ++;                }            }            throw new RuntimeException("现在创建的人太多了, 请稍等再试");        }

 

转载于:https://www.cnblogs.com/ZenoLiang/p/11209980.html

你可能感兴趣的文章
【《Effective C#》提炼总结】提高Unity中C#代码质量的22条准则
查看>>
详解java类的生命周期
查看>>
python 绑定双端口
查看>>
Objective-c继承与组合
查看>>
转:一个Restful Api的访问控制方法(简单版)
查看>>
IIS6修改ASP上传文件200K限制
查看>>
【转】Java连接Mysql,SQL Server, Access,Oracle
查看>>
[CSS]理解line-height
查看>>
设置winform中webBrower控件所使用的IE版本
查看>>
《Linux内核设计与实现》第五章读书笔记
查看>>
linux 下C语言编程库文件处理与Makefile编写
查看>>
软件工程第四次作业
查看>>
YZR IOC之RUtility
查看>>
HTTP 状态码
查看>>
@Linux下Redis的安装
查看>>
java 内部类与控制框架
查看>>
2014=9=24 连接数据库2
查看>>
安装lvs过程
查看>>
[BZOJ3684][拉格朗日反演+多项式求幂]大朋友和多叉树
查看>>
结对编程的感想&收获
查看>>