跳至主要內容
  • Hostloc 空間訪問刷分
  • 售賣場
  • 廣告位
  • 賣站?

4563博客

全新的繁體中文 WordPress 網站
  • 首頁
  • 求 16 位纯数字订单号产生算法
未分類
29 12 月 2020

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

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

資深大佬 : Aluhao 3

最近业务方要求订单号不能大于 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);

大佬有話說 (43)

  • 資深大佬 : hbolive

    单纯依靠算法,16 还是 18 位,都没法保证吧重复吧。
    所以应该有其他机制校验下生成的 ID 是否重复。

  • 資深大佬 : laminux29

    为啥订单号就不能老老实实从 1 开始自增?为啥订单号就不能常见的无符号 32 位整型?

  • 主 資深大佬 : Aluhao

    @hbolive 是有校验,产生的订单写入 Redis 了,产生的时候从 Redis 检查一次。

  • 資深大佬 : pxw2002

    有几位根据日期时间生成
    就不会重复了吧

  • 資深大佬 : bleutee

    @laminux29 萬一人家想操數據呢?一五一十的順序排列,咋操

  • 主 資深大佬 : Aluhao

    @pxw2002 用毫秒加随机 2 位,每秒并发 1 万容易重复的。

  • 主 資深大佬 : Aluhao

    @laminux29 自增要先写数据库,很多多业务是先拿订单号请求接口成功后才写入数据库。
    还有就是自增从 1 开始,容易被人查数据。

  • 資深大佬 : jimmyismagic

    业务方的订单号和你内部的订单号完全可以分开啊,重复就重复呗

  • 主 資深大佬 : Aluhao

    @jimmyismagic 这个就是内部订单号,不能重复的。

  • 資深大佬 : jimmyismagic

    @Aluhao 所以他到底是甲方还是乙方?乙方糊弄过去就行了,甲方就怼回去,不懂瞎指导

  • 資深大佬 : bsg1992

    时间戳 不就解决了吗

  • 資深大佬 : crclz

    你说的 16 位是“个十百千万”的位吧,不是 bit 吧。

    如果是 16 个字符,那么约束我猜就是前端 js 的 number 超过 53~54bit 就会损失精度吧。

    一个解决方案是传字符串。

    如果非要数字,也不是不可以。你去看看 snowflake 算法。https://github.com/beyondfengyu/SnowFlake/blob/master/SnowFlake.java 把第 18 行里面的几个东西改一下,就可以应对不同的位数,本质是(使用年限,机器数量,数据中心数量,每秒并发数量)的权衡。当然首先得去看看 showflake 的结构再来改。

  • 資深大佬 : Jooooooooo

    用时间戳+机器码

    每个机器上维护一个当前时间戳可用的序号

    你并发不至于那么大

  • 主 資深大佬 : Aluhao

    @jimmyismagic 要拿内部唯一订单号去关联对方订单信息,要先请求传 16 位订单号过去。

  • 資深大佬 : xuanbg

    魔改雪花算法,41 位时间戳不要动,10 位设备去掉,差不多就是 16 位数字了。

    但是,我估计你要的是 yyyyMMdd+2 位业务代码+2 位 xx+4 位流水号,流水号还要加密的那种。在我的 github 里面有,请自取

  • 資深大佬 : DarkCat123

    @laminux29 容易被人遍历数据,分析…… 而且不利于分布式数据库的 hash 分区。

    原来的 18 位用的是 snowflake?
    我建议要不要魔改下 snowflake, 牺牲一下时间来换位数降低(我记得原来的 snowflake 可以用 69 年)。
    要不然考虑找个 md5 sha1 之类的 hash 之后转 hex 看看能不能到 16 位吧。

  • 主 資深大佬 : Aluhao

    @Jooooooooo 主要是只限制 16 个数字,长一点都好解决。

  • 資深大佬 : DarkCat123

    @xuanbg 老哥好巧,我们同时提到了魔改 snowlflake……

  • 資深大佬 : jimmyismagic

    @Aluhao 那你从 1 开始不就行了,对方唯一,需要你传的唯一,对方根本不关心你传的什么,上的 snowfake 一般用的很多,分布式 id 用的比较多,单机也没什么问题,16 位 50 多个比特完全够了

  • 資深大佬 : dorothyREN

    13 位时间戳 加 3 位随机数或者 3 位自增数字

  • 資深大佬 : lmmortal

    可以借鉴一下身份证号最后一位的校验算法

  • 資深大佬 : lin07hui

    10 进制转 16 进制,不香吗

  • 資深大佬 : lawler

    @dorothyREN #20 就这个方案里的自增就可以了。
    @Aluhao #7 redis incr,mq

    要觉得不行,不妨把解决 10w/tps 的方案分享出来?
    要觉得可以遍历,不妨把不能遍历的纯数字索引方案分享出来?

  • 資深大佬 : ytmsdy

    时间戳,加两个随机数,外加一个校验位。绰绰有余了!

  • 資深大佬 : yuzo555

    “容易被人遍历数据”这个不是自增的问题,是你们程序权限控制的问题

  • 資深大佬 : Soar360

    20-1226-19-123456

  • 資深大佬 : dorothyREN

    @lawler #23 13 位时间戳+3 位数字,1 毫秒 1000 个单号,肯定够用了

  • 資深大佬 : jzmws

    @crclz 用雪花自己技术不过硬 然后 js 超出精度 坑死自己了 , 用这个算出来的是会操作 js 精度的

  • 資深大佬 : jimmyismagic

    @jzmws js 太傻了,前端技术不行让后端想办法

  • 資深大佬 : dream7758522

    很简单啊,时间戳→md5,16 位。→生成的 md5 中的 abcdef 用 123456 改写。
    举例:0123456789012345→md5,16 位→199aa7dcadfdb4e4→其中的字母字母用 123456 替换→1991174314642454 。
    觉得容易反算的话,可以加盐

  • 資深大佬 : lrvinye

    @laminux29 #2 自增订单号会被竞争对手分析流水

  • 資深大佬 : Lemeng

    重复 16 位 18 位都少。

  • 資深大佬 : catror

    任何一个生成 int64 ID 的算法都行,int64 的 16 进制编码结果就是 16 位

  • 資深大佬 : mxT52CRuqR6o5

    加密一个自增序列可以得到看上去随机的序列,不会重复,魔改加密算法让密文空间和明文空间在 16 位纯数字内

  • 資深大佬 : mxT52CRuqR6o5

    要是没有随机性的要求的话直接魔改 snowflake 就是了

  • 資深大佬 : hijoker

    13 位毫秒数+3 位随机数, 数据库这个字段设置类似唯一约束的东西, 如果真有重复,插入报错,根据报错信息重新生成随机数并重试插入

  • 資深大佬 : oneisall8955

    @jzmws #28 我公司 long 类型都转字符串出去给前端了

  • 資深大佬 : mostkia

    一般都时间戳+盐保证唯一性

  • 資深大佬 : neptuno

    时间戳+(用户 id 转成 3 位数)?是不是最简单+重复率低

  • 資深大佬 : ciddechan

    @dream7758522 这种的会不会分不出是真的 123456 还是替换的 123456

  • 資深大佬 : wangritian

    1.雪花算法:毫秒时间戳+集群号+机器号+进程号+自增序号
    这里最关键的是进程常驻,需要 swoole/workerman 插件
    2.额外写一个单实例部署的 id 生成器,加锁单线程运行,性能没有 1 好

  • 資深大佬 : nano91

    16 位 MD5 ?拿老 18 位订单号做一次转换

  • 資深大佬 : afewok

    但凡深入调研下业界和 github,都不会问出这个问题。

文章導覽

上一篇文章
下一篇文章

AD

其他操作

  • 登入
  • 訂閱網站內容的資訊提供
  • 訂閱留言的資訊提供
  • WordPress.org 台灣繁體中文

51la

4563博客

全新的繁體中文 WordPress 網站
返回頂端
本站採用 WordPress 建置 | 佈景主題採用 GretaThemes 所設計的 Memory
4563博客
  • Hostloc 空間訪問刷分
  • 售賣場
  • 廣告位
  • 賣站?
在這裡新增小工具