讨论数量:
使用 MD5 作为订单号并不是一个好的做法。MD5 是一个散列函数,它被设计用于计算数据的散列值,并用于数据完整性校验等目的。将 MD5 作为订单号不仅容易导致不同订单产生相同的散列值(冲突),还容易被攻击者用暴力破解攻击破解出原始数据,从而影响订单的安全性。更好的做法是使用能够保证唯一性和随机性的订单号。
分享一下我的订单号生成规则,22 位,2304180233303966728324
private function generateOrderNo(int $datacenter = -1, int $workerid = -1)
{
$order_no = date('ymdHis');
// 取毫秒
$millisecond = substr(microtime(), 2, 3);
$datacenter = $datacenter > 31 || $datacenter < 0 ? mt_rand(0, 31) : $datacenter;
$workerid = $workerid > 31 || $workerid < 0 ? mt_rand(0, 31) : $workerid;
$workerLength = 5; // $datacenter 和 $workerid 占用的位数
$workerLeftMoveLength = 12; // 随机位 12 位 即 4095
$datacenterLeftMoveLength = $workerLeftMoveLength + $workerLength; // 17 $workerid 5 位 即 31
$timestampLeftMoveLength = $datacenterLeftMoveLength + $workerLength; // 22
// 毫秒时间戳 10 位 0 - 1023 (最高位可能是0, 生成后高位补0)
$ext = (string) (((intval($millisecond)) << $timestampLeftMoveLength)
| ($datacenter << $datacenterLeftMoveLength)
| ($workerid << $workerLeftMoveLength)
| (mt_rand(0, 4095))); // 随机位
// 前置补0 10位
$order_no .= str_pad($ext, 10, '0', STR_PAD_LEFT);
return $order_no;
}
订单号一般并不采用 md5 , 哪怕顺序号都不用 md5 因为 md5 的订单号没意义没价值。但并不表示不能用。 另外, md5 的确是会撞号。但 md5 足够稀疏了,撞的机会并不大。很可能从系统运行到系统被抛弃一次撞号都遇不到。
只要能保证唯一就行,但是一般直接用 md5 ,会导致这个 订单号,没法直接知道含义,一般会采取字段拼接,比如我们项目中是这样的:
if ($gift) {
$oid = $type . '_' . date('Ymd_His_') . uniqid() . '&' . $gift;
} else {
$oid = $type . '_' . date('Ymd_His_') . uniqid().'_'.mt_rand(1000, 9999);
}
我都是时间 + 随机数 4-8 位左右,再加上 用户 id(左右补零保证长度)
这样除非用户自己同一秒之内并发, 并且生成的随机数还一样,否则肯定不会重复
推荐文章: