参考:
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分布式锁的原理** 分布式锁通常需要满足以下条件: 1. **互斥性**:在同一时刻,只能有一个客户端获取锁。 2. **可重入性**:持有锁的客户端可以再次获取该锁,防止死锁。 3. **自动续期**:防止锁过期导致...
通过理解并正确使用`RedisLock.php`这样的工具,我们可以确保在多用户、多线程环境中正确地管理共享资源,提高系统的稳定性和性能。在实际项目中,还需要根据业务需求对锁的实现进行优化和调整,确保其安全性和效率...
Redisson是一个基于Redis的Java客户端,它提供了丰富的数据结构(如锁、队列、信号量等)以及分布式服务(如原子计数器、ID生成器等)。通过使用Redis作为中间件,Redisson可以在分布式环境中提供高性能的同步和异步...
在Scala中,我们可以创建一个`RedisTool`工具类来实现分布式锁。首先,`RedisTool`对象包含了几个常量,比如`LOCK_SUCCESS`表示加锁成功,`SET_IF_NOT_EXIST`表示只有当键不存在时才设置,`SET_WITH_EXPIRE_TIME`...
当多个进程或线程分布在不同的服务器上,它们可能需要访问同一份资源,分布式锁就是解决这种问题的关键工具。它确保了在任何时刻只有一个进程能够访问特定的共享资源,从而保证数据的一致性和完整性。 【Redis作为...
以下是一个简化的Redis工具类代码片段,展示了如何使用`List`实现等待序列的分布式锁: ```java public class RedisUcUitl { // ... 省略常量和构造方法 ... // 存储redis队列,将值存入队列头部 public static...
Redis锁在高并发场景下被广泛使用,主要是因为其高效的数据访问速度以及丰富的数据结构,使得它成为解决并发问题的有效工具。Redis直接操作内存,相比传统数据库从硬盘读取数据,速度上有显著提升,减轻了数据库...
实现分布式锁的方法有很多,例如基于Redis的Setnx命令或者RedLock算法。 综上所述,缓存和分布式锁是高并发场景下优化系统性能的关键技术。合理使用缓存可以减少数据库访问,提高响应速度;而分布式锁则能保证在多...
- 分布式ID生成:Snowflake算法、UUID、Redis分布式锁等。 - CAP原理:一致性、可用性、分区容错性的权衡。 - 分布式缓存:Redis、Memcached的使用,以及缓存穿透、缓存雪崩、缓存击穿的问题及其解决方案。 8. *...
- 分布式锁、分布式ID生成(如Snowflake算法)、分布式任务调度。 - 分布式服务框架,如Dubbo、Spring Cloud等。 9. **网络编程** - TCP/IP协议基础,三次握手四次挥手过程。 - HTTP协议,状态码、请求响应报文...
在提供的代码中,`ConcurrentUtil` 类提供了一些关键功能,以利用Redis的锁机制来实现在多进程中同步数据。以下是对主要方法的解释: 1. **构建锁的键(key)**: - `buildUserLockKey(long userId, @NotNull ...
使用Redis的原子操作来实现分布式锁。 #### 代码示例: ```java import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.stereotype.Service; @Service public class ...
- **分布式ID的解决方案** - 常见方案包括UUID、Snowflake算法、Twitter的Snowflake等。 - **分布式锁的使用场景及实现方案** - 场景包括分布式环境下的资源互斥访问、防止并发操作导致的数据不一致等。 - 实现...
- 并发工具类:如CountDownLatch、CyclicBarrier、Semaphore等。 3. **IO/NIO/BIO** - 常规IO:File类、InputStream/OutputStream家族。 - NIO(非阻塞I/O):Channel、Buffer、Selector的使用,提高系统性能。 ...
- 分布式ID生成:了解雪花算法、UUID等分布式ID生成策略。 - 分布式缓存:Redis、Memcached等缓存系统的使用与设计。 - 分布式锁:Zookeeper、Redis实现的分布式锁机制。 面试时,面试官可能会结合实际项目经验...
- 并发工具类:ExecutorService、Future、Callable 和 FutureTask,以及 Lock 接口的实现类。 4. **IO/NIO**: - 文件操作:读写文件,流的分类,BufferedReader 和 BufferedWriter 的使用。 - NIO(非阻塞IO)...
线程安全、同步机制(如synchronized、Lock)、并发容器(如ConcurrentHashMap、BlockingQueue)以及并发工具类(如CountDownLatch、CyclicBarrier)都是必须掌握的。 3. **JVM**:Java虚拟机是Java程序的运行环境...
6. **分布式ID解决方案** - UUID:基于时间戳和随机数。 - 雪花算法:生成递增的唯一 ID。 - 分布式数据库自增 ID。 7. **分布式锁的使用场景及实现方案** - **使用场景**:资源争抢、分布式任务执行。 - **...
- 并发工具类:如CountDownLatch、CyclicBarrier、Semaphore等。 5. **JVM优化**: - 类加载机制:了解双亲委派模型及类加载过程。 - 堆内存结构:新生代、老年代和永久代的划分。 - 方法区:了解运行时常量池...
- **并发编程**:理解线程、同步机制(如synchronized,Lock)及并发工具类(如ExecutorService,CountDownLatch,CyclicBarrier)。 3. **IO/NIO** - **传统IO**:包括File、InputStream/OutputStream、Reader/...