1. 程式人生 > >JAVA 生成不重複訂單號 優化版本 訂單號格式為yyyymmdd後面自增

JAVA 生成不重複訂單號 優化版本 訂單號格式為yyyymmdd後面自增

@Service("orderNumberDubbboServiceImpl")
public class OrderNumberDubbboServiceImpl implements OrderNumberDubbboService
{
    private static Logger LOG = Logger.getLogger(OrderNumberDubbboServiceImpl.class);

    private static final Integer ONCE_ORDER_NUM_CREATE =
        ConverterUtils.toInt(EConfig.getOtherConfigPropertiesValue("once_order_num_create"), 10);

    /**
     * redis鎖操作service
     */
    @Resource(name = "redisLockServiceImpl")
    private RedisLockService redisLockService;

    @Resource(name = "redisCacheServiceImpl")
    private RedisCacheService<Integer> redisCacheService;

    /**
     * 預先 產生很多訂單號 key訂單號型別value 預先生產出來的訂單號
     */
    private Map<String, ConcurrentLinkedQueue<String>> orderNumberQueueMap = new ConcurrentHashMap<>();

    public synchronized String getOneOrderNumber(String type)
    {
        ConcurrentLinkedQueue<String> orderNumbers = null;
        orderNumbers = orderNumberQueueMap.get(type);
        // 如果有這個型別 並且還有剩餘的訂單號
        if (orderNumberQueueMap.containsKey(type) && (!orderNumbers.isEmpty()))
        {
            return orderNumbers.poll();
        }
        initOrderNumber(type);
        orderNumbers = orderNumberQueueMap.get(type);
        return orderNumbers.poll();
    }

    /**
     * 初始化指定型別的訂單號
     *
     * @param type 型別
     */
    private synchronized void initOrderNumber(String type)
    {

        // 鎖表(用於判斷現在是否可以建立訂單)一小時的超時時間
        if (!redisLockService.addRedisLock("REDIS_LOCK_MAX_ORDER_NUMBER", 2000, 2))
        {
            LOG.infoMsg("獲取訂單編號失敗,訂單編碼型別為:{}", type);
            throw new CheckException(PubResult.SYSTEM_BUSY.asResult());
        }
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(new Date());
        String date = (new SimpleDateFormat("yyyyMMdd")).format(calendar.getTime());
        String key = "order_number_" + date + "_" + type;
        // key:常量+日期+訂單號 value(orderIndex):日期拼接資料
        Integer orderIndex = redisCacheService.get(key);

        orderIndex = orderIndex == null ? 0 : orderIndex;
        int minOrderIndex = orderIndex + 1;
        // 每次產生1w個訂單號
        orderIndex += ONCE_ORDER_NUM_CREATE;
        redisCacheService.put(key, orderIndex);
        redisLockService.delRedisLock("REDIS_LOCK_MAX_ORDER_NUMBER");
        ConcurrentLinkedQueue<String> orderNumbers =
            orderNumberQueueMap.containsKey(type) ? orderNumberQueueMap.get(type) : new ConcurrentLinkedQueue<>();
        orderNumberQueueMap.put(type, orderNumbers);
        for (int i = minOrderIndex; i <= (ONCE_ORDER_NUM_CREATE + minOrderIndex); i++)
        {
            orderNumbers.offer(StringUtil.formatOrderNumber(date, i));
        }

    }

思路是 先生成 1w個訂單號扔到  佇列中,然後 有需要的直接在佇列取,如果取不到的話,那麼在生成1w個