Redis实现分布式锁

【五斗米】实现分布式锁的三种方式 在单击环境下,就是只有当前JVM虚拟机A中的多个线程对同一个Object(共享资源)进行操作,可以采用同步互斥(就是只有同一时间只有一个线程对共享资源进行事务操作)的方式,我们常用的方式就是采用加锁的方式解决,虽然不能保证数据的强一致性,但是能够保证数据的最终一致性。........................ 阅读详情
/**
 * @author http://blog.youkuaiyun.com/java2000_wl
 * @version <b>1.0.0</b>
 */
public class RedisBillLockHandler implements IBatchBillLockHandler {

	private static final Logger LOGGER = LoggerFactory.getLogger(RedisBillLockHandler.class);

	private static final int DEFAULT_SINGLE_EXPIRE_TIME = 3;
	
	private static final int DEFAULT_BATCH_EXPIRE_TIME = 6;

	private final JedisPool jedisPool;
	
	/**
	 * 构造
	 * @author http://blog.youkuaiyun.com/java2000_wl
	 */
	public RedisBillLockHandler(JedisPool jedisPool) {
		this.jedisPool = jedisPool;
	}

	/**
	 * 获取锁  如果锁可用   立即返回true,  否则返回false
	 * @author http://blog.youkuaiyun.com/java2000_wl
	 * @param billIdentify
	 * @return
	 */
	public boolean tryLock(IBillIdentify billIdentify) {
		return tryLock(billIdentify, 0L, null);
	}

	/**
	 * 锁在给定的等待时间内空闲,则获取锁成功 返回true, 否则返回false
	 * @author http://blog.youkuaiyun.com/java2000_wl
	 * @param billIdentify
	 * @param timeout
	 * @param unit
	 * @return
	 */
	public boolean tryLock(IBillIdentify billIdentify, long timeout, TimeUnit unit) {
		String key = (String) billIdentify.uniqueIdentify();
		Jedis jedis = null;
		try {
			jedis = getResource();
			long nano = System.nanoTime();
			do {
				LOGGER.debug("try lock key: " + key);
				Long i = jedis.setnx(key, key);
				if (i == 1) { 
					jedis.expire(key, DEFAULT_SINGLE_EXPIRE_TIME);
					LOGGER.debug("get lock, key: " + key + " , expire in " + DEFAULT_SINGLE_EXPIRE_TIME + " seconds.");
					return Boolean.TRUE;
				} else { // 存在锁
					if (LOGGER.isDebugEnabled()) {
						String desc = jedis.get(key);
						LOGGER.debug("key: " + key + " locked by another business:" + desc);
					}
				}
				if (timeout == 0) {
					break;
				}
				Thread.sleep(300);
			} while ((System.nanoTime() - nano) < unit.toNanos(timeout));
			return Boolean.FALSE;
		} catch (JedisConnectionException je) {
			LOGGER.error(je.getMessage(), je);
			returnBrokenResource(jedis);
		} catch (Exception e) {
			LOGGER.error(e.getMessage(), e);
		} finally {
			returnResource(jedis);
		}
		return Boolean.FALSE;
	}

	/**
	 * 如果锁空闲立即返回   获取失败 一直等待
	 * @author http://blog.youkuaiyun.com/java2000_wl
	 * @param billIdentify
	 */
	public void lock(IBillIdentify billIdentify) {
		String key = (String) billIdentify.uniqueIdentify();
		Jedis jedis = null;
		try {
			jedis = getResource();
			do {
				LOGGER.debug("lock key: " + key);
				Long i = jedis.setnx(key, key);
				if (i == 1) { 
					jedis.expire(key, DEFAULT_SINGLE_EXPIRE_TIME);
					LOGGER.debug("get lock, key: " + key + " , expire in " + DEFAULT_SINGLE_EXPIRE_TIME + " seconds.");
					return;
				} else {
					if (LOGGER.isDebugEnabled()) {
						String desc = jedis.get(key);
						LOGGER.debug("key: " + key + " locked by another business:" + desc);
					}
				}
				Thread.sleep(300); 
			} while (true);
		} catch (JedisConnectionException je) {
			LOGGER.error(je.getMessage(), je);
			returnBrokenResource(jedis);
		} catch (Exception e) {
			LOGGER.error(e.getMessage(), e);
		} finally {
			returnResource(jedis);
		}
	}

	/**
	 * 释放锁
	 * @author http://blog.youkuaiyun.com/java2000_wl
	 * @param billIdentify
	 */
	public void unLock(IBillIdentify billIdentify) {
		List<IBillIdentify> list = new ArrayList<IBillIdentify>();
		list.add(billIdentify);
		unLock(list);
	}

	/**
	 * 批量获取锁  如果全部获取   立即返回true, 部分获取失败 返回false
	 * @author http://blog.youkuaiyun.com/java2000_wl
	 * @date 2013-7-22 下午10:27:44
	 * @param billIdentifyList
	 * @return
	 */
	public boolean tryLock(List<IBillIdentify> billIdentifyList) {
		return tryLock(billIdentifyList, 0L, null);
	}
	
	/**
	 * 锁在给定的等待时间内空闲,则获取锁成功 返回true, 否则返回false
	 * @author http://blog.youkuaiyun.com/java2000_wl
	 * @param billIdentifyList
	 * @param timeout
	 * @param unit
	 * @return
	 */
	public boolean tryLock(List<IBillIdentify> billIdentifyList, long timeout, TimeUnit unit) {
		Jedis jedis = null;
		try {
			List<String> needLocking = new CopyOnWriteArrayList<String>();	
			List<String> locked = new CopyOnWriteArrayList<String>();	
			jedis = getResource();
			long nano = System.nanoTime();
			do {
				// 构建pipeline,批量提交
				Pipeline pipeline = jedis.pipelined();
				for (IBillIdentify identify : billIdentifyList) {
					String key = (String) identify.uniqueIdentify();
					needLocking.add(key);
					pipeline.setnx(key, key);
				}
				LOGGER.debug("try lock keys: " + needLocking);
				// 提交redis执行计数
				List<Object> results = pipeline.syncAndReturnAll();
				for (int i = 0; i < results.size(); ++i) {
					Long result = (Long) results.get(i);
					String key = needLocking.get(i);
					if (result == 1) {	// setnx成功,获得锁
						jedis.expire(key, DEFAULT_BATCH_EXPIRE_TIME);
						locked.add(key);
					} 
				}
				needLocking.removeAll(locked);	// 已锁定资源去除
				
				if (CollectionUtils.isEmpty(needLocking)) {
					return true;
				} else {	
					// 部分资源未能锁住
					LOGGER.debug("keys: " + needLocking + " locked by another business:");
				}
				
				if (timeout == 0) {	
					break;
				}
				Thread.sleep(500);	
			} while ((System.nanoTime() - nano) < unit.toNanos(timeout));

			// 得不到锁,释放锁定的部分对象,并返回失败
			if (!CollectionUtils.isEmpty(locked)) {
				jedis.del(locked.toArray(new String[0]));
			}
			return false;
		} catch (JedisConnectionException je) {
			LOGGER.error(je.getMessage(), je);
			returnBrokenResource(jedis);
		} catch (Exception e) {
			LOGGER.error(e.getMessage(), e);
		} finally {
			returnResource(jedis);
		}
		return true;
	}

	/**
	 * 批量释放锁
	 * @author http://blog.youkuaiyun.com/java2000_wl
	 * @param billIdentifyList
	 */
	public void unLock(List<IBillIdentify> billIdentifyList) {
		List<String> keys = new CopyOnWriteArrayList<String>();
		for (IBillIdentify identify : billIdentifyList) {
			String key = (String) identify.uniqueIdentify();
			keys.add(key);
		}
		Jedis jedis = null;
		try {
			jedis = getResource();
			jedis.del(keys.toArray(new String[0]));
			LOGGER.debug("release lock, keys :" + keys);
		} catch (JedisConnectionException je) {
			LOGGER.error(je.getMessage(), je);
			returnBrokenResource(jedis);
		} catch (Exception e) {
			LOGGER.error(e.getMessage(), e);
		} finally {
			returnResource(jedis);
		}
	}
	
	/**
	 * @author http://blog.youkuaiyun.com/java2000_wl
	 * @date 2013-7-22 下午9:33:45
	 * @return
	 */
	private Jedis getResource() {
		return jedisPool.getResource();
	}
	
	/**
	 * 销毁连接
	 * @author http://blog.youkuaiyun.com/java2000_wl
	 * @param jedis
	 */
	private void returnBrokenResource(Jedis jedis) {
		if (jedis == null) {
			return;
		}
		try {
			//容错
			jedisPool.returnBrokenResource(jedis);
		} catch (Exception e) {
			LOGGER.error(e.getMessage(), e);
		}
	}
	
	/**
	 * @author http://blog.youkuaiyun.com/java2000_wl
	 * @param jedis
	 */
	private void returnResource(Jedis jedis) {
		if (jedis == null) {
			return;
		}
		try {
			jedisPool.returnResource(jedis);
		} catch (Exception e) {
			LOGGER.error(e.getMessage(), e);
		}
	}

Visual Studio 2015 插件开发 从入门到放弃(一) 必需知识:C#和Visual Studio (1)安装 Visual Studio 2015 的时候选择 Visual Studio 扩展性工具(Visual Studio Extensibility Tools)。对于已经安装好 Visual Studio 2015 的小伙伴,可以找VS2015的安装包,或者在程序与功能中找VS2015双击,在VS2015界面中选择 修改,再选择 阅读详情

相关推荐

量化爬虫第一步:手把手教你搞定同花顺问财的hexin-v参数(附JS逆向实战)

本文详细介绍了如何通过JS逆向技术破解同花顺问财数据接口的核心加密参数hexin-v,构建稳定可靠的量化数据采集方案。从抓包分析到Cookie Hook技术应用,再到环境补全与参数生成实现,手把手教你完成量化爬虫的第一步。文章还提供了实战注意事项与优化建议,帮助开发者规避常见问题。

weixin_42620202的博客 304

什么是分布式锁?几种分布式锁分别是怎么实现的?

一、什么是分布式锁: 1、什么是分布式锁: 分布式锁,即分布式系统中的锁。在单体应用中我们通过锁解决的是控制共享资源访问的问题,而分布式锁,就是解决了分布式系统中控制共享资源访问的问题。与单体应用不同的是,分布式系统中竞争共享资源的最小粒度从线程升级成了进程。 2、分布式锁应该具备哪些条件: 在分布式系统环境下,一个方法在同一时间只能被一个机器的一个线程执行 高可用的获取锁与释放锁 高性能的获取锁与释放锁 具备可重入特性(可理解为重新进入,由多于一个任务并发使用,而

weixin_74412978的博客 6294

NVIDIA 2025 Board Design Engineer 校招笔试全解析:从基础门电路到理想放大器设计

本文详细解析了NVIDIA 2025届板级设计工程师校招笔试的核心考点与解题策略。内容涵盖从基础门电路、CMOS实现NOR门,到开关电源CCM/DCM模式波形分析与效率计算,以及理想运放电路设计与稳定性优化。旨在帮助考生构建硬件知识体系,掌握工程思维,顺利通过NVIDIA Board Design Engineer校招笔试。

weixin_29172201的博客 195

分布式锁Redisson详解(重点)

一、为什么需要分布式锁? 在单体web应用的时候,如果多个线程要访问共享资源的时候,我们通常线程间加锁的机制,在某一个时刻,只有一个线程可以对这个资源进行操作,其他线程需要等待锁的释放,Java中也有一些处理锁的机制,比如synchronized。 而到了分布式的环境中,当某个资源可以被多个系统访问使用到的时候,为了保证大家访问这个数据是一致性的,那么就要求再同一个时刻,只能被一个系统使用,这时候线程之间的锁机制就无法起到作用了,因为分布式环境中,系统是会部署到不同的机器上面的,那么就需要【

Java后端技术栈 8404

用Multisim仿真AD630锁定放大器:从2012年电赛A题实战到避坑指南

本文详细介绍了如何使用Multisim仿真AD630锁定放大器,从2012年电赛A题实战出发,提供完整的电路搭建、参数优化及避坑指南。重点解析AD630的开关调制架构和双相位检测的工程实现,帮助读者在强噪声背景下有效提取微弱信号,提升电子设计竞赛和工程实践中的信号处理能力。

weixin_42549451的博客 203

软件测试方法——等价类划分法详解

!如果下面这些资料用得到的话可以直接拿走:1、自学开发或者测试必备的完整项目源码与环境2、测试工作中所有模板(测试计划、测试用例、测试报告等)3、软件测试经典面试题4、Python/Java自动化测试实战.pdf5、Jmeter/postman接口测试全套视频获取6、Python学习路线图。

MXB1220的博客 1万+

Redis分布式锁实现原理

Redis实现分布式锁原理以及Redisson源码分析

leofee的博客 7574

MySQL下载和安装教程

1.下载MySQL数据库可以访问官方网站:https://www.mysql.com/ 2.点击DOWNLOADS模块下的Community模块下的MySQL Community Server进行下载。 由于目前最新版本是:MySQL Community Server 5.7.21 建议博友下载历史版本,本博下载的是5.6.39 下载步骤: 进入,选择MySQL的版本及主机 根据自己的电脑选择相应的位数进行下载,本机是64位,点击download。 进入下.

残雪的剑的博客 4万+

如何用Redis实现分布式锁

为什么需要分布式锁 在聊分布式锁之前,有必要先解释一下,为什么需要分布式锁。 与分布式锁相对就的是单机锁,我们在写多线程程序时,避免同时操作一个共享变量产生数据问题,通常会使用一把锁来互斥以保证共享变量的正确性,其使用范围是在同一个进程中。如果换做是多个进程,需要同时操作一个共享资源,如何互斥呢?现在的业务应用通常是微服务架构,这也意味着一个应用会部署多个进程,多个进程如果需要修改MySQL中的同一行记录,为了避免操作乱序导致脏数据,此时就需要引入分布式锁了。 想要实现分布式锁,必须借助一个外部系统,所有

Hopefully Sky的博客 4万+

全网首发--Unet3+改进16:在不同位置添加RepLKBlock超大卷积核

本文提出了一种基于大核卷积的神经网络架构RepLKNet,旨在缩小CNN与ViTs之间的性能差距。通过重新审视CNN中的大核设计,研究证明使用少量大卷积核替代多个小核能获得更强大的性能。提出的RepLKNet采用31×31大卷积核,在ImageNet和下游任务上取得了与SwinTransformer相当或更好的结果,同时具有更低延迟。文章详细介绍了实现步骤:(1)创建RepLKBlock模块文件;(2)在模型层中添加注意力机制;(3)在UNet模型中集成RepLKBlock;(4)完成训练流程。该方法展现了

AIcurator的博客 621

Qt 国产嵌入式操作系统实现文字转语音功能(ekho库)

Qt 国产嵌入式操作系统实现文字转语音功能(TTS)_tts驱动 转文字-优快云博客在继上篇文章之后,甲方粑粑不满意使用eSpeak发出的声音太难听了,这就不得不找个替代品,声音稍微好听了一些。使用ekho开源库。Ekho(余音)是一个免费、开源的中文语音合成软件。它目前支持粤语、普通话(国语)、诏安客语、藏语、雅言(中国古代通用语)和韩语(试验中),英文则通过Festival间接实现。Ekho支持Linux、Windows和Android平台。

希望能帮助大家,希望大家多多支持,你们的支持是我前进的动力。 2754

redis实现分布式锁的原理

redis实现分布式锁,从原理的实现,干货满满~~~

LYQ20010417的博客 1万+

走向审计4.0:内部审计数字化转型的路径与方法

企业的内部审计人员可以以数字化为手段,建立内部审计新生态,在数字化过程中引进战略审计、服务审计、开放审计、敏捷审计、数字审计、智慧审计等理念、方法和工具,完成数智生态审计转型。内部审计的审计对象远比国家审计和公众审计丰富和多元化,理论上企业经营管理和日常操作的各个方面都可以成为内部审计的对象,此外还可以开展独立咨询活动。由于内部审计的数字化或数字化的内部审计是实现审计数字化转型的必要条件,是实现“数字引领、数据强审”目标的核心手段,因此企业内部审计部门势必要投入足够的资金和人才来打造一支数字化审计新队伍。

一键难忘的博客 6737

redis 分布式锁实现

分布式锁

weixin_44550507的博客 2054

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

Redis 实现分布式锁

本文主要介绍了Redis的分布式锁。涉及Reids的原子操作,分布式锁,Redis的事务,以及用Go语言实现通过Lua脚本来扣减库存。

tatasix的博客 1826

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

redis实现分布式锁_Redis分布式锁的实现

前言分布式锁一般有三种实现方式:1. 数据库乐观锁;2. 基于Redis的分布式锁;3. 基于ZooKeeper的分布式锁。本文将介绍第二种方式,基于Redis实现分布式锁。可靠性首先,为了确保分布式锁可用,我们至少要确保锁的实现同时满足以下四个条件:互斥性。在任意时刻,只有一个客户端能持有锁。不会发生死锁。即使有一个客户端在持有锁的期间崩溃而没有主动解锁,也能保证后续其他客户端能加锁。具有容错性...

weixin_39647180的博客 176

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

基于Redis实现的分布式锁

利用set nx ex获取锁,并设置过期时间,保存线程标示释放锁时先判断线程标示是否与自己一致,一致则删除锁特性:利用set nx满足互斥性利用set ex保证故障时锁依然能释放,避免死锁,提高安全性利用Redis集群保证高可用和高并发特性。

Achooyo的博客 2315

Redis分布式锁实现

如果负责储存这个分布式锁的Redisson节点宕机以后,而且这个锁正好处于锁住的状态时,这个锁会出现锁死的状态。为了避免这种情况的发生,Redisson内部提供了一个监控锁的看门狗,它的作用是在Redisson实例被关闭前,不断的延长锁的有效期。默认情况下,看门狗的检查锁的超时时间是30秒钟,也可以通过修改Config.lockWatchdogTimeout来另行指定。另外Redisson还通过加锁的方法提供了leaseTime的参数来指定加锁的时间。超过这个时间后锁便自动解开了。

учёба 2414

分布式锁的作用及实现(Redis)

一、什么是分布式锁?要介绍分布式锁,首先要提到与分布式锁相对应的是线程锁、进程锁。线程锁:主要用来给方法、代码块加锁。当某个方法或代码使用锁,在同一时刻仅有一个线程执行该方法或该代码段。线程锁只在同一JVM中有效果,因为线程锁的实现在根本上是依靠线程之间共享内存实现的,比如synchronized是共享对象头,显示锁Lock是共享某个变量(state)。进程锁:为了控制同一操作系统中多个进程访问某...

LiQiyao的博客 8万+
上一篇: Zookeeper(八)分布式队列
下一篇: 短网址(ShortUrl)实现
胸口碎大石_
博客等级 码龄17年 1154粉丝 82原创
评论 19
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值