做项目时遇到一个功能,需要3步,1)通过solr取一个已审核数,然后和可通过数进行比较 2)更新数据库审核状态 3)更新solr已审核数 ,这时遇到一个问题,就是当用户进行批量审核的时候,这时比如有10个品被审核,那这10个请求可能会被同时打到10个机器上,然后同时执行上段代码(1,2,3步),这时就有可能出现高并发的问题,比如现在已经审核了9个商品,然后最多审核10个,两个请求同时进来,第一个请求读取到的是9,然后开始执行2和3步,结果还没执行完3,第二个请求就进来了,这时他读到的也是9(由于还没重刷solr),所以就会导致多审核了一个商品。
由于是多台机器并发问题,所以不能只用Synchroinzed这种,故这里采用分布式锁方式。
String lockKey = null; if(RoutineType.SEC_KILL.isEqual(activity.getRoutineType())){ //秒杀频道 CheckGroup group = routineCheckGroupService.getCheckGroupByErpPin(activity.getChannelID(),erpPin); if(group!=null && pageView.getRoleType()!=1 && routineCheckGroupService.isLeafCheckGroupUser(group.getId())){ //如果是末级审核组,roleType=1为运营审核 lockKey = this.acquireCheckLock(group.getId(), applyWare.getBatchId()); int allCanAssign = queryAssignedBatchResourceCount(group.getId(), applyWare.getBatchId());//查询审核组在当前批次上已分配到的资源数 int hasPassed = checkActivityService.queryHasPassedNum(Arrays.asList(group.getId()), applyWare.getBatchId()); LogTypeEnum.ROUTINE_CHECK_RECOMMEND.warn("passApply hasPassed:{}, allCanAssign:{}", hasPassed, allCanAssign); if(hasPassed + 1 > allCanAssign){ result.setSuccess(false); result.setResultCode("当前批次可审核通过"+ allCanAssign +"条,已审核通过" + hasPassed + "条,通过数量超过最大限制!"); return result; } } } this.releaseCheckLock(lockKey);//释放分布式锁
/** * 获得审核操作时的分布式锁 */ private String acquireCheckLock(final Long checkGroupId, final Long batchId) { String lockKey = "Check_Lock_" + checkGroupId + "_" + batchId; int tryTimes = 0; while(true) { //如果没获得锁,会一直循环,直到超过60次 int lockSeconds = 120;//120秒后过期, 在业务执行完成后会主动删除锁 if (redisClient.setnx(lockKey, "1") > 0) {//锁不存在,则获取锁成功 redisClient.expire(lockKey, lockSeconds); LogTypeEnum.ROUTINE_CHECK_RECOMMEND.warn("审核操作获得锁lockKey:{}, tryTimes:{}", lockKey, tryTimes); break; } tryTimes ++; try { if (redisClient.ttl(lockKey) < 0) {//防止上一操作加锁成功,但设置过期语句执行失败; [当 key 存在但没有设置剩余生存时间时,返回 -1] redisClient.expire(lockKey, 1);//迅速过期 } LogTypeEnum.ROUTINE_CHECK_RECOMMEND.warn("审核操作没有获得锁 lockKey:{}, tryTimes:{}", lockKey, tryTimes); Thread.sleep(2000);//休眠 2 秒 } catch (InterruptedException e) { } if (tryTimes > 60) { throw new RuntimeException("审核操作等待超时!"); } } return lockKey; }
/** * 释放审核操作时获得的分布式锁 */ private void releaseCheckLock(final String checkLock) { if (checkLock != null) { redisClient.del(checkLock); } }
相关推荐
Redis分布式锁实现Redisson 15问.doc
使用命令介绍: SETNX SETNX key val 当且仅当key不存在时,set一个key为val的字符串,返回1;...为key设置一个超时时间,单位为second,超过这个时间锁会自动释放,避免死锁。 delete delete key 删除key
redis分布式锁的工具类,采用的是Lua代码的方式,保证了Java执行方法的原子性。
redis分布式锁实现抢单秒杀,模拟场景,在多用户的情况下进行秒杀抢单,实现库存的变化,一级抢单返回状态。
现在很多项目单机版已经不满足了,分布式变得越受欢迎,同时也带来很多问题,分布式锁也变得没那么容易实现,分享一个redis分布式锁工具类,里面的加锁采用lua脚本(脚本比较简单,采用java代码实现,无须外部调用...
redis 分布式锁实现案例和源码解析备注 * 多线程 * 使用redis事务的方法 * 加事务 乐观锁 * watch命令监控key有没有更改 * multi命令开启事务
本资源为一步一步实现redis分布式锁的demo,利用redis实现高可用的分布式锁,规避各种坑、坑、坑!
自己封装redisson方法,同时通过注解的方式加入redis分布式事务锁,可靠。
redis实现分布式锁,自旋式加锁,lua原子性解锁
用注解实现redis分布式锁,防止短时间内重复请求,尤其对于请求耗时较长的方法,希望对大家有帮助
主要介绍了Java基于redis实现分布式锁代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
redis实现分布式锁(java/jedis),其中包含工具方法以及使用demo 本资源是利用java的jedis实现 redis实现分布式锁(java/jedis),其中包含工具方法以及使用demo 本资源是利用java的jedis实现
redlock-py, 在 python 中,Redis分布式锁 redlock - python 中的分布式锁这个 python 库实现了基于redis的分布式锁管理器算法( ) 。要创建锁定管理器:dlm = Redlock([{"host":"localhost","port":
从业务场景出发,从抽象到实现阐述了如何利用redis实现分布式锁,完成简单的秒杀功能,也记录了笔者思考的过程,希望能给阅读到本篇文章的人一些启发。
C#.net Redis分布式锁源码实现
主要介绍了Redis分布式锁的实现方式(面试常见),需要的朋友可以参考下
redis 分布式锁java 实现
Redis分布式锁在实现跨进程、跨机器的互斥访问时,虽功能强大,但也存在一些常见问题。这些问题主要源于网络延迟、系统时钟误差以及Redis自身的特性。 一个典型问题是锁的"死锁"现象,即因进程意外终止或网络故障,...
主要介绍了jedisLock—redis分布式锁实现示例代码,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧