欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  后端开发

php订单号方案,重复的可能性要很低很低很低,大家说说自己的方案。

程序员文章站 2022-04-10 23:08:42
...
php订单号方案,重复的可能性要很低很低很低,大家说说自己的方案。

回复内容:

php订单号方案,重复的可能性要很低很低很低,大家说说自己的方案。

我的算法是:

买家UID+商家UID+年月日+三位随机数

大家觉得怎么样?

我来说下对京东ID编号的看法,两年前京东订单就突破2亿,现在应该超过四个亿了,十位订单最长才99亿,从这个占比来说,京东的订单号应该不是简单某种随机算法做出来的,如果是随机算法做出来的,肯定要做二次检验,ID是否已存在,如果存在就再生成新的。根据我分析自己在京东购买东西实际编号,丫就是按从小到大生成的
我估计有个外置ID生成服务器,要不然肯定抗不住双11这种,比如可以有一台专门服务器分多个进程,每个进程负责10万个编号分配,没有了就再申请,进程间的编号独立,或者简单点每台应用服务器就有个专属ID区域。

我们这的方式就是:
时间戳 + 机器编号 + 0-1000循环编号

首先时间戳是不会重复的,好像这样就保证了不重复吧。

我看了下淘宝的订单和账户有关。 同一个账户对同一个商家的订单号尾数好像。。是一样的

有反馈下面代码,不靠谱,冲撞率极高,这里就仅做学习,不推荐正式环境使用了

    /**
     *
     * uniqid - 官方是这样说的:
     * Gets a prefixed unique identifier based on the current time in microseconds.
     */
    function build_order_no()
    {
        return date('Ymd').substr(implode(NULL, array_map('ord', str_split(substr(uniqid(), 7, 13), 1))), 0, 8);
    }

补充:来自ECSHOP订单号生成函数:/includes/lib_order.php文件中的get_order_sn()

/**
 * 得到新订单号
 * @return  string
 */
function build_order_no()
{
    /* 选择一个随机的方案 */
    mt_srand((double) microtime() * 1000000);
 
    return date('Ymd') . str_pad(mt_rand(1, 99999), 5, '0', STR_PAD_LEFT);
}

from :http://levi.cg.am/archives/3373

有一个东西叫 UKG 专门来干这个事情的。可以了解下:https://github.com/liexusong/ukg

我觉得uniqid就行
http://php.net/manual/zh/function.uniqid.php

可以 参考一下 ecshop 的订单生成机制

return date('Ymd') . str_pad(mt_rand(1, 99999), 5, '0', STR_PAD_LEFT); 

$str = date('ymd') . substr(implode(null, array_map('ord', str_split(substr(uniqid(), 7, 13), 1))), 0, 8);
或者
$yCode = array('A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J');
$orderSn = $yCode[intval(date('Y')) - 1970] . strtoupper(dechex(date('m'))) . date('d') . substr(time(), -5) . substr(microtime(), 2, 5) . sprintf('%04d%02d', rand(1000, 9999), rand(0, 99));

上面的方案生成的订单号比较长,京东的十位订单号是怎么生成和保证不重复的呢?

订单编号在什么时候生成?怎样避免生成重复的?事务安全?存储过程?

sys_guid

为什么我想用hash做订单号……

/*
 * 得到唯一的订单编号
 * @params null
 * @return string 订单编号
 */
/** preterchan **/
public function gen_id($n=0, $data_format='ymdHi')
{
    $i = rand(0,99999);
    do{
        if(99999==$i){
            $i=0;
        }
        $i++;
        $order_id = date($data_format).str_pad($i,5,'0',STR_PAD_LEFT);
        if ($n) $order_id .= $n;
        $row = $this->db->selectrow('SELECT order_id from orders where order_id ='.$order_id);
    }while($row);
    return $order_id;
} 

生成出的数字转换成36进制(数字+26个字母),可以缩短长度
比如 :

 //会员号 + 秒 + 微秒 + 随机
$mid=118914;
list($usec, $sec) = explode(" ", microtime());
$rand=rand(1000,9999);
echo strtoupper(base_convert($mid,10,36).base_convert($sec,10,36).base_convert($usec*10000000,10,36).base_convert($rand,10,36));
//2JR6NE7JXQ5SPY85BY

如果没有别的前提要求,自增长就足够了...
我之前一个项目的要求是不能让用户看出是怎么生成的,表面上看起来要完全随机
那么加时间戳也会被看出来,使用用户uid也会被看出来,随机生成又有可能出现重复
最后是这样做的

        $time_order=time();
        list($usec, $sec)=explode(" ", microtime());
        $orderid=substr($uid*rand(11,55),0,5);
        $orderid.=date('ymdHis',$sec).ceil($usec*10);
        $orderid=substr($orderid,0,18);
相关标签: php