JAVA 生成不重複訂單號 優化版本 訂單號格式為yyyymmdd後面自增
阿新 • • 發佈:2018-11-10
@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個