`
zy116494718
  • 浏览: 476827 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

redis分布式锁实现

 
阅读更多

        做项目时遇到一个功能,需要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);
        }
    }

 

0
1
分享到:
评论

相关推荐

    Redis分布式锁实现Redisson 15问.doc

    Redis分布式锁实现Redisson 15问 Redis分布式锁是指在分布式系统中,多个服务实例之间对同一个资源加锁的机制,以保证数据的一致性和安全性。Redisson是一个基于Redis的分布式锁实现,它提供了一个高效、可靠的加锁...

    C#实操控制并发之Lock和Redis分布式锁

    以下是一个简单的C# Redis分布式锁实现: ```csharp public bool TryAcquireLock(string lockKey, int lockTimeout) { var redis = ConnectionMultiplexer.Connect("localhost:6379"); var db = redis.Get...

    redis分布式锁实现抢单秒杀

    在IT行业中,尤其是在高并发的电子商务系统中,"redis分布式锁实现抢单秒杀"是一个常见的挑战。这个场景模拟了多个用户同时参与秒杀活动,系统需要确保库存的准确性和抢单的公平性,避免超卖和数据不一致的问题。...

    redis分布式锁实现代码

    使用命令介绍: SETNX SETNX key val 当且仅当key不存在时,set一个key为val的字符串,返回1;...为key设置一个超时时间,单位为second,超过这个时间锁会自动释放,避免死锁。 delete delete key 删除key

    redis分布式锁实现类

    redis分布式锁的工具类,采用的是Lua代码的方式,保证了Java执行方法的原子性。

    redis分布式锁.zip

    Redis 的高可用性和低延迟特性使其成为实现分布式锁的理想选择。下面将详细介绍如何使用 Redis 实现分布式锁以及其中可能遇到的问题和解决方案。 首先,我们需要理解分布式锁的基本概念。分布式锁是一种在分布式...

    redis分布式锁工具类

    现在很多项目单机版已经不满足了,分布式变得越受欢迎,同时也带来很多问题,分布式锁也变得没那么容易实现,分享一个redis分布式锁工具类,里面的加锁采用lua脚本(脚本比较简单,采用java代码实现,无须外部调用...

    redis 分布式锁实现案例和源码解析备注

    redis 分布式锁实现案例和源码解析备注 * 多线程 * 使用redis事务的方法 * 加事务 乐观锁 * watch命令监控key有没有更改 * multi命令开启事务

    基于redis分布式锁实现“秒杀”

    ### 基于Redis分布式锁实现“秒杀” #### 一、引言 在现代互联网应用中,“秒杀”作为一种常见的促销手段,被广泛应用于电商领域。为了保证系统的稳定性和公平性,在高并发环境下实现秒杀功能时,合理地利用分布式...

    基于go语言的redis分布式锁实现项目资源.zip

    基于go语言的redis分布式锁实现项目资源

    springboot基于redis分布式锁

    以下是一个简单的Spring Data Redis的分布式锁实现示例: ```java import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.stereotype.Component; @Component public class...

    用Redis实现分布式锁_redis_分布式_

    二、Redis分布式锁实现 1. 锁的创建:通常使用`SETNX`命令尝试设置一个键(如`lock_key`),如果键不存在,则设置成功,表示获取到锁。同时,为了防止死锁,可以设置一个过期时间,如`EXPIRE lock_key timeout`,...

    Java基于redis实现分布式锁代码实例

    Java基于Redis实现分布式锁代码实例 分布式锁的必要性 在多线程环境中,资源竞争是一个常见的问题。例如,在一个简单的用户操作中,一个线程修改用户状态,首先在内存中读取用户状态,然后在内存中进行修改,然后...

    redis分布式锁工具包,提供纯Java方式调用,支持传统Spring工程.zip

    使用这个Redis分布式锁工具包,开发人员可以快速地在Spring项目中实现可靠的分布式锁机制,提高系统的稳定性和并发性能。 综上所述,这个压缩包提供的Redis分布式锁工具包为Java开发者提供了一种简单、高效的方法来...

    redis实现分布式锁,自旋式加锁,lua原子性解锁

    Redis中的分布式锁实现通常基于`SETNX`命令或`SET`命令的`nx`与`ex`组合。`SETNX`命令用于设置键值,但如果键已经存在,则不执行任何操作,这可以确保锁的互斥性。`SET key value EX timeout NX`则同时设置了超时...

    记录redisson实现redis分布式事务锁

    本篇文章将详细探讨如何使用Redisson实现Redis分布式事务锁,以及在Spring Boot环境中如何进行集成。 首先,Redis作为一个内存数据库,其高速读写性能使其成为实现分布式锁的理想选择。分布式锁的主要作用是在多...

    Redis分布式锁实现方式及超时问题解决

    Redis分布式锁实现方式及超时问题解决 本文主要介绍了Redis分布式锁实现方式及超时问题解决,通过详细的示例代码和实现原理,帮助读者理解分布式锁的应用场景和实现方式,并解决分布式锁常见的问题。 一、分布式锁...

    C#.net Redis分布式锁源码实现

    本篇文章将深入探讨如何在C#.NET环境下利用Redis实现分布式锁,以及相关的核心知识点。 首先,让我们理解什么是分布式锁。分布式锁是在分布式系统中,用于协调不同节点间对共享资源访问的一种工具。它确保在任何...

    C++基于redis的分布式锁redisAPI

    本文将深入探讨如何使用C++结合Redis实现分布式锁,并详细讲解Redis API在C++中的应用,以及如何处理与Boost库的集成。 首先,Redis是一个高性能的键值存储数据库,广泛用于缓存、消息队列、分布式锁等场景。分布式...

Global site tag (gtag.js) - Google Analytics