zoukankan      html  css  js  c++  java
  • 流水号的生成(日期+业务码+自增序列)

    项目开发时,使用了两套数据库,开发环境和上线环境,数据库表中大多採用了自增主键,
    比方:

    id int unsigned primary key auto_increment,

    但往往会碰到一些问题。比方:
    开发环境中,使用爬虫抓取一些数据,建立索引。再把数据迁移到上线环境,会导致索引中的id和
    上线环境数据库中id对不上,所以决定使用字符串作为主键。

    那么问题来了,怎样生成唯一的序列号?
    格式依照:yyyyMMdd+两位业务码+10位的自增序列。

    比方20150101**99**0000000001。

    思路:
    获得日期非常easy;
    业务码是调用服务传入的參数;
    使用Redis来实现10位的自增序列的保存和自增,使用serial.number:{日期}的格式来保存某一天的自增序列的值;

    主要代码例如以下:

    public interface SerialNumberService {
        /**
         * 序列号自增序列
         */
        String SERIAL_NUMBER = "serial.number:";
    
        /**
         * 依据两位业务码字符串,生成一个流水号,格式依照:<br/>
         * yyyyMMdd{bizCode}{10位的自增序列号}
         * 
         * @param bizCode
         *            两位,00-99
         * @return 20位的序列号
         * @throws ServiceException
         */
        String generate(String bizCode) throws ServiceException;
    
        //事实上,应该对bizCode做白名单验证,以免恶意伪造
        default boolean isLegal(String bizCode) {
            if (bizCode == null || bizCode.length() != 2) {
                throw new RuntimeException("bizCode: " + bizCode + "异常");
            }
            if (Character.isDigit(bizCode.charAt(0))
                    && Character.isDigit(bizCode.charAt(1)))
                return true;
            return false;
        }
    }
    
    @Service
    public class SerialNumberServiceImpl implements SerialNumberService {
        @Resource
        private RedisDao redisDao;
    
        @Override
        public String generate(String bizCode) throws ServiceException {
            /** 检查业务码 */
            boolean isLegal = isLegal(bizCode);
            if (!isLegal) {
                throw new ServiceException("bizCode參数不合法");
            }
            /** 获取今天的日期:yyyyMMdd */
            String date = TimeUtil.getToday();
            /** 构造redis的key */
            String key = SERIAL_NUMBER + date;
            /** 自增 */
            long sequence = redisDao.incr(key);
            String seq = StringUtil.getSequence(sequence);
            StringBuilder sb = new StringBuilder();
            sb.append(date).append(bizCode).append(seq);
            String serial = sb.toString();
            return serial;
        }
    }
    
    public class TimeUtil {
        private TimeUtil() {
        }
    
        /**
         * 获取今日日期
         * 
         * @return
         */
        public static String getToday() {
            return "20150101";
        }
    
    }
    
    public class StringUtil {
        private StringUtil() {
    
        }
    
        static final int DEFAULT_LENGTH = 10;
    
        /**
         * 得到10位的序列号,长度不足10位,前面补0
         * 
         * @param seq
         * @return
         */
        public static String getSequence(long seq) {
            String str = String.valueOf(seq);
            int len = str.length();
            if (len >= DEFAULT_LENGTH) {// 取决于业务规模,应该不会到达10
                return str;
            }
            int rest = DEFAULT_LENGTH - len;
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < rest; i++) {
                sb.append('0');
            }
            sb.append(str);
            return sb.toString();
        }
    
    }
    
    

    仅仅声明了RedisDao接口,能够使用Jedisclient来实现。

    public interface RedisDao {
        String get(String key);
    
        /**
         * 自增,+1,返回添加后的值
         * 
         * @param key
         * @return
         */
        long incr(String key);
    }
    

    这样Redis里面就存储了每天产生的最大序列号。
    能够依据日期、业务码等统计相关信息。

  • 相关阅读:
    List of the best open source software applications
    Owin对Asp.net Web的扩展
    NSwag给api加上说明
    'workspace' in VS Code
    unable to find valid certification path to requested target
    JMeter的下载以及安装使用
    exception disappear when forgot to await an async method
    Filter execute order in asp.net web api
    记录web api的request以及response(即写log)
    asp.net web api的源码
  • 原文地址:https://www.cnblogs.com/gcczhongduan/p/5216116.html
Copyright © 2011-2022 走看看