`
uule
  • 浏览: 6358268 次
  • 性别: Icon_minigender_1
  • 来自: 一片神奇的土地
社区版块
存档分类
最新评论

Redis分布式锁取ID-工具类RedisLock

阅读更多

参考:

https://www.jianshu.com/p/79f2e1d9568c

 

工具类:

import org.apache.log4j.Logger;
import redis.clients.jedis.Jedis;
import com.common.common.RedisCacheUtil;


/**
 * 使用Redis实现的分布式锁
 */
public class RedisLock{
	static Logger logger = Logger.getLogger(RedisLock.class);
	
	private String lockKey;
	private boolean owner = false;
	private boolean waiting = false;
	private int defaltTimeoutMsecs = 60*1000;//锁等待超时时间,以毫秒为单位
	private int defaultExpireMsecs = 60*1000;//锁持有超时时间,以毫秒为单位 
	private boolean expired = false;
	private boolean locked = false;
	private Jedis jedis = null;

	public RedisLock(Jedis jedis, String lockKey) {
		this.jedis = jedis;
		this.lockKey = lockKey;
	}

	/**
	 * 获取分布式锁
	 *
	 * @return true if lock is acquired, false acquire timeouted
	 * @throws InterruptedException
	 *             in case of thread interruption
	 */
	public boolean acquire() throws InterruptedException {
		if(jedis == null){
			return false;
		}
		Long startTime = System.currentTimeMillis();
		int timeout = defaltTimeoutMsecs;
		while (timeout >= 0) {
			long expires = System.currentTimeMillis() + defaultExpireMsecs + 1;
			String expiresStr = String.valueOf(expires); //锁到期时间

			if (jedis.setnx(lockKey, expiresStr) == 1) {
				// lock acquired
				locked = true;
				logger.debug("获取分布式锁成功1,锁key:" + lockKey + ",耗时:" + (System.currentTimeMillis()-startTime));
				return true;
			}

			String currentValueStr = jedis.get(lockKey); //redis里的时间
			if (currentValueStr != null && Long.parseLong(currentValueStr) < System.currentTimeMillis()) {
				//判断是否为空,不为空的情况下,如果被其他线程设置了值,则第二个条件判断是过不去的
				// lock is expired

				String oldValueStr = jedis.getSet(lockKey, expiresStr);
				//获取上一个锁到期时间,并设置现在的锁到期时间,
				//只有一个线程才能获取上一个线上的设置时间,因为jedis.getSet是同步的
				if (oldValueStr != null && oldValueStr.equals(currentValueStr)) {
					//如过这个时候,多个线程恰好都到了这里,但是只有一个线程的设置值和当前值相同,他才有权利获取锁
					// lock acquired
					locked = true;
					logger.debug("获取分布式锁成功2,锁key:" + lockKey + ",耗时:" + (System.currentTimeMillis()-startTime));
					return true;
				}
			}
			timeout -= 100;
			Thread.sleep(100);
			logger.debug("等待获取分布式锁,等待时间:"  + (defaltTimeoutMsecs-timeout));
		}
		logger.info("获取分布式锁失败,锁key:" + lockKey  + ",耗时:" + (System.currentTimeMillis()-startTime));
		return false;
	}

	/**
	 * 释放分布式锁
	 */
	public void release(){
		if(locked){
			jedis.del(lockKey);
			logger.info("释放分布式锁成功,锁key:" + lockKey);
		}
	}
}

 使用:

//锁定
			RedisLock redisLock = new RedisLock(RedisCacheUtil.getResource(),"redis-lock-key");
			boolean ac = false;
			try {
				ac = redisLock.acquire();
			} catch (Exception e1) {
				// TODO Auto-generated catch block
				logger.error("code redis lock error");
				return 0L;
			}
			if(ac){
				// 从数据库中取数据。放缓存				
				redisLock.release();
				
			}else {
				//没有取到锁,说明有进程正往缓存中写数据。 先休眠1秒,再取。
				try {
					Thread.sleep(1000);
				} catch (InterruptedException e) {
					logger.error("thread sleep eror");
				}
			}

 

 

..

 

分享到:
评论

相关推荐

    Redis分布式锁.zip

    **Redis分布式锁的原理** 分布式锁通常需要满足以下条件: 1. **互斥性**:在同一时刻,只能有一个客户端获取锁。 2. **可重入性**:持有锁的客户端可以再次获取该锁,防止死锁。 3. **自动续期**:防止锁过期导致...

    php-redis锁-多种加锁解锁

    通过理解并正确使用`RedisLock.php`这样的工具,我们可以确保在多用户、多线程环境中正确地管理共享资源,提高系统的稳定性和性能。在实际项目中,还需要根据业务需求对锁的实现进行优化和调整,确保其安全性和效率...

    Redis实现分布式锁和等待序列的方法示例

    以下是一个简化的Redis工具类代码片段,展示了如何使用`List`实现等待序列的分布式锁: ```java public class RedisUcUitl { // ... 省略常量和构造方法 ... // 存储redis队列,将值存入队列头部 public static...

    springboot 集成Redission 简单完美解决分布式锁

    Redisson是一个基于Redis的Java客户端,它提供了丰富的数据结构(如锁、队列、信号量等)以及分布式服务(如原子计数器、ID生成器等)。通过使用Redis作为中间件,Redisson可以在分布式环境中提供高性能的同步和异步...

    scala+redis实现分布式锁的示例代码

    在Scala中,我们可以创建一个`RedisTool`工具类来实现分布式锁。首先,`RedisTool`对象包含了几个常量,比如`LOCK_SUCCESS`表示加锁成功,`SET_IF_NOT_EXIST`表示只有当键不存在时才设置,`SET_WITH_EXPIRE_TIME`...

    详解Java如何实现基于Redis的分布式锁

    当多个进程或线程分布在不同的服务器上,它们可能需要访问同一份资源,分布式锁就是解决这种问题的关键工具。它确保了在任何时刻只有一个进程能够访问特定的共享资源,从而保证数据的一致性和完整性。 【Redis作为...

    如何利用Redis锁解决高并发问题详解

    Redis锁在高并发场景下被广泛使用,主要是因为其高效的数据访问速度以及丰富的数据结构,使得它成为解决并发问题的有效工具。Redis直接操作内存,相比传统数据库从硬盘读取数据,速度上有显著提升,减轻了数据库...

    05、缓存&分布式锁1

    实现分布式锁的方法有很多,例如基于Redis的Setnx命令或者RedLock算法。 综上所述,缓存和分布式锁是高并发场景下优化系统性能的关键技术。合理使用缓存可以减少数据库访问,提高响应速度;而分布式锁则能保证在多...

    互联网架构面试题

    - 分布式ID生成:Snowflake算法、UUID、Redis分布式锁等。 - CAP原理:一致性、可用性、分区容错性的权衡。 - 分布式缓存:Redis、Memcached的使用,以及缓存穿透、缓存雪崩、缓存击穿的问题及其解决方案。 8. *...

    Java架构面试专题汇总(含答案)和学习笔记.zip

    - 分布式锁、分布式ID生成(如Snowflake算法)、分布式任务调度。 - 分布式服务框架,如Dubbo、Spring Cloud等。 9. **网络编程** - TCP/IP协议基础,三次握手四次挥手过程。 - HTTP协议,状态码、请求响应报文...

    redis实现多进程数据同步工具代码分享

    在提供的代码中,`ConcurrentUtil` 类提供了一些关键功能,以利用Redis的锁机制来实现在多进程中同步数据。以下是对主要方法的解释: 1. **构建锁的键(key)**: - `buildUserLockKey(long userId, @NotNull ...

    Spring Boot中配置Redis的讲义最全讲义

    使用Redis的原子操作来实现分布式锁。 #### 代码示例: ```java import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.stereotype.Service; @Service public class ...

    跳槽涨薪精选面试题.pdf

    - **分布式ID的解决方案** - 常见方案包括UUID、Snowflake算法、Twitter的Snowflake等。 - **分布式锁的使用场景及实现方案** - 场景包括分布式环境下的资源互斥访问、防止并发操作导致的数据不一致等。 - 实现...

    advanced-java-master.zip

    - 并发工具类:如CountDownLatch、CyclicBarrier、Semaphore等。 3. **IO/NIO/BIO** - 常规IO:File类、InputStream/OutputStream家族。 - NIO(非阻塞I/O):Channel、Buffer、Selector的使用,提高系统性能。 ...

    java后端工程师面试题

    - 分布式ID生成:了解雪花算法、UUID等分布式ID生成策略。 - 分布式缓存:Redis、Memcached等缓存系统的使用与设计。 - 分布式锁:Zookeeper、Redis实现的分布式锁机制。 面试时,面试官可能会结合实际项目经验...

    八月份最新上海面试题

    - 并发工具类:ExecutorService、Future、Callable 和 FutureTask,以及 Lock 接口的实现类。 4. **IO/NIO**: - 文件操作:读写文件,流的分类,BufferedReader 和 BufferedWriter 的使用。 - NIO(非阻塞IO)...

    java面试指南包括 Java基础、Java并发、JVM、MySQL、Redis、Spring、MyBatis、Kafka

    线程安全、同步机制(如synchronized、Lock)、并发容器(如ConcurrentHashMap、BlockingQueue)以及并发工具类(如CountDownLatch、CyclicBarrier)都是必须掌握的。 3. **JVM**:Java虚拟机是Java程序的运行环境...

    (2024)跳槽涨薪必备精选面试题.pdf

    6. **分布式ID解决方案** - UUID:基于时间戳和随机数。 - 雪花算法:生成递增的唯一 ID。 - 分布式数据库自增 ID。 7. **分布式锁的使用场景及实现方案** - **使用场景**:资源争抢、分布式任务执行。 - **...

    java程序员 面试宝典

    - 并发工具类:如CountDownLatch、CyclicBarrier、Semaphore等。 5. **JVM优化**: - 类加载机制:了解双亲委派模型及类加载过程。 - 堆内存结构:新生代、老年代和永久代的划分。 - 方法区:了解运行时常量池...

    Java 工程师进阶知识完全扫盲

    - **并发编程**:理解线程、同步机制(如synchronized,Lock)及并发工具类(如ExecutorService,CountDownLatch,CyclicBarrier)。 3. **IO/NIO** - **传统IO**:包括File、InputStream/OutputStream、Reader/...

Global site tag (gtag.js) - Google Analytics