使用redis实现一个简单的分布式锁,主要是使用redis的setnx和getset方法进行实现。
加锁:
1.使用setnx设置值:
key:为需要加锁的锁名 value 为 当前时间+锁的超时时间
成功:
返回true 和锁的超时时间
失败:
根据key获取超时时间
为空:说明该锁已经释放了,重新获取锁
不为空:
判断锁是否已经超时
超时:
使用getset进行获取锁
如果返回的值和上一步获取的锁的超时时间一样说明获取锁,(当不一样时可能会导致将上一个线程设置的锁的超时时间进行修改,应该影响不大。)
没有超时:
说明锁被别的线程持有。
解锁:
解锁只可解除自己加的锁:
先获取锁的超时时间
为空:说明该锁已经不存在了
不为空: 根据加锁得到的返回值 和解锁得到的时间进行比较,如果一样说明是自己加的锁。
代码:
com.huan.redis.redis_lock.Lock.LockResult ---> 获取锁之后的返回值 用于判断是否获取锁 和 放入锁中的内容
com.huan.redis.redis_lock.Lock ---> 锁的接口
com.huan.redis.redis_lock.RedisLock ---> 锁的具体实现
锁的接口
package com.huan.redis.redis_lock; /** * 锁的接口 * * @描述 * @作者 huan * @时间 2016年10月30日 - 下午2:31:10 */ public interface Lock { LockResult lock(String lockName); /** * 获取锁 * * @param lockName * 需要上那一把锁 * @param lockTime * 需要使用所的时间 * @param waitTime * 当waitTime这个时间之内还没有获取到锁就退出获取锁 */ LockResult lock(String lockName, long lockTime, long waitTime); /** * 释放锁 * * @param lockName */ void unLock(String lockName, LockResult result); static class LockResult { private boolean lock; private long info; public LockResult(boolean lock, long info) { super(); this.lock = lock; this.info = info; } public boolean isLock() { return lock; } public void setLock(boolean lock) { this.lock = lock; } public long getInfo() { return info; } public void setInfo(long info) { this.info = info; } } }
锁的具体实现
package com.huan.redis.redis_lock; import java.text.SimpleDateFormat; import java.util.Date; import redis.clients.jedis.Jedis; /** * 使用redis实现分布式锁 * * @描述 * @作者 huan * @时间 2016年10月30日 - 下午2:39:11 */ public class RedisLock implements Lock { private Jedis jedis; public RedisLock(Jedis jedis) { this.jedis = jedis; } @Override public LockResult lock(String lockName, long lockTime, long waitTime) { long now = System.currentTimeMillis(); LockResult lockResult = new LockResult(false, 0); while (System.currentTimeMillis() - now <= waitTime) { // 重试 直到超时 long needLockTime = System.currentTimeMillis() + lockTime; if (jedis.setnx("lock:" + lockName, String.valueOf(needLockTime)) == 1) { // 获取锁 System.out.println(Thread.currentThread().getName() + " : 获取锁1.." + new SimpleDateFormat("yyyyMMdd HH:mm:ss").format(new Date())); lockResult = new LockResult(true, needLockTime); return lockResult; } String oldTime = jedis.get("lock:" + lockName); // 如果没有获取锁,则获取锁的持有时间 if (null != oldTime) { // 锁还在 if (System.currentTimeMillis() - Long.parseLong(oldTime) > 0) { // 锁已经超时 needLockTime = System.currentTimeMillis() + lockTime; // 计算新的锁超时时间 String _oldLockTime = jedis.getSet("lock:" + lockName, String.valueOf(needLockTime)); // 设置锁的超时时间 if (null != oldTime && _oldLockTime != null && oldTime.equals(_oldLockTime)) { // 获取锁 System.out.println(Thread.currentThread().getName() + " : 获取锁2.." + new SimpleDateFormat("yyyyMMdd HH:mm:ss").format(new Date())); lockResult = new LockResult(true, needLockTime); return lockResult; } else { // System.out.println("另外的线程释放锁."); } } // System.out.println(Thread.currentThread().getName() + " : 尝试获取锁.."); } else { // 另外的线程释放锁,需要重新获取锁 needLockTime = System.currentTimeMillis() + lockTime; // 计算新的锁超时时间 if (jedis.setnx("lock:" + lockName, String.valueOf(needLockTime)) == 1) { System.out.println(Thread.currentThread().getName() + " : 获取锁3.." + new SimpleDateFormat("yyyyMMdd HH:mm:ss").format(new Date())); lockResult = new LockResult(true, needLockTime); return lockResult; } } try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); Thread.currentThread().interrupt(); } } return lockResult; } @Override public void unLock(String lockName, LockResult lockResult) { String oldTime = jedis.get("lock:" + lockName); if (null != oldTime && lockResult.isLock() && lockResult.getInfo() == Long.parseLong(oldTime)) { System.out.println(Thread.currentThread().getName() + " 释放锁.." + new SimpleDateFormat("yyyyMMdd HH:mm:ss").format(new Date())); jedis.del("lock:" + lockName); } else { if (0 == lockResult.getInfo()) { System.out.println(Thread.currentThread().getName() + " : 获取锁失败..."); } else { System.out.println(Thread.currentThread().getName() + " 持有的锁由于已经被被的线程修改锁不用次线程进行释放."); } } } @Override public LockResult lock(String lockName) { return lock(lockName, Long.MAX_VALUE, Long.MAX_VALUE); } }
测试:
相关推荐
Java基于Redis实现分布式锁代码实例 分布式锁的必要性 在多线程环境中,资源竞争是一个常见的问题。例如,在一个简单的用户操作中,一个线程修改用户状态,首先在内存中读取用户状态,然后在内存中进行修改,然后...
本文将深入探讨如何使用Redis实现分布式锁,以及如何利用自旋式加锁和Lua脚本实现原子性解锁。 首先,我们来理解分布式锁的基本概念。分布式锁是在多节点之间共享资源时,用于协调各个节点的访问控制机制。在分布式...
redis实现分布式锁(java/jedis),其中包含工具方法以及使用demo 本资源是利用java的jedis实现 redis实现分布式锁(java/jedis),其中包含工具方法以及使用demo 本资源是利用java的jedis实现
本文将深入探讨如何使用C++结合Redis实现分布式锁,并详细讲解Redis API在C++中的应用,以及如何处理与Boost库的集成。 首先,Redis是一个高性能的键值存储数据库,广泛用于缓存、消息队列、分布式锁等场景。分布式...
本文讨论了分布式锁的实现方案,主要基于Redis实现分布式锁,以解决分布式系统中资源访问的同步问题。在分布式系统中,需要协调各个系统或主机之间的资源访问,以避免彼此干扰和保证一致性。分布式锁是控制分布式...
在实际项目中,`redis实现分布式锁与java信号量.md`文件可能详细介绍了如何将这些理论知识应用到实际代码中,包括连接Redis、设置和获取锁、释放锁、异常处理等步骤。而`项目说明.zip`文件则可能包含了一个实际的...
Redis,作为一个高性能的键值存储系统,常被用于实现分布式锁,因为它提供了丰富的数据类型和原子操作。本教程将深入探讨如何利用Redis来构建分布式锁。 一、Redis分布式锁的优势 1. 响应速度:Redis是内存数据库...
本文将深入探讨如何利用Redis实现分布式锁,并对比其与信号量的区别。 一、Redis分布式锁 1. **基本原理**:在Redis中,分布式锁通常通过`SETNX`(Set if Not eXists)命令或者`SET`命令配合`nx`和`ex`选项来创建...
一、Redis实现分布式锁 1. Redis分布式锁的核心是`setnx()`命令,它用于设置键值对,但如果键已存在,则返回失败。在分布式锁的实现中,通常会为锁设置一个超时时间,以防锁意外丢失。例如,使用`Lock:order`作为锁...
本篇文章将深入探讨如何利用Redis实现分布式锁以及如何构建一个基于Redis的任务队列。 分布式锁是解决多节点共享资源时防止数据冲突的关键机制。在Go中,我们通常通过与Redis交互来实现这一功能。Redis提供了`SETNX...
Spring Boot 提供了与 Redis 集成的便捷方式,使得开发者能够快速实现分布式锁功能。本篇文章将详细讲解如何利用 Spring Boot 结合 Redis 实现分布式锁。 首先,理解分布式锁的基本概念。分布式锁是在分布式系统中...
首先,Redis作为一个内存数据库,其高速读写性能使其成为实现分布式锁的理想选择。分布式锁的主要作用是在多节点环境下保证同一时刻只有一个节点可以执行特定操作,避免并发问题。Redisson的分布式锁通过`RLock`接口...
分布式锁有很多种解决方案,今天我们要讲的是怎么使用缓存数据库Redis来实现分布式锁。 课程目标: 理解redis分布式锁的应用场景 掌握redis分布式锁的实现原理 掌握redis分布式锁在微服务项目中的应用 掌握...
Redis实现分布式锁主要依赖三个基本操作:`SETNX`(Set If Not eXists)、`EXPIRE` 和 `DEL`。 1. **`SETNX` 命令**:只有当键不存在时才设置键值,返回1表示设置成功,返回0表示键已存在,无法设置。 2. **`EXPIRE...
4. 性能与可用性:使用Redis实现分布式锁,可以保证很高的性能,因为Redis操作非常快速。同时,由于Redis支持主从复制和哨兵模式,提供了高可用性的保障。即便主节点不可用,通过故障转移,其他从节点可以迅速接管,...
读书笔记:架构实战篇十八Spring Boot Redis实现分布式锁
本篇文章将深入探讨如何在C#.NET环境下利用Redis实现分布式锁,以及相关的核心知识点。 首先,让我们理解什么是分布式锁。分布式锁是在分布式系统中,用于协调不同节点间对共享资源访问的一种工具。它确保在任何...
本文将深入探讨如何使用Go语言(Golang)和Redis来实现分布式锁,并介绍其中涉及到的关键概念和实现方式,包括看门狗(Watchdog)和红锁(RedLock)策略。 **一、Redis作为分布式锁** Redis因其高性能、轻量级以及...
不过,以上代码提供了一个基本的实现思路,帮助你理解如何在SpringBoot应用中使用Redis实现分布式锁。 通过提供的Word文档,你应该能够找到更详细的配置和使用步骤。记得在实际项目中根据具体需求进行调整,确保...