Redis生成订单号

 


 

基于SSM+Maven单号生成器:

  • 订单号:业务类型+yyyyMMddHHmmss+ 6位流水号。

业务类型为任意2个英文字母,HHmmss为redis服务器的时间,6位流水号从1开始自增。

  • KEY1:包名+业务类型+yyyyMMdd,48h过期
  • KEY2:包名+HHmmss,这里设置KEY2是为了防止宕机后
  • import java.text.SimpleDateFormat;
    import java.util.Date;
    import java.util.Locale;
    import java.util.concurrent.TimeUnit;
    
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Component;
    
    import com.xx.xx.JedisClient;
    
    /**
     * 
     * @ClassName: SerialNumberUtil
     * @Description: 发号器:业务类型+yyyyMMddHHmmss+ 6位流水号
     * @author
     * @date 2018年11月30日 下午12:42:01
     *
     */
    @Component
    public class SerialNumberUtil {
    	@Autowired
    	JedisClient jedisClient;
    
    	Logger logger = LoggerFactory.getLogger(SerialNumberUtil.class);
    
    	String value = "";
    
    	// 设置3秒过期
    	int DEFAULT_SINGLE_EXPIRE_TIME = 3;
    
    	public String createNo(String bizCode) {
    
    		// 此处代码是锁上的
    		if (this.tryLock("statusCheck")) {
    
    			String date = new SimpleDateFormat("yyyMMdd").format(new Date());
    			String pacName = getPacName();
    			String key = pacName + bizCode + date;
    
    			if (bizCode.matches("[a-zA-Z]{2}")) {
    				jedisClient.incr(key);
    				// 过期时间48小时
    				jedisClient.expire(key, 60 * 60 * 48);
    			}
    			String redisTime = getRedisTime();
    			// 获取redis服务器的时间HHmmss,防止宕机
    			String key2 = pacName + redisTime;
    
    			if (jedisClient.get(key2) == null) {
    				jedisClient.set(key2, redisTime);
    			}
    
    			value = jedisClient.get(key);
    			value = bizCode + date + jedisClient.get(key2) + autoCOS(value);
    			// unLock("statusCheck");
    		}
    		return value;
    
    	}
    
    	/**
    	 * 获取包名
    	 */
    	private String getPacName() {
    		String clzName = Thread.currentThread().getStackTrace()[1].getClassName();
    		int index = clzName.lastIndexOf(".");
    		String pacName = clzName.substring(0, index) + ":";
    		return pacName;
    	}
    
    	/**
    	 * 获取锁 如果锁可用 立即返回true, 否则立即返回false,作为非阻塞式锁使用
    	 */
    	public boolean tryLock(String key) {
    		try {
    			return tryLock(key, key, 0L, null);
    		} catch (InterruptedException e) {
    			e.printStackTrace();
    		}
    		return false;
    	}
    
    	/**
    	 * 锁在给定的等待时间内空闲,则获取锁成功 返回true, 否则返回false,作为阻塞式锁使用
    	 * 
    	 * @param key锁键
    	 * @param value被谁锁定s
    	 * @param timeout尝试获取锁时长
    	 * @param unit,建议传递TimeUnit.MILLISECONDS
    	 * @return
    	 * @throws InterruptedException
    	 */
    	public boolean tryLock(String key, String value, long timeout, TimeUnit unit) throws InterruptedException {
    		// 纳秒
    		long begin = System.nanoTime();
    		do {
    			// LOGGER.debug("{}尝试获得{}的锁.", value, key);
    			Long i = jedisClient.setnx(key, value);
    			if (i == 1) {
    				jedisClient.expire(key, DEFAULT_SINGLE_EXPIRE_TIME);
    				logger.debug(value + "-成功获取{}的锁,设置锁过期时间为{}秒 ", key, DEFAULT_SINGLE_EXPIRE_TIME);
    				return true;
    			} else {
    				// 存在锁 ,但可能获取不到,原因是获取的一刹那间
    				// String desc = lockManger.jc.get(key);
    				// LOGGER.error("{}正被{}锁定.", key, desc);
    			}
    			if (timeout == 0) {
    				break;
    			}
    			// 在其睡眠的期间,锁可能被解,也可能又被他人占用,但会尝试继续获取锁直到指定的时间
    			Thread.sleep(100);
    		} while ((System.nanoTime() - begin) < unit.toNanos(timeout));
    		// 因超时没有获得锁
    		return false;
    
    	}
    
    	/**
    	 * 释放单个锁
    	 */
    	public void unLock(String key) {
    		jedisClient.del(key);
    		logger.debug("{}锁被{}释放 .", key, key);
    	}
    
    	/**
    	 * 获取Redis服务器时间(HHmmss)
    	 */
    	private String getRedisTime() {
    
    		Long timestamp = Long.parseLong(jedisClient.time().get(0)) * 1000;
    		String redisTime = new SimpleDateFormat("HHmmss", Locale.CHINA).format(new Date(timestamp));
    		return redisTime;
    
    	}
    
    	/**
    	 * 自动补全6位数自增序列
    	 */
    	private String autoCOS(String v) {
    		int DEFAULT_LENGTH = 6;
    		int length = v.length();
    		if (length >= DEFAULT_LENGTH) {
    			return v;
    		}
    		int rest = DEFAULT_LENGTH - length;
    		StringBuilder sb = new StringBuilder();
    		for (int i = 0; i < rest; i++) {
    			sb.append('0');
    		}
    		sb.append(v);
    		return sb.toString();
    
    	}
    
    }
    
    仅作为初学记录,以供查阅。

 

 

展开阅读全文
博主设置当前文章不允许评论。

没有更多推荐了,返回首页