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

大型门户网站设计解决方案新站网站建设

大型门户网站设计解决方案,新站网站建设,上海网站建设团队,html5网站框架背景 对于一些内部使用的管理系统来说#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.hkea.cn/news/14511329/

相关文章:

  • 收录网站源码有没有网址免费的
  • 手机版企业网站设计本app
  • 佛山网站建设公司怎么做中国建设app手机银行
  • 一流的高密网站建设app推广专员好做吗
  • 建设网站公司哪里好相关的热搜问题百度新闻
  • 电商网站如何存储图片wordpress+手机端
  • 刚做的网站搜全名查不到网络广告和传统广告的区别
  • 电脑网站建设企业网站建设的目标
  • 做网站算经商吗企业建设网站方案
  • 汽车网站设计论文最新的新开传奇网站
  • 网站建设管理情况汇报聚美优品网站建设主题
  • 开发大型网站的流程wordpress和抽奖页面
  • 常熟有做网站的网络公司吗网站建设的发展历史与新方向
  • 襄阳企业网站建设整站关键词快速排名
  • 大良网站制作公司建企业网站公司
  • 网站建设 教程做企业网站的合同
  • 个人网站优秀作品网站你懂我意思正能量晚上下载
  • 安徽省建设信息网站汕头seo关键词排名
  • 网站建设有哪些环节国家企业信用查询信息系统(全国)
  • 网站设计与建设开发深圳创意设计网站
  • 手机端网站模板下载增城网站开发
  • 石家庄网站开发工程师招聘网网页前端开发框架
  • 万网网站备案证书推广图片怎么做
  • 找人做网站域名怎么过户河南省住房与城乡建设厅网站
  • 电商网站开发过程seo推广教程seo推广技巧
  • 建的网站403靖江做网站的单位
  • 企业网站怎么做毕业设计外贸推广营销公司
  • 东莞品牌网站建设报价百度hao123
  • 免费网站知乎邯郸有做网站的吗
  • 盐城中瑞做网站公司浏览器网页打不开怎么解决