harry890829
V2EX  ›  问与答

关于订单号的生成

  •  
  •   harry890829 · Aug 23, 2016 · 10476 views
    This topic created in 3735 days ago, the information mentioned may be changed or developed.

    现在项目场景是, pc 客户端生成订单号传给后端,之前使用的是微秒级的时间+随机数,但是依旧发生了重复情况,现在想要优化这个算法,要求订单号中只包含数字,长度小于 30 。

    后来想到两种方法: 1.YYMMDDhhmmss+mac 地址(转成 18 位十进制),经过讨论, mac 地址可以进行修改,时间也不一定是确定的,假设场景,客户在 12:00 支付完成之后,发现自己时间快了半小时,然后回调了,这样在 11:30 到 12:00 之间就有可能重复。

    2.YYYYMMDDhhmiss+毫秒+微秒+IP 尾 4 位+6 位随机数,其中 6 位随机数种子采用( mac 地址前三位前补 00 )与( mac 地址后三位后补 00 )进行异或得出。这个方法大家觉得只是极大的减少的几率问题,但是并不能避免重复的问题

    也有同事提到了, guid 来做,但是订单号要求纯数字,现问下如何解决此类问题,多谢 开发语言 c/c++

    Supplement 1  ·  Aug 24, 2016
    多谢大家的吐槽和建议,我已经让领导看了这个帖子,现在暂定做法就是极大减少重复几率,然后后期在服务器修改,以优化
    63 replies  •  2016-08-24 14:23:35 +08:00
    jugelizi
    jugelizi
    Aug 23, 2016
    1
    客户端。。。大作死啊
    harry890829
    harry890829
    OP
    Aug 23, 2016
    2
    @jugelizi 哎,现在这个事情已经不可逆了……要是再服务器生成订单号需要修改大量的模块……
    loading
    loading
    Aug 23, 2016 via Android
    3
    Uuid 算法
    loading
    loading
    Aug 23, 2016 via Android
    4
    不用大改吧……入服务器单独设置个接口,申请一个 id 返回,你后面的流程都没变……
    egen
    egen
    Aug 23, 2016
    5
    你们有 30 个数字, YYMMDDhhmm 长度只有 10 ,后面 20 个全部随机,重复的几率可以忽略,比你加毫秒 mac 什么的重复几率小多了
    lincanbin
    lincanbin
    Aug 23, 2016
    6
    GUID 从二进制映射到十进制,大概需要 35 位整数,你要求长度小于 30 ,其实已经很接近了。
    再多加几位,或者心大点,砍掉 GUID 的几位。
    allce231
    allce231
    Aug 23, 2016
    7
    客户端。。。大作死啊!!!!
    egen
    egen
    Aug 23, 2016
    8
    因为客户端的时间不可信,记录秒和毫秒也没什么意义
    harry890829
    harry890829
    OP
    Aug 23, 2016
    9
    @loading 我也想到这个情况,其实我完全可以让服务器开一个接口给我,然后我每次要生成订单号的时候,问服务器要就好了,不过貌似后端不想加这个接口

    @egen 这个貌似领导不能接受……

    @lincanbin guid 映射到十进制?我去看看,多谢了
    qian0206
    qian0206
    Aug 23, 2016
    10
    在服务端弄个接口专门给客户端调用获取订单号不就行了
    harry890829
    harry890829
    OP
    Aug 23, 2016
    11
    @allce231 都是泪……不知道项目启动的时候为什么这么规划
    @egen 是啊,客户端时间不可信, mac 也不是一个可信的值,所以感觉太蛋疼
    lincanbin
    lincanbin
    Aug 23, 2016
    12
    订单号这种东西你们都敢客户端生成,心很大啊。
    lincanbin
    lincanbin
    Aug 23, 2016
    13
    @harry890829
    噫,我前面算错了, GUID 映射成十进制,是最多需要 39 位整数。

    例如说 GUID ,{99D66A96-4CCD-2944-9A3C-9D583513897A},转十进制后就是 204485196726229962288084266002268806444 。

    你看着办吧。
    loading
    loading
    Aug 23, 2016 via Android
    14
    如果让后台做个订单 id 的接口都搞不定,你们公司也就玩完了。
    xinyewdz
    xinyewdz
    Aug 23, 2016
    15
    用户 id+时间+随机数。这样还会重复?
    terence4444
    terence4444
    Aug 23, 2016 via iPhone
    16
    让客户端提交时检测是不是有重复号码,有的话重新生成一个?
    dong3580
    dong3580
    Aug 23, 2016
    17
    @harry890829
    客户端怎么改都会有可能有重复,还是服务器端保存那里将收到的订单号运算一下 重新生成一下呀,不就好了,
    BuilderQiu
    BuilderQiu
    Aug 23, 2016
    18
    我比较关注价格也是客户端算好传过去的吗?
    如果是,分享下客户端下载地址。


    然后,客户端生成订单 ID 这种方案是谁批的。。。设计方案讨论能通过。。

    治标就各种想办法减少重复数据,治本的办法还是服务器生成,沟通解决吧。
    yao978318542
    yao978318542
    Aug 23, 2016
    19
    @allce231 你这个头像作大死
    allce231
    allce231
    Aug 23, 2016
    20
    后端判断订单号重复 如果重复重新生成一个 id 给它
    sunshinewu85
    sunshinewu85
    Aug 23, 2016
    21
    按楼主现在的意思,后端是不愿意提供任何生成及检测支持,全靠客户端去整,呵呵,这也理解,谁都不愿在自己管辖的地盘补上一脚,否则一出问题,把全问题都推过去了。。。可是在客户端无论怎么整,其实都已经在拆东墙补西墙了,还不是亡羊补牢。目前亡羊补牢靠谱的还是这两个方案较为合适吧:
    1 、找个能拍板让服务端改的人来,从服务端拿 ID 。有些业务,纵使现状改起来麻烦,也好过后续引出更多麻烦;
    2 、服务端不提供生成,那总得提供个检测吧~话说回来,都检测了,干脆服务端生成一起了吧,毕竟一劳永逸啊 <img src=" " class="embedded_image" border="0" />
    xmh51
    xmh51
    Aug 23, 2016
    22
    额。不是办法的办法,服务器生成订单号传给客户端,客户端再上传到服务器。另一种 YYMMDDhhmm +随机数。但是被你否了。 另外随机和重复不是等同的,随机值不能避免重复。你还是在服务器生成订单号比较好。客户端怎么也不可能知道服务器上面是否有重复的订单号。
    finian
    finian
    Aug 23, 2016
    23
    客户端再怎么整都可能会有问题(合法性、安全性),这事儿必须服务端来整。
    harry890829
    harry890829
    OP
    Aug 23, 2016
    24
    @lincanbin guid 的情况我再看看能不能支持,多谢

    @loading
    @qian0206
    @sunshinewu85
    @xmh51
    @finian
    也不是没有想过服务端只开一个生成订单的接口,让客户端调用,但是本来一次的能够完成的动作变成了两次完成,这样失败的情况也就大幅度增加了,于是直接被否决

    @xinyewdz 用户 id 是本地 id ,并不唯一,或者说大家都是重复的

    @terence4444
    @dong3580
    @allce231
    现在目前的情况是服务器收到相同的订单号就会直接拒绝,也就是说服务器收到的第二个订单会被拒绝并返回订单号重复,目前的解决就是让前端重新发起一笔

    @BuilderQiu 哎,金额也是前端送的啊,不过我们后端有相应验证,并无大碍

    感谢大家,我倾向于方案二来做了,毕竟几率已经很小,关于 guid 的情况,我上报一下,看看是不是有定论
    sc3263
    sc3263
    Aug 23, 2016
    25
    加个代理模块吧。客户端发消息到代理,代理那边计算好订单号,加到消息里,然后转发给服务端。

    还是得服务端改。不过改动能小很多。
    dong3580
    dong3580
    Aug 23, 2016 via Android
    26
    @harry890829
    订单重复谁发出的?服务器对吧,它都知道重复了还不自动重新生成一下订单号,也是醉了。
    scnace
    scnace
    Aug 23, 2016 via Android
    27
    用户 id 做 hash?
    HunterPan
    HunterPan
    Aug 23, 2016
    28
    @allce231 你的头像好像在哪见过..
    hinate
    hinate
    Aug 23, 2016
    29
    客户端的时间戳是不可信的。。。
    abelyao
    abelyao
    Aug 23, 2016 via iPhone
    30
    客户端把不带订单号的数据提交给服务端,由服务端来生成订单号,反馈结果给客户端的时候,把订单号一起带上。这样仍然是一次请求。
    guizer
    guizer
    Aug 23, 2016 via iPhone
    31
    前缀+时间+uid
    应该淘宝差不多就这么干的
    mogita
    mogita
    Aug 23, 2016
    32
    中心化的发号机,别让客户端生成 id 。
    jon
    jon
    Aug 23, 2016
    34
    客户端生成订单号服务端全盘接受吗,不检查怎么避免问题,检查了为什么不直接服务端生成
    ihuotui
    ihuotui
    Aug 23, 2016
    35
    设计有问题,怎么补都不完美,再加一个接口,客户端获取服务器的全局唯一序号(不用别人教了吧,不过也不算很难或者很简单),然后剩下的逻辑和原来一样。
    以后的项目再写第二版,重写。
    popok
    popok
    Aug 23, 2016
    36
    正常用户的用户使用出现重复的概率很小,就怕别有用心的人,毕竟你的订单号在客户端生成
    caola
    caola
    Aug 23, 2016
    37
    一切客户端传入的数据,都有可能是是不可靠的。要是你内部人员使用就无所谓,
    如果是面向公众用户使用的话,做得安全一点是好的,毕竟可能会有那么一些别有用心之人。
    ljbha007
    ljbha007
    Aug 24, 2016
    38
    客户端做的任何安全措施都是没有屌用的
    Perry
    Perry
    Aug 24, 2016
    39
    @allce231 头像不错
    wavingclear
    wavingclear
    Aug 24, 2016 via iPad
    40
    微秒级加随机数还有重复,这就是尝试攻击了,客户端还改啥
    gkiwi
    gkiwi
    Aug 24, 2016
    41
    @yao978318542
    @Perry
    @HunterPan

    头像是什么梗。。求科普
    imnpc
    imnpc
    Aug 24, 2016
    42
    客户端生成订单号 这么作大死的办法谁想出来的?
    客户端只允许传输关键类数据 例如商品 ID 数量
    其他涉及到安全的一律服务端控制...
    likai
    likai
    Aug 24, 2016
    43
    客户端时间随便可以更改。拿来生成订单号合适么?
    再一个。都知道重复了。后台啥事也不作?
    gkiwi
    gkiwi
    Aug 24, 2016
    44
    本来想写点的客户端怎么避免和处理的,但是这个锅不应该让客户端背!
    GKLuke
    GKLuke
    Aug 24, 2016
    45
    客户端就不要调用本地时间了,调用网络时间或者服务器时间,那就不存在时间回调了。
    当然,永远不要相信前台数据,起码都要滤一边真伪啊。
    Clarencep
    Clarencep
    Aug 24, 2016
    46
    订单号居然在客户端生成,这是在开玩笑吗
    wanttofly
    wanttofly
    Aug 24, 2016❤️1
    47
    @gkiwi 头像的梗:这马容易劈腿。。。
    yuankui
    yuankui
    Aug 24, 2016
    48
    这种问题,网上解决方案不是一大堆吗?

    你不是应该发一个帖子说你发现了哪些方案,然后让大家评价一下各个方案的优劣吗?
    GavinJ
    GavinJ
    Aug 24, 2016
    49
    客户端生成订单, 新鲜~~~~
    DrJoseph
    DrJoseph
    Aug 24, 2016❤️1
    50
    @gkiwi 马蓉的微博头像
    killerv
    killerv
    Aug 24, 2016
    51
    客户端生成订单号,这是什么人想出来的……
    ThreeBody
    ThreeBody
    Aug 24, 2016 via Android
    52
    天啊,订单号让前端生成已经是很严重的设计缺陷了,金额也让前段发?你后台有验证还要前段发一次?
    就这两个,我觉得你们系统可能还有很多坑。
    我想问问,我看到你说前端的用户 id 是一样的,你们前端难道不用用户登录的?就是可以匿名下单?
    是不是类似那种, 1688 元的 iphone 6s ,然后输入名字,地址,电话就直接下单那些?
    微妙级的订单都可能重复,加个 uuid ,这样应该就够的了。 uuid 碰撞几率这么低,加时间前缀,应该是够的了。
    pljhonglu
    pljhonglu
    Aug 24, 2016
    53
    服务器的锅为什么要你来背。。。
    southwolf
    southwolf
    Aug 24, 2016
    54
    LZ 赶紧来爆一下产品名字,组织 V2 群众薅羊毛去啊…… iPhone6s 点击就送啊
    damean
    damean
    Aug 24, 2016
    55
    @harry890829 “本来一次的能够完成的动作变成了两次完成,这样失败的情况也就大幅度增加了”
    这个“大幅度”有统计过吗?
    为啥会失败呢?失败了还可以在尝试几次的。
    romisanic
    romisanic
    Aug 24, 2016
    56
    如果改客户端订单号生成规则可行,意味着大家的客户端都要更新,既然如此,为什么不直接改成后端生成,这样所有客户端使用的订单号实际上是从一个位置生成的,也就不会再有重复的顾虑。哪怕后续有需要修改的地方,那也只需要直接修改服务端就可以了。
    22too
    22too
    Aug 24, 2016
    57
    我们目前的做法,毫秒级时间 + 随机数 + 用户 id 。也就是除非这个用户故意重复,用户直接是隔离的。目前没有发现问题。
    williamx
    williamx
    Aug 24, 2016
    58
    上面的说得没错,把用户 id 加上,基本都不会出现重复的问题。
    hitmanx
    hitmanx
    Aug 24, 2016
    59
    如果把本地时间换成通过网络服务器获取时间呢?这样精确到毫秒,应该没有重复性的问题了吧,除非用户 hack ,不过那就是是整个架构问题了,反正现在也有这个问题。
    maxmilia
    maxmilia
    Aug 24, 2016
    60
    用户 ID 直接给的话会被人知道用户规模,所以加个密
    SlipStupig
    SlipStupig
    Aug 24, 2016
    61
    如果是单纯冲突的话转成 MD5 或者 SHA1 转一下,如果是破解,只能用 VMProtect 这类软件延缓一下,基本上在客户端是挡不住的
    harry890829
    harry890829
    OP
    Aug 24, 2016
    62
    @sc3263 这个方法比较好,我也向领导反映了这个方案
    @dong3580 服务器发现重复直接拒绝,前端重新发起就好
    @scnace 用户 id 重复的
    @flyingfz 多谢,没想到汤不热上也有技术性文章……
    harry890829
    harry890829
    OP
    Aug 24, 2016
    63
    上面各位不一一回复了,在这里感谢大家给出的建议……
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Privacy   ·   Solana   ·   2069 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 97ms · UTC 09:07 · PVG 17:07 · LAX 01:07 · JFK 04:07
    ♥ Do have faith in what you're doing.