基于Redis实现分布式锁(下)
来源:互联网 发布:全轮转可变数据印刷机 编辑:程序博客网 时间:2024/06/05 20:00
基于Redis实现分布式锁,上一篇已经介绍了原理和流程,下面是实现的代码。
Redis分布式锁
package com.github.jedis.lock;import redis.clients.jedis.Jedis;/** * Redis distributed lock implementation. */public class JedisLock { Jedis jedis; /** * Lock key path. */ String lockKey; /** * Lock expiration in miliseconds. * 锁超时,防止线程在入锁以后,无限的执行等待 */ int expireMsecs = 60 * 1000; /** * Acquire timeout in miliseconds. * 锁等待,防止线程饥饿 */ int timeoutMsecs = 10 * 1000; boolean locked = false; /** * Detailed constructor with default acquire timeout 10000 msecs and lock expiration of 60000 msecs. * * @param jedis * @param lockKey lock key (ex. account:1, ...) */ public JedisLock(Jedis jedis, String lockKey) { this.jedis = jedis; this.lockKey = lockKey; } /** * Detailed constructor with default lock expiration of 60000 msecs. * * @param jedis * @param lockKey lock key (ex. account:1, ...) * @param timeoutMsecs acquire timeout in miliseconds (default: 10000 msecs) */ public JedisLock(Jedis jedis, String lockKey, int timeoutMsecs) { this(jedis, lockKey); this.timeoutMsecs = timeoutMsecs; } /** * Detailed constructor. * * @param jedis * @param lockKey lock key (ex. account:1, ...) * @param timeoutMsecs acquire timeout in miliseconds (default: 10000 msecs) * @param expireMsecs lock expiration in miliseconds (default: 60000 msecs) */ public JedisLock(Jedis jedis, String lockKey, int timeoutMsecs, int expireMsecs) { this(jedis, lockKey, timeoutMsecs); this.expireMsecs = expireMsecs; } /** * Detailed constructor with default acquire timeout 10000 msecs and lock expiration of 60000 msecs. * * @param lockKey lock key (ex. account:1, ...) */ public JedisLock(String lockKey) { this(null, lockKey); } /** * Detailed constructor with default lock expiration of 60000 msecs. * * @param lockKey lock key (ex. account:1, ...) * @param timeoutMsecs acquire timeout in miliseconds (default: 10000 msecs) */ public JedisLock(String lockKey, int timeoutMsecs) { this(null, lockKey, timeoutMsecs); } /** * Detailed constructor. * * @param lockKey lock key (ex. account:1, ...) * @param timeoutMsecs acquire timeout in miliseconds (default: 10000 msecs) * @param expireMsecs lock expiration in miliseconds (default: 60000 msecs) */ public JedisLock(String lockKey, int timeoutMsecs, int expireMsecs) { this(null, lockKey, timeoutMsecs, expireMsecs); } /** * @return lock key */ public String getLockKey() { return lockKey; } /** * Acquire lock. * * @return true if lock is acquired, false acquire timeouted * @throws InterruptedException in case of thread interruption */ public synchronized boolean acquire() throws InterruptedException { return acquire(jedis); } /** * Acquire lock. * * @param jedis * @return true if lock is acquired, false acquire timeouted * @throws InterruptedException in case of thread interruption */ public synchronized boolean acquire(Jedis jedis) throws InterruptedException { //锁等待,防止线程饥饿 int timeout = timeoutMsecs; while (timeout >= 0) { //锁超时,防止线程在入锁以后,无限的执行等待(为什么加1:因为可能有相同时间的操作,这样做不完美,但是实用) long expires = System.currentTimeMillis() + expireMsecs + 1; String expiresStr = String.valueOf(expires); //锁到期时间 if (jedis.setnx(lockKey, expiresStr) == 1) { // lock acquired locked = true; 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; return true; } } timeout -= 100; Thread.sleep(100); } return false; } /** * Acqurired lock release. */ public synchronized void release() { release(jedis); } /** * Acqurired lock release. */ public synchronized void release(Jedis jedis) { if (locked) { jedis.del(lockKey); locked = false; } }}
分布式锁封装
<pre name="code" class="java">/** * Copyright (c) 2011-2020 Panguso, Inc. * All rights reserved. * * This software is the confidential and proprietary information of Panguso, * Inc. ("Confidential Information"). You shall not * disclose such Confidential Information and shall use it only in * accordance with the terms of the license agreement you entered into with Panguso. */package com.chinaso.phl.concurrent;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import redis.clients.jedis.Jedis;import redis.clients.jedis.JedisPool;import com.github.jedis.lock.JedisLock;/** * 分布式锁的简单用法 * @author come from network * @date 2014-3-7 */public class SimpleLock { private static Logger logger = LoggerFactory.getLogger(SimpleLock.class); private static JedisPool pool; private JedisLock jedisLock; private String lockKey; private Jedis jedis; private int timeoutMsecs; private int expireMsecs; public SimpleLock(String lockKey) { this(lockKey, 3000, 300000); } public SimpleLock(String lockKey, int timeoutMsecs, int expireMsecs) { this.lockKey = lockKey; this.jedis = pool.getResource(); this.timeoutMsecs = timeoutMsecs; this.expireMsecs = expireMsecs; this.jedisLock = new JedisLock(jedis, lockKey.intern(), timeoutMsecs, expireMsecs); } public void wrap(Runnable runnable) { long begin = System.currentTimeMillis(); try { // timeout超时,等待入锁的时间,设置为3秒;expiration过期,锁存在的时间设置为5分钟 logger.info("begin logck,lockKey={},timeoutMsecs={},expireMsecs={}", lockKey, timeoutMsecs, expireMsecs); if (jedisLock.acquire()) { // 启用锁 runnable.run(); } else { //logger.info("The time wait for lock more than [{}] ms ", timeoutMsecs); } } catch (Throwable t) { // 分布式锁异常 logger.warn(t.getMessage(), t); } finally { this.lockRelease(jedisLock, jedis); } logger.info("[{}]cost={}", lockKey, System.currentTimeMillis() - begin); } /** * 释放锁,后期欲将离线计算的释放锁封装 * * @param lock * @param jedis * @author come from network * @date 2014-3-6 */ private void lockRelease(JedisLock lock, Jedis jedis) { if (lock != null) { try { lock.release();// 则解锁 } catch (Exception e) { } } if (jedis != null) { try { pool.returnResource(jedis);// 还到连接池里 } catch (Exception e) { } } logger.info("release logck,lockKey={},timeoutMsecs={},expireMsecs={}", lockKey, timeoutMsecs, expireMsecs); } public static JedisPool getPool() { return pool; } public static synchronized void setPool(JedisPool pool) { SimpleLock.pool = pool; }}
分布式锁测试
package com.chinaso.phl.concurrent;import org.apache.commons.pool2.impl.GenericObjectPoolConfig;import redis.clients.jedis.JedisPool;/** * @author com from network * @date 2014-3-13*/public class SimpleLockTest { /** * @param args * @author com from network * @date 2014-3-13 */ public static void main(String[] args) { GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig(); final JedisPool pool = new JedisPool(poolConfig, "192.168.142.237", 6379, 3000); //最后一个参数为密码 SimpleLock.setPool(pool);//只需要初始化一次 String key = "test"; SimpleLock lock = new SimpleLock(key); lock.wrap(new Runnable() { @Override public void run() { //此处代码是锁上的 System.out.println(111); } }); }}
阅读全文
0 0
- 基于Redis实现分布式锁(下)
- 基于Redis实现分布式锁(上)
- 基于redis 实现分布式锁(二)
- 基于Redis实现分布式锁
- 基于Redis实现分布式锁
- 分布式锁实现(基于redis)
- 基于Redis实现分布式锁
- 基于Redis实现分布式锁
- 基于Redis实现分布式锁
- 基于Redis实现分布式锁
- 基于Redis实现分布式锁
- 基于Redis实现分布式锁
- 基于Redis实现分布式锁
- 基于Redis实现分布式锁
- 基于Redis实现分布式锁
- 基于Redis实现分布式锁
- 基于Redis实现分布式锁
- 基于Redis实现分布式锁
- 易语言正则批量匹配
- 压缩列表(ziplist)
- Android 关于观察者模式使用代码总结
- 未声明的标识符错误
- 中文分词Rwordseg
- 基于Redis实现分布式锁(下)
- Codeforces
- Xcode后台打印出现:[Client] Geocode error: Error Domain=GEOErrorDomain Code=-8 "(null)”
- JPA入门例子(采用JPA的hibernate实现版本)
- Java布局的一般步骤
- shell 两个日期之间循环
- CF-608B 前缀和
- android N 恢复出厂设置流程简析
- 求助:Parse error in application web.xml file at jndi:/localhost/ssh/WEB-INF/web.xml