01./** 02. * @author http://blog.csdn.net/java2000_wl 03. * @version <b>1.0.0</b> 04. */ 05.public class RedisBillLockHandler implements IBatchBillLockHandler { 06. 07. private static final Logger LOGGER = LoggerFactory.getLogger(RedisBillLockHandler.class); 08. 09. private static final int DEFAULT_SINGLE_EXPIRE_TIME = 3; 10. 11. private static final int DEFAULT_BATCH_EXPIRE_TIME = 6; 12. 13. private final JedisPool jedisPool; 14. 15. /** 16. * 构造 17. * @author http://blog.csdn.net/java2000_wl 18. */ 19. public RedisBillLockHandler(JedisPool jedisPool) { 20. this.jedisPool = jedisPool; 21. } 22. 23. /** 24. * 获取锁 如果锁可用 立即返回true, 否则返回false 25. * @author http://blog.csdn.net/java2000_wl 26. * @param billIdentify 27. * @return 28. */ 29. public boolean tryLock(IBillIdentify billIdentify) { 30. return tryLock(billIdentify, 0L, null); 31. } 32. 33. /** 34. * 锁在给定的等待时间内空闲,则获取锁成功 返回true, 否则返回false 35. * @author http://blog.csdn.net/java2000_wl 36. * @param billIdentify 37. * @param timeout 38. * @param unit 39. * @return 40. */ 41. public boolean tryLock(IBillIdentify billIdentify, long timeout, TimeUnit unit) { 42. String key = (String) billIdentify.uniqueIdentify(); 43. Jedis jedis = null; 44. try { 45. jedis = getResource(); 46. long nano = System.nanoTime(); 47. do { 48. LOGGER.debug("try lock key: " + key); 49. Long i = jedis.setnx(key, key); 50. if (i == 1) { 51. jedis.expire(key, DEFAULT_SINGLE_EXPIRE_TIME); 52. LOGGER.debug("get lock, key: " + key + " , expire in " + DEFAULT_SINGLE_EXPIRE_TIME + " seconds."); 53. return Boolean.TRUE; 54. } else { // 存在锁 55. if (LOGGER.isDebugEnabled()) { 56. String desc = jedis.get(key); 57. LOGGER.debug("key: " + key + " locked by another business:" + desc); 58. } 59. } 60. if (timeout == 0) { 61. break; 62. } 63. Thread.sleep(300); 64. } while ((System.nanoTime() - nano) < unit.toNanos(timeout)); 65. return Boolean.FALSE; 66. } catch (JedisConnectionException je) { 67. LOGGER.error(je.getMessage(), je); 68. returnBrokenResource(jedis); 69. } catch (Exception e) { 70. LOGGER.error(e.getMessage(), e); 71. } finally { 72. returnResource(jedis); 73. } 74. return Boolean.FALSE; 75. } 76. 77. /** 78. * 如果锁空闲立即返回 获取失败 一直等待 79. * @author http://blog.csdn.net/java2000_wl 80. * @param billIdentify 81. */ 82. public void lock(IBillIdentify billIdentify) { 83. String key = (String) billIdentify.uniqueIdentify(); 84. Jedis jedis = null; 85. try { 86. jedis = getResource(); 87. do { 88. LOGGER.debug("lock key: " + key); 89. Long i = jedis.setnx(key, key); 90. if (i == 1) { 91. jedis.expire(key, DEFAULT_SINGLE_EXPIRE_TIME); 92. LOGGER.debug("get lock, key: " + key + " , expire in " + DEFAULT_SINGLE_EXPIRE_TIME + " seconds."); 93. return; 94. } else { 95. if (LOGGER.isDebugEnabled()) { 96. String desc = jedis.get(key); 97. LOGGER.debug("key: " + key + " locked by another business:" + desc); 98. } 99. } 100. Thread.sleep(300); 101. } while (true); 102. } catch (JedisConnectionException je) { 103. LOGGER.error(je.getMessage(), je); 104. returnBrokenResource(jedis); 105. } catch (Exception e) { 106. LOGGER.error(e.getMessage(), e); 107. } finally { 108. returnResource(jedis); 109. } 110. } 111. 112. /** 113. * 释放锁 114. * @author http://blog.csdn.net/java2000_wl 115. * @param billIdentify 116. */ 117. public void unLock(IBillIdentify billIdentify) { 118. List<IBillIdentify> list = new ArrayList<IBillIdentify>(); 119. list.add(billIdentify); 120. unLock(list); 121. } 122. 123. /** 124. * 批量获取锁 如果全部获取 立即返回true, 部分获取失败 返回false 125. * @author http://blog.csdn.net/java2000_wl 126. * @date 2013-7-22 下午10:27:44 127. * @param billIdentifyList 128. * @return 129. */ 130. public boolean tryLock(List<IBillIdentify> billIdentifyList) { 131. return tryLock(billIdentifyList, 0L, null); 132. } 133. 134. /** 135. * 锁在给定的等待时间内空闲,则获取锁成功 返回true, 否则返回false 136. * @author http://blog.csdn.net/java2000_wl 137. * @param billIdentifyList 138. * @param timeout 139. * @param unit 140. * @return 141. */ 142. public boolean tryLock(List<IBillIdentify> billIdentifyList, long timeout, TimeUnit unit) { 143. Jedis jedis = null; 144. try { 145. List<String> needLocking = new CopyOnWriteArrayList<String>(); 146. List<String> locked = new CopyOnWriteArrayList<String>(); 147. jedis = getResource(); 148. long nano = System.nanoTime(); 149. do { 150. // 构建pipeline,批量提交 151. Pipeline pipeline = jedis.pipelined(); 152. for (IBillIdentify identify : billIdentifyList) { 153. String key = (String) identify.uniqueIdentify(); 154. needLocking.add(key); 155. pipeline.setnx(key, key); 156. } 157. LOGGER.debug("try lock keys: " + needLocking); 158. // 提交redis执行计数 159. List<Object> results = pipeline.syncAndReturnAll(); 160. for (int i = 0; i < results.size(); ++i) { 161. Long result = (Long) results.get(i); 162. String key = needLocking.get(i); 163. if (result == 1) { // setnx成功,获得锁 164. jedis.expire(key, DEFAULT_BATCH_EXPIRE_TIME); 165. locked.add(key); 166. } 167. } 168. needLocking.removeAll(locked); // 已锁定资源去除 169. 170. if (CollectionUtils.isEmpty(needLocking)) { 171. return true; 172. } else { 173. // 部分资源未能锁住 174. LOGGER.debug("keys: " + needLocking + " locked by another business:"); 175. } 176. 177. if (timeout == 0) { 178. break; 179. } 180. Thread.sleep(500); 181. } while ((System.nanoTime() - nano) < unit.toNanos(timeout)); 182. 183. // 得不到锁,释放锁定的部分对象,并返回失败 184. if (!CollectionUtils.isEmpty(locked)) { 185. jedis.del(locked.toArray(new String[0])); 186. } 187. return false; 188. } catch (JedisConnectionException je) { 189. LOGGER.error(je.getMessage(), je); 190. returnBrokenResource(jedis); 191. } catch (Exception e) { 192. LOGGER.error(e.getMessage(), e); 193. } finally { 194. returnResource(jedis); 195. } 196. return true; 197. } 198. 199. /** 200. * 批量释放锁 201. * @author http://blog.csdn.net/java2000_wl 202. * @param billIdentifyList 203. */ 204. public void unLock(List<IBillIdentify> billIdentifyList) { 205. List<String> keys = new CopyOnWriteArrayList<String>(); 206. for (IBillIdentify identify : billIdentifyList) { 207. String key = (String) identify.uniqueIdentify(); 208. keys.add(key); 209. } 210. Jedis jedis = null; 211. try { 212. jedis = getResource(); 213. jedis.del(keys.toArray(new String[0])); 214. LOGGER.debug("release lock, keys :" + keys); 215. } catch (JedisConnectionException je) { 216. LOGGER.error(je.getMessage(), je); 217. returnBrokenResource(jedis); 218. } catch (Exception e) { 219. LOGGER.error(e.getMessage(), e); 220. } finally { 221. returnResource(jedis); 222. } 223. } 224. 225. /** 226. * @author http://blog.csdn.net/java2000_wl 227. * @date 2013-7-22 下午9:33:45 228. * @return 229. */ 230. private Jedis getResource() { 231. return jedisPool.getResource(); 232. } 233. 234. /** 235. * 销毁连接 236. * @author http://blog.csdn.net/java2000_wl 237. * @param jedis 238. */ 239. private void returnBrokenResource(Jedis jedis) { 240. if (jedis == null) { 241. return; 242. } 243. try { 244. //容错 245. jedisPool.returnBrokenResource(jedis); 246. } catch (Exception e) { 247. LOGGER.error(e.getMessage(), e); 248. } 249. } 250. 251. /** 252. * @author http://blog.csdn.net/java2000_wl 253. * @param jedis 254. */ 255. private void returnResource(Jedis jedis) { 256. if (jedis == null) { 257. return; 258. } 259. try { 260. jedisPool.returnResource(jedis); 261. } catch (Exception e) { 262. LOGGER.error(e.getMessage(), e); 263. } 264. }
相关推荐
Java基于Redis实现分布式锁代码实例 分布式锁的必要性 在多线程环境中,资源竞争是一个常见的问题。例如,在一个简单的用户操作中,一个线程修改用户状态,首先在内存中读取用户状态,然后在内存中进行修改,然后...
本文将深入探讨如何使用Redis实现分布式锁,以及如何利用自旋式加锁和Lua脚本实现原子性解锁。 首先,我们来理解分布式锁的基本概念。分布式锁是在多节点之间共享资源时,用于协调各个节点的访问控制机制。在分布式...
redis实现分布式锁(java/jedis),其中包含工具方法以及使用demo 本资源是利用java的jedis实现 redis实现分布式锁(java/jedis),其中包含工具方法以及使用demo 本资源是利用java的jedis实现
本文将深入探讨如何使用C++结合Redis实现分布式锁,并详细讲解Redis API在C++中的应用,以及如何处理与Boost库的集成。 首先,Redis是一个高性能的键值存储数据库,广泛用于缓存、消息队列、分布式锁等场景。分布式...
redis实现分布式锁 通过lua脚本和redisson两种方式实现分布式锁
在实际项目中,`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实现分布式锁,以及相关的核心知识点。 首先,让我们理解什么是分布式锁。分布式锁是在分布式系统中,用于协调不同节点间对共享资源访问的一种工具。它确保在任何...
Redis,作为一种高性能的NoSQL数据库,因其支持原子操作和具备高可用性,成为实现分布式锁的理想选择。 文章指出,利用Redis的SET命令来实现锁机制是实现分布式锁的一个有效途径。SET命令在Redis中用于设置键值对,...
本文将深入探讨如何使用Go语言(Golang)和Redis来实现分布式锁,并介绍其中涉及到的关键概念和实现方式,包括看门狗(Watchdog)和红锁(RedLock)策略。 **一、Redis作为分布式锁** Redis因其高性能、轻量级以及...
不过,以上代码提供了一个基本的实现思路,帮助你理解如何在SpringBoot应用中使用Redis实现分布式锁。 通过提供的Word文档,你应该能够找到更详细的配置和使用步骤。记得在实际项目中根据具体需求进行调整,确保...