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里面就存储了每天产生的最大序列号。
    能够依据日期、业务码等统计相关信息。

  • 相关阅读:
    2.NET Core设定数据库种子
    1.ASP.NET Core 中向 Razor Pages 应用添加模型
    获取文件夹目录下的文件信息
    dataGridView读写文本
    C# winform 启动外部程序
    netcore访问本地磁盘
    c#利用定时器自动备份数据库(mysql)
    c#mysql数据库备份还原
    Linux之旅(二)
    Linux之旅
  • 原文地址:https://www.cnblogs.com/gcczhongduan/p/5216116.html
Copyright © 2011-2022 走看看