当前位置: 首页 > news >正文

微信手机网站设计专业开发网站设计

微信手机网站设计,专业开发网站设计,网店怎么开新手,宜宾网站建设宜宾背景 对于一些内部使用的管理系统来说#xff0c;可能没有引入Redis#xff0c;又想基于现有的基础设施处理并发问题#xff0c;而数据库是每个应用都避不开的基础设施之一#xff0c;因此分享个我曾经维护过的一个系统中#xff0c;使用数据库表来实现事务锁的方式。 之…背景 对于一些内部使用的管理系统来说可能没有引入Redis又想基于现有的基础设施处理并发问题而数据库是每个应用都避不开的基础设施之一因此分享个我曾经维护过的一个系统中使用数据库表来实现事务锁的方式。 之前在文章Java业务功能并发问题处理中实现了使用MySQL行锁、Redis分布式锁来处理业务并发问题这次来填坑了如果想了解其他并发问题处理方式和区别可以看看文章Java业务功能并发问题处理哈。 业务流程说明 方案分析 适用场景 应用服务有多个实例但是数据库是单实例没有用上Redis的应用服务想通过现有的基础设施解决并发数据问题 待改进措施 设置超时机制当出现锁无法及时释放时需要手动删除表数据可以设置逻辑删除字段或者定时器删除过期数据重试获取锁机制设置一定的循环次数当获取不到锁时休眠200毫秒再次获取直到循环次数用尽后再返回失败锁重入支持通过增加加锁次数字段让当同一个线程可以重复获取锁 程序实现过程 框架及工具说明 技术框架SpringBoot、MyBatis、Maven数据库MySQL测试工具Apifox表设计及代码说明 唯一索引需要有一个用于判断唯一的字段在数据库表中通过指定唯一索引来实现加锁的线程号避免A线程加的锁被B线程删除锁的可见性要单独事务添加事务锁的逻辑应在我们执行业务逻辑的事务之前且不能跟业务逻辑的事务在一块否则在事务提交前其他线程根本看不到这个锁也就达不到我们锁的目的了为了我们的锁更方便使用也可以将加锁逻辑抽到注解中实现注解的实现流程 在pom文件中引入spring-boot-starter-aop编写自定义注解ConcurrencyLock实现切面类Aspect逻辑 代码展示 为了能让大家更关注加解锁逻辑本文只保留主要代码参考链接处会放置码云gitee的源码地址(或者点击此处跳转) 另外本文就不展示注解方式的使用了以免占用篇幅。 代码结构图 实体类 /*** 并发锁实体类*/ public class ConcurrencyLockBean {/*** 数据库主键*/private Long id;/*** 操作节点*/private String businessNode;/*** 订单唯一编号*/private String businessUniqueNo;/*** 线程ID*/private Long threadId;/*** 创建日期*/private Date creationDate; }/*** 订单实体类*/ Setter Getter ToString public class OrderInfoBean {/*** 自增长主键*/private int id;/*** 订单号*/private String orderNo;/*** 物料数量*/private Integer itemQty; }ConcurrencyLockServiceImpl.java Slf4j Service public class ConcurrencyLockServiceImpl implements ConcurrencyLockService {ConcurrencyLockMapper mapper;/*** service类注入*/AutowiredConcurrencyLockServiceImpl(ConcurrencyLockMapper mapper) {this.mapper mapper;}Overridepublic Boolean tryLock(String businessNode, String businessUniqueNo) {long threadId Thread.currentThread().getId();ConcurrencyLockBean concurrencyLock mapper.selectConcurrencyLock(businessNode, businessUniqueNo);if (concurrencyLock ! null) {log.info({}数据正在操作中请稍后, threadId);return false;}ConcurrencyLockBean lock new ConcurrencyLockBean();lock.setBusinessNode(businessNode);lock.setBusinessUniqueNo(businessUniqueNo);lock.setThreadId(threadId);try {int insertCount mapper.insertConcurrencyLock(lock);if (insertCount 0) {log.info({}获取锁失败请稍后重试, threadId);return false;}} catch (Exception e) {log.info({}获取锁异常请稍后重试, threadId);return false;}log.info({}完成锁表插入, threadId);return true;}Overridepublic void unLock(String businessNode, String businessUniqueNo) {ConcurrencyLockBean lock new ConcurrencyLockBean();long threadId Thread.currentThread().getId();lock.setThreadId(threadId);lock.setBusinessNode(businessNode);lock.setBusinessUniqueNo(businessUniqueNo);mapper.deleteConcurrencyLock(lock);log.info({}执行解锁完毕, threadId);} }ConcurrencyLockMapper.java import org.apache.ibatis.annotations.Param;public interface ConcurrencyLockMapper {/*** 根据业务节点和唯一业务号查询锁*/ConcurrencyLockBean selectConcurrencyLock(Param(businessNode) String businessNode, Param(businessUniqueNo) String businessUniqueNo);/*** 插入锁*/int insertConcurrencyLock(ConcurrencyLockBean lock);/*** 删除锁*/int deleteConcurrencyLock(ConcurrencyLockBean lock); }ConcurrencyLockMapper.xml ?xml version1.0 encodingUTF-8 ? !DOCTYPE mapper PUBLIC -//mybatis.org//DTD Mapper 3.0//EN http://mybatis.org/dtd/mybatis-3-mapper.dtd mapper namespacecom.runningrookie.mapper.ConcurrencyLockMapperselect idselectConcurrencyLock resultTypecom.runningrookie.domain.ConcurrencyLockBeanSELECTTHREAD_ID,BUSINESS_NODE,BUSINESS_UNIQUE_NO,CREATION_DATEFROM concurrency_lockWHERE BUSINESS_UNIQUE_NO #{businessUniqueNo}AND BUSINESS_NODE #{businessNode}/selectinsert idinsertConcurrencyLock useGeneratedKeystrue keyPropertyidINSERT INTO concurrency_lock (THREAD_ID,BUSINESS_NODE,BUSINESS_UNIQUE_NO,CREATION_DATE)VALUES(#{threadId}, #{businessNode}, #{businessUniqueNo}, NOW());/insertdelete iddeleteConcurrencyLockDELETE FROM concurrency_lockWHERE THREAD_ID #{threadId}and BUSINESS_NODE #{businessNode}and BUSINESS_UNIQUE_NO #{businessUniqueNo}/delete /mapperConcurrencyLock.java注解 Target({ElementType.METHOD}) Retention(RetentionPolicy.RUNTIME) Documented public interface ConcurrencyLock {String businessNode();String businessUniqueNoKey(); }ConcurrencyLockAspect.java注解类 Aspect Component Slf4j public class ConcurrencyLockAspect {ConcurrencyLockService concurrencyLockService;AutowiredConcurrencyLockAspect(ConcurrencyLockService concurrencyLockService) {this.concurrencyLockService concurrencyLockService;}// 环绕切面Around(annotation(concurrencyLock))public Object around(ProceedingJoinPoint joinPoint, ConcurrencyLock concurrencyLock) throws Throwable {long threadId Thread.currentThread().getId();Object[] args joinPoint.getArgs();if (args.length 0) {return joinPoint.proceed();}// 通过反射获取值String invokeMethodName get concurrencyLock.businessUniqueNoKey().substring(0, 1).toUpperCase() concurrencyLock.businessUniqueNoKey().substring(1);// 获取Order类的Class对象Class? clazz args[0].getClass();// 获取getOrderNo方法的Method对象Method method clazz.getMethod(invokeMethodName);// 调用getOrderNo方法并获取返回值String businessUniqueNo method.invoke(args[0]).toString();Boolean isSuccessLock concurrencyLockService.tryLock(concurrencyLock.businessNode(), businessUniqueNo);if (!isSuccessLock) {log.info({}加锁失败请稍后重试, threadId);// 生成与切点方法相同的返回对象return AjaxResult.error(加锁失败请稍后重试);}try {log.info({}开始执行业务逻辑, threadId);joinPoint.proceed();} finally {concurrencyLockService.unLock(concurrencyLock.businessNode(), businessUniqueNo);}return joinPoint.proceed();} } OrderInfoController.java RestController RequestMapping(/orderInfo) public class OrderInfoController {OrderInfoService orderInfoService;Autowiredprivate OrderInfoController(OrderInfoService orderInfoService) {this.orderInfoService orderInfoService;}PostMappingpublic AjaxResult saveOrderInfo(RequestBody OrderInfoBean bean) {return orderInfoService.saveOrderInfo(bean);} }OrderServiceImpl.java /*** 订单逻辑代码*/ Slf4j Service public class OrderInfoServiceImpl implements OrderInfoService {ConcurrencyLockService concurrencyLockService;/*** service类注入*/AutowiredOrderInfoServiceImpl(ConcurrencyLockService concurrencyLockService) {this.concurrencyLockService concurrencyLockService;}Overridepublic AjaxResult saveOrderInfo(OrderInfoBean bean) {long threadId Thread.currentThread().getId();final String businessNode 插入;Boolean isSuccessLock concurrencyLockService.tryLock(businessNode, bean.getOrderNo());if (!isSuccessLock) {return AjaxResult.error(加锁失败请稍后重试);}try {log.info({}开始执行业务逻辑, threadId);// TODO:模拟业务逻辑耗时Thread.sleep(1500);} catch (InterruptedException e) {throw new RuntimeException(e);} finally {concurrencyLockService.unLock(businessNode, bean.getOrderNo());}return AjaxResult.success();}OverrideConcurrencyLock(businessNode 插入, businessUniqueNoKey orderNo)Transactionalpublic AjaxResult saveOrderInfoByAnnotation(OrderInfoBean bean) {// TODO:模拟业务逻辑耗时Thread.sleep(1500);return AjaxResult.success();} }pom.xml相关依赖 在dependencies中添加下列依赖 dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-web/artifactId /dependency dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-aop/artifactId /dependency dependencygroupIdorg.mybatis.spring.boot/groupIdartifactIdmybatis-spring-boot-starter/artifactIdversion2.1.4/version /dependency !-- Mysql驱动包 -- dependencygroupIdmysql/groupIdartifactIdmysql-connector-java/artifactId /dependency事务处理表的表结构 CREATE TABLE concurrency_lock (ID int NOT NULL AUTO_INCREMENT COMMENT 主键,THREAD_ID int DEFAULT NULL COMMENT 线程号,BUSINESS_NODE varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT 操作节点,BUSINESS_UNIQUE_NO varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT 单据号,CREATION_DATE datetime DEFAULT NULL COMMENT 创建时间,PRIMARY KEY (ID),UNIQUE KEY uni_business_no (BUSINESS_UNIQUE_NO,BUSINESS_NODE) USING BTREE ) ENGINEInnoDB AUTO_INCREMENT1 DEFAULT CHARSETutf8mb4 COLLATEutf8mb4_general_ci;测试输出结果 使用Apifox并发发送5次请求可以看到实际成功获取到锁并执行的只有一个线程 17:08:00.449 [http-nio-8080-exec-1] c.r.service.impl.ConcurrencyLockServiceImpl - 40完成锁表插入 17:08:00.462 [http-nio-8080-exec-1] c.runningrookie.service.impl.OrderInfoServiceImpl - 40开始执行业务逻辑 17:08:00.573 [http-nio-8080-exec-5] c.r.service.impl.ConcurrencyLockServiceImpl - 44获取锁异常请稍后重试 17:08:00.573 [http-nio-8080-exec-4] c.r.service.impl.ConcurrencyLockServiceImpl - 43获取锁异常请稍后重试 17:08:00.573 [http-nio-8080-exec-3] c.r.service.impl.ConcurrencyLockServiceImpl - 42获取锁异常请稍后重试 17:08:00.573 [http-nio-8080-exec-2] c.r.service.impl.ConcurrencyLockServiceImpl - 41获取锁异常请稍后重试 17:08:00.574 [http-nio-8080-exec-1] c.r.service.impl.ConcurrencyLockServiceImpl - 40执行解锁完毕参考链接 gitee代码仓库地址数据库并发锁
http://www.dnsts.com.cn/news/202618.html

相关文章:

  • 网站网站开发建设个人网站要有什么
  • 杭州观建设计网站做网站域名优化的怎么样
  • 打开上次浏览的网站模板网络游戏开发平台
  • 百度微信网站东莞市人力资源网官网
  • 重庆做网站做得好的公司高级网站设计效果图
  • 制作触屏版网站开发传媒公司制作网站
  • 如何建设网站建设郑州手机网站建设多少钱
  • 黑色网站模版wish跨境电商平台
  • 网站开发工作总结wordpress 数据库 插件
  • 广东住房和城乡建设厅网站王芃外贸seo软件
  • 网站开发报价明细表网页设计网站欣赏
  • 做网站前端的软件成都个人做网站
  • 广州自助网站制作vue做的网站百度抓取
  • 清爽网站免费设计标志
  • 人与狗做的电影网站售后服务网站建设
  • 广州网站建设网页制作开发云南网站设计多少钱
  • 苏州网站建设官网做网站网站
  • 用jsp做的网站源代码下载做影视网站需要的软件
  • 防蚊手环移动网站建设宿迁房产网
  • 贵州省住房和城乡建设厅官网站首页wordpress选项卡分页
  • 网站建设产品编辑的工作内容自己怎么创建微信小程序
  • 网站的栏目规划做网站宣传图片
  • 网站建设中html 下载wordpress story 模板
  • 怎样在百度上做推广网站昆明网站开发的公司
  • 中英文网站后台网站空间1
  • 重庆专业网站推广怎么用网络推广业务
  • 网站怎么更改关键词wordpress添加子菜单
  • 淘宝客网站用什么软件做微站小程序
  • 西安网站制作公司哪安溪城乡建设局网站
  • 可以做投票功能的网站网站做好了如何发布