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

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

分布式锁是控制分布式系统之间同步访问共享资源的一种方式

锁接口定义

定义一个锁通用接口,对外提供锁服务

import java.util.concurrent.TimeUnit;public interface LockService {    /**      * 尝试获取锁     * @param 锁名     */    public boolean tryLock(String name);    /**      * 在指定时间内尝试获取锁     * @param 锁名     * @param 尝试时间     */    public boolean tryLock(String name, long timeout, TimeUnit unit);    /**      * 获取锁,阻塞方法,直到获取锁成功为止     * @param 锁名     */    public void lock(String name) throws Exception;    /**      * 释放锁     * @param 锁名     */    public void unlock(String name);}

redis锁的实现:

public class RedisLockService implements LockService {    private static final String NAMESPACE = "lock-service:";    private static final Logger log = LogManager.getLogger(RedisLockService.class);    @Autowired    private RedisTemplate
stringRedisTemplate; /** 锁默认超时时间,单位:秒 */ @Value("${lockService.timeout:300}") private int timeout; /** 服务ID,用于区分释放锁权限。 */ @Value("${instance.id:locks}") private String instanceId; @Override public boolean tryLock(String name) { String key = NAMESPACE + name; String value = getValue(); boolean success = stringRedisTemplate.opsForValue().setIfAbsent(key, value); //如果不存在key,则set if (success) stringRedisTemplate.expire(key, this.timeout, TimeUnit.SECONDS); //设置默认锁有效时间 return success; } @Override public boolean tryLock(String name, long timeout, TimeUnit unit) { if (timeout <= 0) return tryLock(name); String key = NAMESPACE + name; String value = getValue(); boolean success = stringRedisTemplate.opsForValue().setIfAbsent(key, value); long millisTimeout = unit.toMillis(timeout); long start = System.currentTimeMillis(); while (!success) { //若获取锁不成功,则在限定时间内不断尝试,直到获取成功,或超时 try { Thread.sleep(100); } catch (InterruptedException e) { return false; } if ((System.currentTimeMillis() - start) >= millisTimeout) break; success = stringRedisTemplate.opsForValue().setIfAbsent(key, value); } if (success) stringRedisTemplate.expire(key, this.timeout, TimeUnit.SECONDS); return success; } @Override public void lock(String name) { String key = NAMESPACE + name; String value = getValue(); boolean success = stringRedisTemplate.opsForValue().setIfAbsent(key, value); while (!success) { try { Thread.sleep(100); //每间隔100毫秒,再次尝试获取锁 } catch (InterruptedException e) { e.printStackTrace(); } success = stringRedisTemplate.opsForValue().setIfAbsent(key, value); if (success) stringRedisTemplate.expire(key, this.timeout, TimeUnit.SECONDS); } } @Override public void unlock(String name) { String key = NAMESPACE + name; String value = getValue(); //一行lua脚本,如果KEY的值等于VALUE,则删除KEY,否则返回0 String str = "if redis.call(\"get\",KEYS[1]) == ARGV[1] then return redis.call(\"del\",KEYS[1]) else return 0 end"; RedisScript
script = new DefaultRedisScript
(str, Long.class); Long ret = stringRedisTemplate.execute(script, Collections.singletonList(key), value); if (ret == 0) log.warn("Lock [{}] is not hold by instance [{}]", name, value); } /** * 生成由服务ID+线程名组成的线程唯一value。用于保证只能被拥有锁的线程解锁 */ private String getValue(){ return instanceId + Thread.currentThread().getName(); }}

转载于:https://www.cnblogs.com/coderzl/p/7490226.html

你可能感兴趣的文章
【javascript】ajax请求 编码问题导致的ie浏览器在输入中文文字后没有内容,而chrome正常搜到文字...
查看>>
Git分支操作
查看>>
Spring Integration概述
查看>>
[SAP ABAP开发技术总结]权限对象检查
查看>>
RDIFramework.NET ━ 9.6 模块(菜单)管理 ━ Web部分
查看>>
Android安全问题 静音拍照与被拍
查看>>
cocos2d-x 3.1.1 学习笔记[13] listen 监听器
查看>>
定制私人博客
查看>>
WTL介绍
查看>>
应用程序框架实战三十四:数据传输对象(DTO)介绍及各类型实体比较(转)
查看>>
放量滞涨,抛出信号
查看>>
BeanFactory not initialized or already closed - call 'refresh' before accessing beans解决办法
查看>>
dSYM 文件分析工具
查看>>
R语言合并data.frame
查看>>
linux主机下的Vmware Workstation配置NAT设置 端口映射-Ubuntu为例
查看>>
unity physics joint
查看>>
TD的访问地址
查看>>
JAVA常见面试题之Forward和Redirect的区别
查看>>
tmpFile.renameTo(classFile) failed 错误
查看>>
【甘道夫】Apache Hadoop 2.5.0-cdh5.2.0 HDFS Quotas 配额控制
查看>>