流水号的生成(日期+业务码+自增序列)

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

id int unsigned primary key auto_increment,

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

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

比如20150101**99**0000000001。

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

主要代码如下:

public interface SerialNumberService {
    /**
     * 序列号自增序列
     */
    String SERIAL_NUMBER = "serial.number:";

    /**
     * 根据两位业务码字符串,生成一个流水号,格式按照:
* 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接口,可以使用Jedis客户端来实现。

public interface RedisDao {
    String get(String key);

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

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

个人博客: bingtel-木犹如此的博客, 有兴趣可以关注下

你可能感兴趣的:(Redis,开发)