求 16 位纯数字订单号产生算法

2020-12-26 16:35:25 +08:00
 Aluhao
最近业务方要求订单号不能大于 16 位,以前写的 18 位算法不能用了,改成 16 位重复的概率太高了,问问大家有什么好的算法分享!

现在用的 18 位:

<?php declare(strict_types=1);
date_default_timezone_set('Etc/GMT-8');
$time = microtime(true);
function order()
{
$ids = 0;
$aes = substr(microtime(), 2, 6);
$pid = $aes . getmypid() . mt_rand(0, 999999);
for($in = 0; $in < 18; $in++) {
$ids += (int) (substr($pid, $in, 1));
}
return time() . $aes . str_pad(strval($ids), 2, '0', STR_PAD_LEFT);
}

$arr = array();
for($i = 0; $i < 1000000; $i++) {
$arr[] = order();
}
$arrs = array_count_values($arr);
echo 'COUNT ' . count($arrs);
echo '<br>';
echo 'RAND ' . array_rand($arrs);
echo '<br>';
arsort($arrs);
$as = [];
foreach($arrs as $ids => $aos) {
if ($aos > 1) {
$as[] = $ids;
echo $ids . ' - ' . $aos . '<br>';
}
}
echo 'COUNT ' . count($as);
echo '<br>';
echo 'Time ' . number_format((microtime(true) - $time), 3);
6742 次点击
所在节点    PHP
43 条回复
lmmortal
2020-12-26 17:43:26 +08:00
可以借鉴一下身份证号最后一位的校验算法
lin07hui
2020-12-26 18:03:19 +08:00
10 进制转 16 进制,不香吗
lawler
2020-12-26 18:23:14 +08:00
@dorothyREN #20 就这个方案里的自增就可以了。
@Aluhao #7 redis incr,mq


要觉得不行,不妨把解决 10w/tps 的方案分享出来?
要觉得可以遍历,不妨把不能遍历的纯数字索引方案分享出来?
ytmsdy
2020-12-26 18:31:32 +08:00
时间戳,加两个随机数,外加一个校验位。绰绰有余了!
yuzo555
2020-12-26 18:40:12 +08:00
“容易被人遍历数据”这个不是自增的问题,是你们程序权限控制的问题
Soar360
2020-12-26 19:49:48 +08:00
20-1226-19-123456
dorothyREN
2020-12-26 20:16:37 +08:00
@lawler #23 13 位时间戳+3 位数字,1 毫秒 1000 个单号,肯定够用了
jzmws
2020-12-26 20:45:54 +08:00
@crclz 用雪花自己技术不过硬 然后 js 超出精度 坑死自己了 , 用这个算出来的是会操作 js 精度的
jimmyismagic
2020-12-26 21:24:38 +08:00
@jzmws js 太傻了,前端技术不行让后端想办法
dream7758522
2020-12-26 21:41:24 +08:00
很简单啊,时间戳→md5,16 位。→生成的 md5 中的 abcdef 用 123456 改写。
举例:0123456789012345→md5,16 位→199aa7dcadfdb4e4→其中的字母字母用 123456 替换→1991174314642454 。
觉得容易反算的话,可以加盐
lrvinye
2020-12-26 22:31:17 +08:00
@laminux29 #2 自增订单号会被竞争对手分析流水
Lemeng
2020-12-27 00:56:21 +08:00
重复 16 位 18 位都少。
catror
2020-12-27 01:36:49 +08:00
任何一个生成 int64 ID 的算法都行,int64 的 16 进制编码结果就是 16 位
mxT52CRuqR6o5
2020-12-27 02:25:49 +08:00
加密一个自增序列可以得到看上去随机的序列,不会重复,魔改加密算法让密文空间和明文空间在 16 位纯数字内
mxT52CRuqR6o5
2020-12-27 02:26:55 +08:00
要是没有随机性的要求的话直接魔改 snowflake 就是了
hijoker
2020-12-27 04:09:34 +08:00
13 位毫秒数+3 位随机数, 数据库这个字段设置类似唯一约束的东西, 如果真有重复,插入报错,根据报错信息重新生成随机数并重试插入
oneisall8955
2020-12-27 09:28:48 +08:00
@jzmws #28 我公司 long 类型都转字符串出去给前端了
mostkia
2020-12-27 12:38:31 +08:00
一般都时间戳+盐保证唯一性
neptuno
2020-12-27 13:46:31 +08:00
时间戳+(用户 id 转成 3 位数)?是不是最简单+重复率低
ciddechan
2020-12-28 09:04:41 +08:00
@dream7758522 这种的会不会分不出是真的 123456 还是替换的 123456

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/739204

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX