取号器设计

该博客探讨了一种确保商品编码全局唯一且无序的方法,包括由生成器、取号器和编码池组成的系统设计。生成器在编码池低于阈值时生成新的编码,取号器利用Redis的单线程特性解决高并发下的取号问题,同时通过乐观锁在MySQL中处理并发控制。此外,还提出了定时或按需生成编码的策略调整。
摘要由CSDN通过智能技术生成

背景

新建商品时,每个商品需要有商品编码,有以下要求

1.8位无序的编码(编码比较敏感,不能被外部猜测到平台的商品数量);

2.全局唯一,不可重复;

方案

  

由三部分组成,分别是“生成器”,“取号器”,"编码池"。"生成器"定时定量生成唯一编码放到"编码池",由“取号器”从"编码池"获取唯一编码,"编码池"的数量随着商品的创建会越来越少,

,我们采用每天一次检查,如果检查到当前"编码池"的可用编码低于阈值(10W)时,再重新申请新的号段生成100W编码。

8位 无序编码有两部分组成:号段+随机数。号段:2位,随机数:6位。也就是说一次性会生成100W的编码

 

"预生成的编码池"

 

"已使用的号段表"


这里涉及几个问题:

1.如何保证"编码池"的编码是全局唯一且无序的;

2."定时定量"如何评估;

3."取号器"需要保证高并发场景下的多线程竞争取号问题;

 

解释下第1个步骤:生成器首先要申请可用的号段。怎么申请?排除“已使用的号段”表中数据,随机生成一个两位数的号段。

步骤2:号段+随机数 保存到redis中,并且把“号段”持久化到Mysql中,记录哪些号段已被使用了。直到“编码池”的数据小于阈值,重复1,2步骤

这就解决了第一个问题,保证全局唯一,并且无序。

关于问题2,不是本文讨论的重点,这里一次性生成多少编码,阈值该定义多少,到时根据系统实际流量做调整。

“定时定量”也可以换种方式,由"取号"的时候来实时判断,当低于阈值时,新起一个线程生成新的一批编码丢到"编码池"。

问题3:每次取号成功后该号就从"编码池"删除。利用Redis单线程优势,可有效避免多线程并发取号问题,确保取到的号都是唯一的

 

如果对并发没有要求,可以把“编码池”放到Mysql中,利用乐观锁控制多线程并发问题

   public String getCodFromPool(Integer type){
        if(type==null){
            throw new ServiceException( ResultCode.PARAM_IS_INVALID );
        }
        int loopCount = 0;
        int maxLoopCount = 50;

        while(true){
            log.info( "循环开始:获取编码,次数:{}", loopCount);
            loopCount++;
            BasPreCodeInfo basPreCodeInfo =  basPreCodeInfoMapper.selectCode(type);
            if(basPreCodeInfo == null){
                throw new ServiceException( ProductResultCode.OCR_MPU_CODE_EMPTY_ERROR );
            }
            int count = basPreCodeInfoMapper.deleteById(basPreCodeInfo.getId()  );
            //乐观锁,如果删除记录为0说明code已被使用了
            if(count==1){
                log.info( "循环结束:获取编码:{},次数:{}", basPreCodeInfo,loopCount);
                return basPreCodeInfo.getPreCode();
            }
            try {
                Thread.sleep( 100 );
            } catch ( InterruptedException e ) {
                e.printStackTrace();
            }
            if(loopCount==maxLoopCount){
                log.error( "========获取编码超过次数==========");
                throw new ServiceException( ResultCode.SERVER_ERROR );
            }
        }

    }

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值