电商系统订单号设计

2019年7月2日16:43:41

 订单号设计,这个功能说复杂也复杂,简单也简单

先说一下比较基础的做法,

例如

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

利用php自带的生成唯一ID 方法,生成带日期的唯一订单号,并发情况下不会重复,经过测试过,连续写10000次不会重复

 请不要使用随机数函数,因为会重复

设计思路的话有几种:

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];
    }
原文地址:https://www.cnblogs.com/zx-admin/p/11121604.html