基于redis的规则流水号生成(一)

设计方案一:

使用redis的incr自增,由于redis是单线程的,每次按同一key自增可保证快速生成流水号,且唯一。

比如最基础的生成不重复序号:

long serilno=cacheClient.incr("CST");

incr操作在key为空时初始化为0

在实际意义中,客户号没有这种全0的。大部分可以是有部分含义的规则流水号。

比如:CST2018080200000

可考虑:CST+当天日期串+redis自增序号,其中以“CST”作为key值,后续00001调用字符串补充方法。

假设若要实现20180802从CST2018080200000生成,20180803也从CST2018080300000生成,则需要以CST+currentDate作为key值,其中currentDate字符串格式为yyyyMMdd,特别注意currentDate实际内容可能为20180802,而非“yyyyMMdd”。

附代码:

    @Override
    public String getSerialNumberByPrefix(String prefix) {
        return getSerialNumberByRules(prefix,"yyMMddHHmmss",CrlSerialNumberCodeConstant.CRL_SERIAL_NUMBER_IDC,CrlSerialNumberCodeConstant.CRL_SERIAL_NUMBER_DATABASE,CrlSerialNumberCodeConstant.CRL_SERIAL_NUMBER_NORMAL,CrlSerialNumberCodeConstant.CRL_SERIAL_NUMBER_LENGTH);
    }

    @Override
    public String getSerialNumberByPrefixAndLength(String prefix,int length) {
        return getSerialNumberByRules(prefix,"yyMMddHHmmss",CrlSerialNumberCodeConstant.CRL_SERIAL_NUMBER_IDC,CrlSerialNumberCodeConstant.CRL_SERIAL_NUMBER_DATABASE,CrlSerialNumberCodeConstant.CRL_SERIAL_NUMBER_NORMAL,length);
    }

    /**
    * @param prefix为业务前缀
    * @param dateFormatter是日期格式
    * @param normal是普通位
    * @param length是流水号最后位数
    */
    @Override
    public String getSerialNumberByForFixedLength(String prefix,String dateFormatter,String idc,String dataBase,String normal,int length) {
        String currentDate="";
        if(StringUtils.isNotBlank(dateFormatter)){
            currentDate=new SimpleDateFormat(dateFormatter).format(new Date());
        }
        StringBuilder crlSerialNumber=new StringBuilder();
        try {
            logger.info("getSerialNumberByPrefixAndLength|按业务前缀和后缀长度获取流水号|获取缓存值开始|prefix:" + prefix + "|length:" + length);
            long cacheCurrentValue = cacheClient.incr(prefix +currentDate+length);
            if(cacheCurrentValue==getMaxValueString(length)){
                logger.info("getSerialNumberByPrefixAndLength|按业务前缀和后缀长度获取流水号|缓存达到位数最大值执行清除|prefix:" + prefix + "|length:" + length+"|cacheCurrentValue:"+cacheCurrentValue);
                cacheClient.del(prefix +currentDate+ length);
            }
            String currentValue = getCurrentValueString(length, cacheCurrentValue);
            return   crlSerialNumber.append(prefix).append(currentDate).append(idc).append(dataBase).append(normal).append(currentValue).toString();
        } catch (Exception e) {
            logger.error("getSerialNumberByPrefixAndLength|按业务前缀和后缀长度获取流水号异常|prefix:"+prefix+"|length:"+length,"|exception", e);
            int i=new Random().nextInt(getMaxValueString(length));
            return crlSerialNumber.append(prefix).append(currentDate).append(idc).append(dataBase).append(String.valueOf(i)).toString();
        }
    }

    /**
     * 字符串补足方法
     * @param length
     * @param currentValue
     * @return
     */
    private  String getCurrentValueString(int length, long currentValue) {
        String cValue=String.valueOf(currentValue);
        for(int i=cValue.length();i<length;i++){
            cValue="0"+cValue;
        }
        return cValue;
    }

       /**
     * 字符串最大值
     * @param length
     * @return
     */
    private  int getMaxValueString(int length) {
        String value="";
        for(int i=0;i<length;i++){
            value="9"+value;
        }
        return Integer.parseInt(value);
    }

附:

/*利用时间戳生成唯一序号的方法参考*/
 

public static final String str_yyyyMMddHHmmsssss = "yyyyMMddHHmmssSSS";

    /**
     * 将日期格式化为字符串
     *
     * @param date    日期
     * @param pattern 格式
     * @return 格式化后的日期串
     */
    public static String date2Str(Date date, String pattern) {
        SimpleDateFormat yyyy_MM_dd = new SimpleDateFormat(pattern);
        return yyyy_MM_dd.format(date);
    }

猜你喜欢

转载自blog.csdn.net/wzh474420999/article/details/81352848