redis【锁】

本贴最后更新于 1452 天前,其中的信息可能已经斗转星移

工具类

RedisLockHandler.java

package com.bohee.module.gl.voucher.redisCommon.lock; import com.alibaba.excel.util.CollectionUtils; import com.bohee.module.gl.voucher.entity.Voucher; import com.bohee.module.gl.voucher.redisCommon.redisUtils.JedisClientPools; import com.bohee.utils.common.LoggerUtils; import com.bohee.utils.common.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import redis.clients.jedis.Jedis; import redis.clients.jedis.JedisPool; import redis.clients.jedis.Pipeline; import redis.clients.jedis.exceptions.JedisConnectionException; import java.util.ArrayList; import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.TimeUnit; /** * @author hax redis锁实现高并发 * Created by Administrator on 2020/9/4. */ @Component public class RedisLockHandler { private static final Logger LOGGER = LoggerFactory.getLogger(RedisLockHandler.class); private static final int DEFAULT_SINGLE_EXPIRE_TIME = 3; private static final int DEFAULT_BATCH_EXPIRE_TIME = 6; private static final String LOCK_SUCCESS = "OK"; private static final String SET_IF_NOT_EXIST = "NX"; private static final String SET_WITH_EXPIRE_TIME = "PX"; @Autowired private JedisClientPools jedisClientPool; /** * 获取锁 如果锁可用 立即返回true, 否则返回false * @param billIdentify * @return */ public boolean tryLock(TSuperclass billIdentify) { return tryLock(billIdentify, 0L, null); } public void lock(TSuperclass billIdentify) { this.voidLock(billIdentify); } /** * 锁在给定的等待时间内空闲,则获取锁成功 返回true, 否则返回false * @param billIdentify * @param timeout * @param unit * @return */ public boolean tryLock(TSuperclass billIdentify, long timeout, TimeUnit unit) { String $_lockKey = (String) billIdentify.getTSuperclassKey(); try { String $_lockValue= StringUtils.uuid(); long nano = System.nanoTime(); do { LOGGER.debug("try lock key: " + $_lockKey); Long i = jedisClientPool.setnx($_lockKey, $_lockValue); if (i == 1) { jedisClientPool.expire($_lockKey, DEFAULT_SINGLE_EXPIRE_TIME); LOGGER.debug("get lock, key: " + $_lockKey + " , expire in " + DEFAULT_SINGLE_EXPIRE_TIME + " seconds."); return Boolean.TRUE; } else { // 存在锁 if (LOGGER.isDebugEnabled()) { String desc = jedisClientPool.get($_lockKey); LOGGER.debug("key: " + $_lockKey + " 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(jedisClientPool.getJedis()); } catch (Exception e) { LOGGER.error(e.getMessage(), e); } finally { returnResource(jedisClientPool.getJedis()); } return Boolean.FALSE; } /** * 如果锁空闲立即返回 获取失败 一直等待 * @param billIdentify */ public void voidLock(TSuperclass billIdentify) { String key = (String) billIdentify.getTSuperclassKey(); try { do { LOGGER.info("lock key: " + key); Long i = jedisClientPool.setnx(key, key); if (i == 1) { jedisClientPool.expire(key, DEFAULT_SINGLE_EXPIRE_TIME); LOGGER.info("get lock, key: " + key + " , expire in " + DEFAULT_SINGLE_EXPIRE_TIME + " seconds."); return; } else { if (LOGGER.isDebugEnabled()) { String desc = jedisClientPool.get(key); LOGGER.info("key: " + key + " locked by another business:" + desc); } } Thread.sleep(300); } while (true); } catch (JedisConnectionException je) { LOGGER.error(je.getMessage(), je); returnBrokenResource(jedisClientPool.getJedis()); } catch (Exception e) { LOGGER.error(e.getMessage(), e); } finally { returnResource(jedisClientPool.getJedis()); } } /** * 释放锁 * @param billIdentify */ public void unLock(TSuperclass billIdentify) { List<TSuperclass> list = new ArrayList<TSuperclass>(); list.add(billIdentify); unLock(list); } /** * 获取所有的锁数据 * @param ids * @return */ public List<TSuperclass> queryLocks(List<String> ids) { List<TSuperclass> list=new ArrayList<>(); ids.forEach(id->{ list.add(TSuperclass.getVoucher(id)); }); return list; } /** * 一键释放锁 * @param ids * @return */ public boolean unLocks(List<String> ids) { List<TSuperclass> list = this.queryLocks(ids); boolean lock = this.tryLock(list); return lock; } /** * 批量获取锁 如果全部获取 立即返回true, 部分获取失败 返回false * @param billIdentifyList * @return */ public boolean tryLock(List<TSuperclass> billIdentifyList) { return tryLock(billIdentifyList, 0L, null); } /** * 锁在给定的等待时间内空闲,则获取锁成功 返回true, 否则返回false * @param billIdentifyList * @param timeout * @param unit * @return */ public boolean tryLock(List<TSuperclass> billIdentifyList, long timeout, TimeUnit unit) { try { List<String> needLocking = new CopyOnWriteArrayList<String>(); List<String> locked = new CopyOnWriteArrayList<String>(); long nano = System.nanoTime(); do { // 构建pipeline,批量提交 Pipeline pipeline = jedisClientPool.getJedis().pipelined(); for (TSuperclass identify : billIdentifyList) { String key = (String) identify.getTSuperclassKey(); 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成功,获得锁 jedisClientPool.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)) { jedisClientPool.delbath(locked.toArray(new String[0])); } return false; } catch (JedisConnectionException je) { LOGGER.error(je.getMessage(), je); returnBrokenResource(jedisClientPool.getJedis()); } catch (Exception e) { LOGGER.error(e.getMessage(), e); } finally { returnResource(jedisClientPool.getJedis()); } return true; } /** * 批量释放锁 * @param billIdentifyList */ public void unLock(List<TSuperclass> billIdentifyList) { List<String> keys = new CopyOnWriteArrayList<String>(); for (TSuperclass identify : billIdentifyList) { String key = (String) identify.getTSuperclassKey(); keys.add(key); } try { jedisClientPool.delbath(keys.toArray(new String[0])); LOGGER.debug("release lock, keys :" + keys); } catch (JedisConnectionException je) { LOGGER.error(je.getMessage(), je); returnBrokenResource(jedisClientPool.getJedis()); } catch (Exception e) { LOGGER.error(e.getMessage(), e); } finally { returnResource(jedisClientPool.getJedis()); } } /** * 销毁连接 * @param jedis */ private void returnBrokenResource(Jedis jedis) { if (jedis == null) { return; } try { //容错 jedisClientPool.getJedisPool().returnBrokenResource(jedis); } catch (Exception e) { LOGGER.error(e.getMessage(), e); } } /** * @param jedis */ private void returnResource(Jedis jedis) { if (jedis == null) { return; } try { jedisClientPool.getJedisPool().returnResource(jedis); } catch (Exception e) { LOGGER.error(e.getMessage(), e); } } }

持续更新中..........

  • Java

    Java 是一种可以撰写跨平台应用软件的面向对象的程序设计语言,是由 Sun Microsystems 公司于 1995 年 5 月推出的。Java 技术具有卓越的通用性、高效性、平台移植性和安全性。

    3194 引用 • 8214 回帖 • 1 关注

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...

推荐标签 标签

  • 脑图

    脑图又叫思维导图,是表达发散性思维的有效图形思维工具 ,它简单却又很有效,是一种实用性的思维工具。

    31 引用 • 96 回帖
  • AngularJS

    AngularJS 诞生于 2009 年,由 Misko Hevery 等人创建,后为 Google 所收购。是一款优秀的前端 JS 框架,已经被用于 Google 的多款产品当中。AngularJS 有着诸多特性,最为核心的是:MVC、模块化、自动化双向数据绑定、语义化标签、依赖注入等。2.0 版本后已经改名为 Angular。

    12 引用 • 50 回帖 • 499 关注
  • DNSPod

    DNSPod 建立于 2006 年 3 月份,是一款免费智能 DNS 产品。 DNSPod 可以为同时有电信、网通、教育网服务器的网站提供智能的解析,让电信用户访问电信的服务器,网通的用户访问网通的服务器,教育网的用户访问教育网的服务器,达到互联互通的效果。

    6 引用 • 26 回帖 • 526 关注
  • NetBeans

    NetBeans 是一个始于 1997 年的 Xelfi 计划,本身是捷克布拉格查理大学的数学及物理学院的学生计划。此计划延伸而成立了一家公司进而发展这个商用版本的 NetBeans IDE,直到 1999 年 Sun 买下此公司。Sun 于次年(2000 年)六月将 NetBeans IDE 开源,直到现在 NetBeans 的社群依然持续增长。

    78 引用 • 102 回帖 • 701 关注
  • SendCloud

    SendCloud 由搜狐武汉研发中心孵化的项目,是致力于为开发者提供高质量的触发邮件服务的云端邮件发送平台,为开发者提供便利的 API 接口来调用服务,让邮件准确迅速到达用户收件箱并获得强大的追踪数据。

    2 引用 • 8 回帖 • 487 关注
  • Swift

    Swift 是苹果于 2014 年 WWDC(苹果开发者大会)发布的开发语言,可与 Objective-C 共同运行于 Mac OS 和 iOS 平台,用于搭建基于苹果平台的应用程序。

    36 引用 • 37 回帖 • 544 关注
  • FFmpeg

    FFmpeg 是一套可以用来记录、转换数字音频、视频,并能将其转化为流的开源计算机程序。

    23 引用 • 32 回帖
  • InfluxDB

    InfluxDB 是一个开源的没有外部依赖的时间序列数据库。适用于记录度量,事件及实时分析。

    2 引用 • 86 关注
  • Python

    Python 是一种面向对象、直译式电脑编程语言,具有近二十年的发展历史,成熟且稳定。它包含了一组完善而且容易理解的标准库,能够轻松完成很多常见的任务。它的语法简捷和清晰,尽量使用无异义的英语单词,与其它大多数程序设计语言使用大括号不一样,它使用缩进来定义语句块。

    556 引用 • 674 回帖
  • golang

    Go 语言是 Google 推出的一种全新的编程语言,可以在不损失应用程序性能的情况下降低代码的复杂性。谷歌首席软件工程师罗布派克(Rob Pike)说:我们之所以开发 Go,是因为过去 10 多年间软件开发的难度令人沮丧。Go 是谷歌 2009 发布的第二款编程语言。

    498 引用 • 1395 回帖 • 257 关注
  • 强迫症

    强迫症(OCD)属于焦虑障碍的一种类型,是一组以强迫思维和强迫行为为主要临床表现的神经精神疾病,其特点为有意识的强迫和反强迫并存,一些毫无意义、甚至违背自己意愿的想法或冲动反反复复侵入患者的日常生活。

    15 引用 • 161 回帖
  • Eclipse

    Eclipse 是一个开放源代码的、基于 Java 的可扩展开发平台。就其本身而言,它只是一个框架和一组服务,用于通过插件组件构建开发环境。

    76 引用 • 258 回帖 • 631 关注
  • 音乐

    你听到信仰的声音了么?

    61 引用 • 512 回帖
  • 小说

    小说是以刻画人物形象为中心,通过完整的故事情节和环境描写来反映社会生活的文学体裁。

    31 引用 • 108 回帖
  • ActiveMQ

    ActiveMQ 是 Apache 旗下的一款开源消息总线系统,它完整实现了 JMS 规范,是一个企业级的消息中间件。

    19 引用 • 13 回帖 • 679 关注
  • VirtualBox

    VirtualBox 是一款开源虚拟机软件,最早由德国 Innotek 公司开发,由 Sun Microsystems 公司出品的软件,使用 Qt 编写,在 Sun 被 Oracle 收购后正式更名成 Oracle VM VirtualBox。

    10 引用 • 2 回帖 • 21 关注
  • 京东

    京东是中国最大的自营式电商企业,2015 年第一季度在中国自营式 B2C 电商市场的占有率为 56.3%。2014 年 5 月,京东在美国纳斯达克证券交易所正式挂牌上市(股票代码:JD),是中国第一个成功赴美上市的大型综合型电商平台,与腾讯、百度等中国互联网巨头共同跻身全球前十大互联网公司排行榜。

    14 引用 • 102 回帖 • 319 关注
  • Kubernetes

    Kubernetes 是 Google 开源的一个容器编排引擎,它支持自动化部署、大规模可伸缩、应用容器化管理。

    116 引用 • 54 回帖 • 4 关注
  • 大数据

    大数据(big data)是指无法在一定时间范围内用常规软件工具进行捕捉、管理和处理的数据集合,是需要新处理模式才能具有更强的决策力、洞察发现力和流程优化能力的海量、高增长率和多样化的信息资产。

    93 引用 • 113 回帖
  • 倾城之链
    23 引用 • 66 回帖 • 158 关注
  • 笔记

    好记性不如烂笔头。

    311 引用 • 796 回帖
  • ReactiveX

    ReactiveX 是一个专注于异步编程与控制可观察数据(或者事件)流的 API。它组合了观察者模式,迭代器模式和函数式编程的优秀思想。

    1 引用 • 2 回帖 • 174 关注
  • 创造

    你创造的作品可能会帮助到很多人,如果是开源项目的话就更赞了!

    182 引用 • 1010 回帖
  • DevOps

    DevOps(Development 和 Operations 的组合词)是一组过程、方法与系统的统称,用于促进开发(应用程序/软件工程)、技术运营和质量保障(QA)部门之间的沟通、协作与整合。

    57 引用 • 25 回帖 • 7 关注
  • 单点登录

    单点登录(Single Sign On)是目前比较流行的企业业务整合的解决方案之一。SSO 的定义是在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统。

    9 引用 • 25 回帖 • 2 关注
  • FlowUs

    FlowUs.息流 个人及团队的新一代生产力工具。

    让复杂的信息管理更轻松、自由、充满创意。

    1 引用
  • Spring

    Spring 是一个开源框架,是于 2003 年兴起的一个轻量级的 Java 开发框架,由 Rod Johnson 在其著作《Expert One-On-One J2EE Development and Design》中阐述的部分理念和原型衍生而来。它是为了解决企业应用开发的复杂性而创建的。框架的主要优势之一就是其分层架构,分层架构允许使用者选择使用哪一个组件,同时为 JavaEE 应用程序开发提供集成的框架。

    946 引用 • 1460 回帖