热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

RedisRedisson实现分布式锁(3)—项目落地实现

有关Redisson实现分布式锁前面写了两篇博客作为该项目落地的铺垫。1、Redisson实现分布式锁(1)---原理2、Redisson实现分布式锁(2)—RedissonL

有关Redisson实现分布式锁前面写了两篇博客作为该项目落地的铺垫。

1、Redisson实现分布式锁(1)---原理

2、Redisson实现分布式锁(2)—RedissonLock

这篇讲下通过Redisson实现分布式锁的项目实现,我会把项目放到GitHub,该项目可以直接运用于实际开发中,作为分布式锁使用。

一、项目概述

1、技术架构

项目总体技术选型

SpringBoot2.1.5 + Maven3.5.4 + Redisson3.5.4 + lombok(插件)

2、加锁方式

该项目支持 自定义注解加锁 和 常规加锁 两种模式

自定义注解加锁

@DistributedLock(value="goods", leaseTime=5)
public String lockDecreaseStock(){//业务逻辑
}

常规加锁

//1、加锁
redissonLock.lock("redisson", 10);
//2、业务逻辑
//3、解锁
redissonLock.unlock("redisson");

3、Redis部署方式

该项目支持四种Redis部署方式

1、单机模式部署
2、集群模式部署
3、主从模式部署
4、哨兵模式部署

该项目已经实现支持上面四种模式,你要采用哪种只需要修改配置文件application.properties,项目代码不需要做任何修改。

4、项目整体结构

redis-distributed-lock-core # 核心实现
|
---src|---com.jincou.redisson|# 通过注解方式 实现分布式锁---annotation|# 配置类实例化RedissonLock---config|# 放置常量信息---constant|# 读取application.properties信息后,封装到实体---entity |# 支持单机、集群、主从、哨兵 代码实现---strategyredis-distributed-lock-web-test # 针对上面实现类的测试类
|
---src|---java|---com.jincou.controller|# 测试 基于注解方式实现分布式锁---AnnotatinLockController.java|# 测试 基于常规方式实现分布式锁---LockController.java---resources | # 配置端口号 连接redis信息(如果确定部署类型,那么将连接信息放到core项目中)---application.properties

 

二、测试

模拟1秒内100个线程请求接口,来测试结果是否正确。同时测试3中不同的锁:lock锁、trylock锁、注解锁。

1、lock锁

/*** 模拟这个是商品库存*/public static volatile Integer TOTAL = 10;@GetMapping("lock-decrease-stock")public String lockDecreaseStock() throws InterruptedException {redissonLock.lock("lock", 10);if (TOTAL > 0) {TOTAL--;}Thread.sleep(50);log.info("======减完库存后,当前库存===" + TOTAL);//如果该线程还持有该锁,那么释放该锁。如果该线程不持有该锁,说明该线程的锁已到过期时间,自动释放锁if (redissonLock.isHeldByCurrentThread("lock")) {redissonLock.unlock("lock");}return "=================================";}

 

压测结果

没问题,不会超卖!

2、tryLock锁

/*** 模拟这个是商品库存*/
public static volatile Integer TOTAL = 10;@GetMapping("trylock-decrease-stock")public String trylockDecreaseStock() throws InterruptedException {if (redissonLock.tryLock("trylock", 10, 5)) {if (TOTAL > 0) {TOTAL--;}Thread.sleep(50);redissonLock.unlock("trylock");log.info("====tryLock===减完库存后,当前库存===" + TOTAL);} else {log.info("[ExecutorRedisson]获取锁失败");}return "===================================";
}

测试结果

没有问题 ,不会超卖!

3、注解锁

/*** 模拟这个是商品库存*/
public static volatile Integer TOTAL = 10;@GetMapping("annotatin-lock-decrease-stock")
@DistributedLock(value="goods", leaseTime=5)
public String lockDecreaseStock() throws InterruptedException {if (TOTAL > 0) {TOTAL--;}log.info("===注解模式=== 减完库存后,当前库存===" + TOTAL);return "=================================";
}

测试结果

没有问题 ,不会超卖!

通过实验可以看出,通过这三种模式都可以实现分布式锁,然后呢?哪个最优。

三、三种锁的锁选择

观点 最完美的就是lock锁,因为

1、tryLock锁是可能会跳过减库存的操作,因为当过了等待时间还没有获取锁,就会返回false,这显然很致命!2、注解锁只能用于方法上,颗粒度太大,满足不了方法内加锁。

1、lock PK tryLock 性能的比较

模拟5秒内1000个线程分别去压测这两个接口,看报告结果!

1)lock锁

压测结果 1000个线程平均响应时间为31324。吞吐量 14.7/sec

2)tryLock锁

压测结果 1000个线程平均响应时间为28628。吞吐量 16.1/sec

这里只是单次测试,有很大的随机性。从当前环境单次测试来看,tryLock稍微高点。

2、常见异常 attempt to unlock lock, not ······

在使用RedissonLock锁时,很容易报这类异常,比如如下操作

//设置锁1秒过去
redissonLock.lock("redisson", 1);
/*** 业务逻辑需要咨询2秒*/
redissonLock.release("redisson");

上面在并发情况下就会这样

造成异常原因:

线程1 进来获得锁后,但它的业务逻辑需要执行2秒,在 线程1 执行1秒后,这个锁就自动过期了,那么这个时候
线程2 进来了获得了锁。在线程1去解锁就会抛上面这个异常(因为解锁和当前锁已经不是同一线程了)

所以我们需要注意,设置锁的过期时间不能设置太小,一定要合理,宁愿设置大点。

正对上面的异常,可以通过isHeldByCurrentThread()方法,

//如果为false就说明该线程的锁已经自动释放,无需解锁
if (redissonLock.isHeldByCurrentThread("lock")) {redissonLock.unlock("lock");
}

好了,这篇博客就到这了!

至于完整的项目地址见GitHub。

如果对您能有帮助,就给个星星吧,哈哈!

GitHub地址 https://github.com/yudiandemingzi/spring-boot-distributed-redisson

 

参考

1、自己写分布式锁--基于redission

2、Redisson实现Redis分布式锁的N种姿势

3、利用Redisson实现分布式锁及其底层原理解析

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


推荐阅读
  • 一次上线事故,30岁+的程序员踩坑经验之谈
    本文主要介绍了一位30岁+的程序员在一次上线事故中踩坑的经验之谈。文章提到了在双十一活动期间,作为一个在线医疗项目,他们进行了优惠折扣活动的升级改造。然而,在上线前的最后一天,由于大量数据请求,导致部分接口出现问题。作者通过部署两台opentsdb来解决问题,但读数据的opentsdb仍然经常假死。作者只能查询最近24小时的数据。这次事故给他带来了很多教训和经验。 ... [详细]
  • 本文整理了Java中java.lang.NoSuchMethodError.getMessage()方法的一些代码示例,展示了NoSuchMethodErr ... [详细]
  • 2018年人工智能大数据的爆发,学Java还是Python?
    本文介绍了2018年人工智能大数据的爆发以及学习Java和Python的相关知识。在人工智能和大数据时代,Java和Python这两门编程语言都很优秀且火爆。选择学习哪门语言要根据个人兴趣爱好来决定。Python是一门拥有简洁语法的高级编程语言,容易上手。其特色之一是强制使用空白符作为语句缩进,使得新手可以快速上手。目前,Python在人工智能领域有着广泛的应用。如果对Java、Python或大数据感兴趣,欢迎加入qq群458345782。 ... [详细]
  • 一、Hadoop来历Hadoop的思想来源于Google在做搜索引擎的时候出现一个很大的问题就是这么多网页我如何才能以最快的速度来搜索到,由于这个问题Google发明 ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • Google Play推出全新的应用内评价API,帮助开发者获取更多优质用户反馈。用户每天在Google Play上发表数百万条评论,这有助于开发者了解用户喜好和改进需求。开发者可以选择在适当的时间请求用户撰写评论,以获得全面而有用的反馈。全新应用内评价功能让用户无需返回应用详情页面即可发表评论,提升用户体验。 ... [详细]
  • 本文总结了初学者在使用dubbo设计架构过程中遇到的问题,并提供了相应的解决方法。问题包括传输字节流限制、分布式事务、序列化、多点部署、zk端口冲突、服务失败请求3次机制以及启动时检查。通过解决这些问题,初学者能够更好地理解和应用dubbo设计架构。 ... [详细]
  • 在Docker中,将主机目录挂载到容器中作为volume使用时,常常会遇到文件权限问题。这是因为容器内外的UID不同所导致的。本文介绍了解决这个问题的方法,包括使用gosu和suexec工具以及在Dockerfile中配置volume的权限。通过这些方法,可以避免在使用Docker时出现无写权限的情况。 ... [详细]
  • 云原生边缘计算之KubeEdge简介及功能特点
    本文介绍了云原生边缘计算中的KubeEdge系统,该系统是一个开源系统,用于将容器化应用程序编排功能扩展到Edge的主机。它基于Kubernetes构建,并为网络应用程序提供基础架构支持。同时,KubeEdge具有离线模式、基于Kubernetes的节点、群集、应用程序和设备管理、资源优化等特点。此外,KubeEdge还支持跨平台工作,在私有、公共和混合云中都可以运行。同时,KubeEdge还提供数据管理和数据分析管道引擎的支持。最后,本文还介绍了KubeEdge系统生成证书的方法。 ... [详细]
  • Android中高级面试必知必会,积累总结
    本文介绍了Android中高级面试的必知必会内容,并总结了相关经验。文章指出,如今的Android市场对开发人员的要求更高,需要更专业的人才。同时,文章还给出了针对Android岗位的职责和要求,并提供了简历突出的建议。 ... [详细]
  • 本文介绍了在Win10上安装WinPythonHadoop的详细步骤,包括安装Python环境、安装JDK8、安装pyspark、安装Hadoop和Spark、设置环境变量、下载winutils.exe等。同时提醒注意Hadoop版本与pyspark版本的一致性,并建议重启电脑以确保安装成功。 ... [详细]
  • ch3中可视化软件pangolin的安装步骤及注意事项
    本文介绍了在ch3中安装可视化软件pangolin的步骤及注意事项。首先提供了pangolin的下载地址,并说明了下载后需要放到与虚拟机交互的文件夹地址。然后详细介绍了安装pangolin所需的依赖项,并提供了在终端进行安装的命令。最后给出了解压pangolin的步骤。 ... [详细]
  • 本文介绍了Android 7的学习笔记总结,包括最新的移动架构视频、大厂安卓面试真题和项目实战源码讲义。同时还分享了开源的完整内容,并提醒读者在使用FileProvider适配时要注意不同模块的AndroidManfiest.xml中配置的xml文件名必须不同,否则会出现问题。 ... [详细]
  • 一句话解决高并发的核心原则
    本文介绍了解决高并发的核心原则,即将用户访问请求尽量往前推,避免访问CDN、静态服务器、动态服务器、数据库和存储,从而实现高性能、高并发、高可扩展的网站架构。同时提到了Google的成功案例,以及适用于千万级别PV站和亿级PV网站的架构层次。 ... [详细]
  • Sleuth+zipkin链路追踪SpringCloud微服务的解决方案
    在庞大的微服务群中,随着业务扩展,微服务个数增多,系统调用链路复杂化。Sleuth+zipkin是解决SpringCloud微服务定位和追踪的方案。通过TraceId将不同服务调用的日志串联起来,实现请求链路跟踪。通过Feign调用和Request传递TraceId,将整个调用链路的服务日志归组合并,提供定位和追踪的功能。 ... [详细]
author-avatar
乖乖88918
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有