高中信息技术网站建设,风格活泼的网站设计,网上在线注册公司,设计公司怎么找客户文章目录 锁处理目的#xff1a;考虑锁控制思路#xff1a;生命周期接口并发控制解决方案#xff1a;测试锁是否生效#xff1a;模拟多线程并发场景的2种方式#xff1a; 事务处理目的#xff1a;考虑事务控制思路#xff1a;解决方案#xff1a; 总结 锁处理
目的考虑锁控制思路生命周期接口并发控制解决方案测试锁是否生效模拟多线程并发场景的2种方式 事务处理目的考虑事务控制思路解决方案 总结 锁处理
目的
为了避免接口被并发访问导致业务数据校验是否正式已存在、是否审批中被迫通过导致创建多个流程单据去新增业务数据造成正式业务数据重复
*代表采用应用的方案。
应用分布式锁
考虑锁控制思路
1.分析并发场景相同应用、不同应用访问、给出解决方案
如客户上市接口
并发访问场景 同一外部应用系统同一个用户创建一个客户连续快速点击2次2个线程同时访问同一接口数据已在审批中代码校验被迫通过 解决办法clientID 外部应用标识 同一外部应用系统不同用户同时创建同一个客户2个线程同时访问同一接口数据已在审批中代码校验被迫通过 解决办法clientID 外部应用标识 不同外部应用同时创建相同客户标识的客户2个线程同时访问同一接口数据已在审批中代码校验被迫通过 解决办法客户唯一识别标识
2.取用最适配所有场景方案
客户上市最终方案通过客户唯一识别标识来加锁处理身份证号纳税人识别号
即能控制并发场景1、2又能控制并发场景3
生命周期接口并发控制解决方案
1. 客户上市接口并发控制 方案1粗粒度clientId控制同一外部应用并发访问缺点不能控制不同应用并发创建同一个客户时场景 方案2*细粒度不同外部应用同一个客户不能并发创建同一个客户识别标识身份证号 纳税人识别号
2. 客户变更基础变更、客户调整接口并发控制 方案1粗粒度clientId控制同一外部应用并发访问缺点不能控制不同应用并发更新同一个客户时场景 方案2*细粒度同一个客户不能并发进行基础信息变更、客户调整缺点牺牲了同一个客户实际场景中是可以同时进行基础变更、客户调整操作造成的结果就是A客户变更、B客户调整AB同时发起线程快的会先进入方法后进入的被锁住失败访问需要等待1-2s后进行访问
3. 客户扩充、冻结解冻、地址变更接口并发控制 方案1*粗粒度clientId控制外部应用并发访问缺点不能控制不同应用并发扩充、冻结解冻同一个客户时场景回调处理新增数据时先去校验扩充插入条目是否存在弥补了并发导致重复扩充同一业务范围条目这种场景 方案2细粒度由于是批量客户处理无法通过客户编码等业务字段来限制并发访问
测试锁是否生效
// 这里是对外部应用加锁控制同一应用并发访问改接口方法
Lock4j(keys {#request.clientId})
Override
public ServiceResponse testLock(ExtendsCustomerBusinessScopeTaskDto request) {System.out.println(开始处理: request.getClientId() - LocalDateTime.now());try {// 模拟处理时间Thread.sleep(2000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(处理完成: request.getClientId() - LocalDateTime.now());return ServiceResponse.success();
}/**
预期结果1如果加锁无效开始处理和结束处理之间间隔2s,但同一clientid调用时间不联系几乎是同时进行的类似这样开始处理: client001 - 2024-07-13T14:31:58.451154700处理完成: client001 - 2024-07-13T14:32:00.4599192002024-07-13 14:32:00.549 INFO 21864 ---[tag 客户端IDclient001-]开始处理: client001 - 2024-07-13T14:32:00.550816300处理完成: client001 - 2024-07-13T14:32:02.5556544002024-07-13 14:32:02.636 INFO 21864 ---[tag 客户端IDclient001-]开始处理: client001 - 2024-07-13T14:32:02.636094400处理完成: client001 - 2024-07-13T14:32:04.6392284002024-07-13 14:32:04.700 INFO 21864 ---[tag 客户端IDclient001-]开始处理: client001 - 2024-07-13T14:32:04.701772900处理完成: client001 - 2024-07-13T14:32:06.7171383002024-07-13 14:32:06.799 INFO 21864 ---[tag 客户端IDclient001-]开始处理: client001 - 2024-07-13T14:32:06.799141500处理完成: client001 - 2024-07-13T14:32:08.803225预期结果2如果加锁有效开始处理和结束处理之间间隔2s,且同一clientid调用时间是连续的类似这样开始处理: client001 - 2024-07-13T14:23:48.889049800处理完成: client001 - 2024-07-13T14:23:50.8946381002024-07-13 14:23:50.984 INFO 16064 --- [tag 客户端IDclient001-]开始处理: client001 - 2024-07-13T14:23:50.992565800处理完成: client001 - 2024-07-13T14:23:52.9942138002024-07-13 14:23:53.088 INFO 16064 --- [tag 客户端IDclient001-]开始处理: client001 - 2024-07-13T14:23:53.095387900处理完成: client001 - 2024-07-13T14:23:55.0962475002024-07-13 14:23:55.170 INFO 16064 --- [tag 客户端IDclient001-]开始处理: client001 - 2024-07-13T14:23:55.178764600处理完成: client001 - 2024-07-13T14:23:57.1841779002024-07-13 14:23:57.269 INFO 16064 --- [tag 客户端IDclient001-]开始处理: client001 - 2024-07-13T14:23:57.335996600处理完成: client001 - 2024-07-13T14:23:59.341987300实际测试结果预期结果2加锁有效
*/模拟多线程并发场景的2种方式
方式1postman多线程并发测试 方式2代码对任务多线程同时调用
// 应用启动main方法
EnableOpenApi(matrix-mdm)
EnableMatrixFeignClients
EnableDiscoveryClient
EnableMatrixResourceServer
SpringBootApplication
public class App {public static void main(String[] args) {SpringApplication.run(App.class, args);// lock4j分布式锁控制方法并发有效前提线程必须通过Spring管理的bean来访问方法否则加锁无效TnCustomerManagementService tnCustomerManagementServiceImpl (TnCustomerManagementService) SpringReflectUtils.getBean(tnCustomerManagementServiceImpl);ExtendsCustomerBusinessScopeTaskDto request new ExtendsCustomerBusinessScopeTaskDto();request.setClientId(client001);Runnable task () - tnCustomerManagementServiceImpl.customerBusinessScopeExtendsTask(request);new Thread(task).start();new Thread(task).start();new Thread(task).start();new Thread(task).start();new Thread(task).start();}
}// spring管理的bean的内部方// 请求超时时间设置为30s, 多线程并发时第一个线程拿到锁执行中第二个线程获取不到锁直接报错reqire fail, 想要看到完整5个线程并发控制后串行打印出梳理时间信息就需要放大点请求超时时间 5个并发线程处理时间总和 Lock4j(keys {#request.clientId}, acquireTimeout 30000L)Overridepublic ServiceResponse customerBusinessScopeExtendsTask(ExtendsCustomerBusinessScopeTaskDto request) {System.out.println(Thread Thread.currentThread().getName() 开始处理: request.getClientId() - LocalDateTime.now());try {// 模拟处理时间Thread.sleep(2000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(Thread Thread.currentThread().getName() 处理完成: request.getClientId() - LocalDateTime.now());return ServiceResponse.success();}事务处理
目的
为了避免多条数据库SQL操作中间异常时数据已被插入正式表但是业务已经执行不下去再次执行时就会发生数据已存在的代码校验死锁卡住。
考虑事务控制思路
多个SQL操作要么都发生要么都不发生不数据回滚导致业务重复校验死锁、业务不能操作下去
解决方案
异常回滚处理场景 扩充、地址新增 插入正式表新条目时根据数据条目唯一标识校验是否存在弥补客户扩充是批量扩充接口导致锁控制粒度只能控制在 相同应用 clientId 中不同 clientId 并发扩充同一个业务范围数据场景控制不住 如果存在原因可能历史数据已存在、锁未并发控制不同ClientId导致审批中数据代码校验失效直接抛出异常将之前可能执行的新增、更新操作回滚 这时候操作人员看到报错去检查处理异常已存在数据后检查记录被创建原因处理删除数据再次点击时业务正常进行下去 扩充、地址新增、变更 执行多条SQL操作方法时中间出现字段过长等导致插入失败时抛出异常事务回滚返回操作人员看到报错去检查处理异常放大字段后继续执行下去
总结
锁控制、事务控制、异常处理必须分析场景再采用最优处理方案 sychronized 同步锁在分布式系统中不生效需要用到分布式锁 加锁时需要考虑锁的粒度。 判断条件如果接口访问场景并发量大考虑细粒度锁控制如果接口访问场景并发量小考虑粗粒度锁控制 粗粒度锁如访问接口的外部应用 细粒度锁如具体接口业务功能数据判定客户上市身份证号、纳税人识别号来锁定唯一客户控制类似重复点击、同一时刻创建同一客户并发访问接口导致同一客户被创建审批数据 事务控制需要考虑到多SQL操作异常、业务数据重复异常时等进行回滚操作异常信息暴漏到前端方便开发运维 若有错误烦请评论指正