🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
## 一、概述 对应单JVM部署的应用,我们用synchronized或java.util.concurrent.locks.Lock都可以解决一段待,同时只能一个线程调用的问题,非常简单; 但如果考虑到多个组件分布式部署,这些组件分布在不同的JVM中,那么,显然用上面的办法无法解决多线程同步的问题; 平台提供了RayLocker分布锁解决方案来解决这个问题; ## 二、技术方案 ``` @Autowired private RayLocker rayLocker; ``` 分布锁示范代码: ``` String traceMethodPerIpKey = getCurrentRequestUniqueKey(joinPoint); if (rayLocker.lock(traceMethodPerIpKey)) { try { object = joinPoint.proceed(args); } finally { rayLocker.unlock(traceMethodPerIpKey); } } else { throw new RayRequestRepeatedException(); } ``` ## 三、举例 如果你需要控制某个业务的同步,比如同一个对象,不能被多个组件同时修改,那么,用RayLocker机制很容易解决;代码结构可以参考上面的情况,只需要找到合适的lockKey即可; 举例,我们需要控制对一个账号的修改。那么,主程序中,要修改账号的地方,用账号的id作为锁的key,开始处理的时候加锁,处理完也必须释放锁;如果同时,在调度服务器中,也需要修改对象,那么很简单,调度服务程序中修改账号的地方,同样用账号的id作为锁的key,开始处理的时候加锁,处理完也必须释放锁;这样,就完美的实现了在多个JVM的分布式部署程序中实现同步; ``` @Autowired private RayLocker rayLocker; @Transactional public void refresh(SysStaff staff) throws InterruptedException { String today = DateUtil.getDateStr(5); String lockKey = today + staff.getStaffId(); if (rayLocker.lock(lockKey)) { try { RsaleStaffProfitStatDaily daily = rsaleStaffProfitStatDailyDao.findByStaffIdAndProfitDate(staff.getStaffId(), today); if (daily == null) { daily = new RsaleStaffProfitStatDaily(); daily.setProfitDate(today); daily.setStaffId(staff.getStaffId()); daily.setInvitedDirectProfit(0L); daily.setInvitedTeamProfit(0L); daily.setMerchanDirectProfit(0L); daily.setMerchanTeamProfit(0L); } daily.setMerchanDirectProfit(daily.getMerchanDirectProfit() + settleMerchantDirect(staff.getStaffId(), today).longValue()); daily.setMerchanTeamProfit(daily.getMerchanTeamProfit() + settleMerchantTeam(staff.getStaffId(), today).longValue()); rsaleStaffProfitStatDailyDao.save(daily); } finally { rayLocker.unlock(lockKey); } } } ``` >[danger] 注意,多个JVM中程序控制同样对象的时候,lockKey必须一样,否则没有意义;