電商系統訂單號設計

2019年7月2日16:43:41php

 訂單號設計,這個功能說複雜也複雜,簡單也簡單mysql

 

先說一下比較基礎的作法,redis

例如算法

$orderKey = uniqid(date('Ymd'));
        pp($orderKey);
201907205d32de71e6002

利用php自帶的生成惟一ID 方法,生成帶日期的惟一訂單號,併發狀況下不會重複,通過測試過,連續寫10000次不會重複sql

 請不要使用隨機數函數,由於會重複express

 

設計思路的話有幾種:數組

1,有意義的位數的訂單號安全

日期+訂單來源+支付類型+業務標記+用戶ID+自遞增數併發

這樣就比較一目瞭然,也是很常見的 設計方案函數

2,能夠反解的訂單號,自己一眼是看不出你訂單的意義

能夠經過反解訂單知道此訂單的狀況,這不是和方案1同樣嗎?方案一會暴露系統的訂單設計意義,方案可能會涉及到加密等問題,爲了數據安全考慮

3,無心義的訂單號爲了處理併發,有些狀況下,爲了巨大的併發量會設計一個算法來生產訂單號的接口,直接使用

4,使用redis,mysql鎖機制作自增數,一個內部調用的一個服務這樣而後能夠配合任意的前綴

 使用mysql作計數器的一個demo

 public static function counter($shop_id = 0, $type = null, $need_transaction = 1, $pad_length = 15, $now = null) {

        if (empty($type)) {
            throw new \Exception('type標籤不能爲空');
        }
        if (empty($now)) {
            $now = time();
        }

        /*
         * 合同生產須要短一點,根據20190703XXXX的格式,長度爲12,再短的話,就會出現一天以內生產333個,可能後期業務會不夠用
         */
        if ($type == 5) {
            $time = date('Ymd', $now);
            $pad_length = 11;
        } else {
            $time = date('Ym', $now);
        }

        $length = $pad_length - mb_strlen($time);
        $tag = self::counter_array($type);
        $name = $time . '_' . $tag;

        $need_transaction == 1 && DB::beginTransaction();
        try {
            $Counter = Counter::where('name', $name)->first(['value', 'id']);
            if (empty($Counter)) {
                //沒有就插入
                $Counter = new Counter;
                $Counter->name = $name;
                $Counter->type = $type;
                $Counter->tag = $tag;
//                $Counter->shop_id = $shop_id;
                $Counter->save();
                $Counter = Counter::where('name', $name)->first(['value', 'id']);
            }

            $Counter = $Counter->toArray();
            //加鎖 防止生成的訂單號出錯,沒有在name上加索引
            Counter::where('id', $Counter['id'])->lockForUpdate()->first();

            $new_count = (float) $Counter['value'] + 3;
            Counter::where('name', $name)->update(['value' => $new_count]);
            $string = $time . str_pad($new_count, $length, '0', STR_PAD_LEFT);

            $need_transaction == 1 && DB::commit();
            return $string;
        } catch (\Exception $e) {
            $need_transaction == 1 && DB::rollBack();
            throw new \Exception($e->getMessage());
        }
    }
 //訂單計數器映射數組
    public static function counter_array($type = null) {
       
        $array['5'] = 'contract';
       
        $array['10'] = 'sales_order_number';
        
        $array['20'] = 'purchase_order_number';
       
        $array['30'] = 'logistics_order_number';
        
        $array['40'] = 'inbound_order_number';
        
        $array['50'] = 'outbound_order_number';
        
        $array['60'] = 'purchase_point_number';
        
        $array['70'] = 'express_number';
        
        $array['75'] = 'return_express_number';
        
        $array['80'] = 'sale_voucher_number';
        
        $array['90'] = 'batch_number';
        
        $array['100'] = 'purchase_settle_number';
        
        $array['110'] = 'sales_settle_number';
       
        $array['120'] = 'sales_point_number';
        
        $array['130'] = 'k3_pay_number';
        if (empty($type)) {
            return $array;
        }
        return $array[$type];
    }
相關文章
相關標籤/搜索