V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
tanteng
V2EX  ›  PHP

请教 PHP 有什么的好的办法生成流水号?

  •  
  •   tanteng · 2015-09-03 00:01:23 +08:00 · 10440 次点击
    这是一个创建于 3361 天前的主题,其中的信息可能已经有所发展或是发生改变。

    比如流水号是 10 位: 1000000001 , 1000000002 ,这样的,我想使用 PHP 生成这样的流水号,根据我的理解,流水号应该是连续增长的,但是我每次生成的时候怎么不重复而且保持连续呢?

    存数据库的话比较麻烦,而且每次要查库,还要更新数据,性能低。也不能使用随机码,这样数字不连续。放到 redis 里面万一 redis 挂掉了呢所以也不好。

    PHP 生成流水号有什么好办法?

    第 1 条附言  ·  2015-09-03 11:48:21 +08:00
    Redis 支持持久化,但不知道一般情况下是否开启持久化
    第 2 条附言  ·  2015-09-03 16:04:31 +08:00
    那我想通过 redis 自增的方式获取流水号,线上 redis 有没有可能重启或断点,那流水号就重新开始了
    24 条回复    2015-09-08 11:10:52 +08:00
    guoer
        1
    guoer  
       2015-09-03 00:08:31 +08:00
    redis 可以备份的
    dsgygb
        2
    dsgygb  
       2015-09-03 00:13:00 +08:00
    窝这有个生成订单的函数。=--是随机的。只能保证 26 年内不重复。。。
    function make_number (){
    $year_code = array ('A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','I','S','T','U','V','W','X','Y','Z');



    return $year_code[intval (date ('Y'))-2015].
    strtoupper (dechex (date ('m'))).date ('d').
    substr (time (),-5 ).substr (microtime (),2,5 ).sprintf ('%02d',rand (0,99 ));


    }
    oott123
        3
    oott123  
       2015-09-03 00:15:10 +08:00 via Android
    不依赖数据库、不依赖外部存储…
    万一楼主的 php 挂了呢?
    realpg
        4
    realpg  
       2015-09-03 00:22:09 +08:00
    不依赖数据库不依赖外部存储?
    既然你叫流水号要求不冲突,

    如果是顺序的,那么至少要有一个地方存储当前值或者下一个值吧?
    如果是随机的,那么至少要有一个地方存储已经生成的全部号码避免生成重复吧?
    branchzero
        5
    branchzero  
       2015-09-03 00:26:01 +08:00
    满足这个条件的思路:
    得有一个进程锁,保证每次读取 ID 之前,前面跑脚本的操作已经完全进行完毕了(也就是在每次读取 ID 前上锁, ID 自增后解锁)。
    然后随便找一个靠谱地方存计数器就是了(文件啊、数据库、内存缓存或者其他,随便你)

    用数据库的话上面这些都不是问题,不用数据库的话,自己想办法解决吧。
    br00k
        6
    br00k  
       2015-09-03 00:29:00 +08:00
    万一服务器挂了呢。
    incompatible
        7
    incompatible  
       2015-09-03 00:29:58 +08:00 via iPhone
    每次生成一批放在缓存里 随用随取
    快用完时再生成一批
    wumch
        8
    wumch  
       2015-09-03 00:32:09 +08:00
    你这是同时高要求一致性、可用性、分区容错性啊
    lavadore
        9
    lavadore  
       2015-09-03 00:35:31 +08:00
    数据库已经有这个功能了,你不用为什么非要在 php 里用?

    数据库不用查库, auto_increment 每次插入后自动返回流水号,已有的功能为什么不用
    Mac
        10
    Mac  
       2015-09-03 00:45:05 +08:00 via Android
    @dsgygb 直接用年份岂不是可以保证永久不重复?高并发的情况下也不能保证吧,只不过有这么大的订单量环境很罕见而已
    aprikyblue
        11
    aprikyblue  
       2015-09-03 00:47:33 +08:00
    万一来一道雷呢
    cevincheung
        12
    cevincheung  
       2015-09-03 00:55:28 +08:00
    mysql
    select uuid_short ()

    生成流水号也是用来入库的,数据库挂了生成流水号也没啥用。
    huigeer
        13
    huigeer  
       2015-09-03 01:55:09 +08:00
    时间戳加随机数
    rails
        14
    rails  
       2015-09-03 03:34:29 +08:00
    其实楼主的问题可以简化为:如何在 php 内计数
    1004
        15
    1004  
       2015-09-03 03:35:34 +08:00
    弄个订单系统不就行了
    roychan
        16
    roychan  
       2015-09-03 07:58:15 +08:00
    要不查库那肯定只能找一个自递增或者自递减的变量了,也就是时间,自己设计一个算法生成不会重复的流水号即可。
    moe3000
        17
    moe3000  
       2015-09-03 08:14:23 +08:00
    redis 中开一个 key ,每次取出后, incr 一次,直接用 reids 生成
    不过这样就依赖 redis 了
    tanteng
        18
    tanteng  
    OP
       2015-09-03 09:09:07 +08:00 via iPhone
    @moe3000 redis 重启或挂了会不会丢失之前保存的值
    wwek
        19
    wwek  
       2015-09-03 09:38:28 +08:00
    @tanteng redis 支撑持久化啊
    tanteng
        20
    tanteng  
    OP
       2015-09-03 16:04:24 +08:00
    @moe3000 那我想通过 redis 自增的方式获取流水号,线上 redis 有没有可能重启或断点,那流水号就重新开始了
    undeadking
        21
    undeadking  
       2015-09-03 20:29:26 +08:00
    楼主对于流水号的理解本身就是有问题的,于是陷入了伪问题,平时都不留意各种系统的流水号是什么规则么.
    loginv2
        22
    loginv2  
       2015-09-04 11:22:13 +08:00
    默认环境为 centOS 6.5 下的话

    使用文件锁定的方式(保证一致性)在自带的 RAMDISK 分区写入文件记录流水号
    然后在业务结束之前 流水号写入数据库
    ( RAMDISK 和 文件锁 保证性能和一致性,服务器重启 数据库也没法用 所以也不用担心服务重启)
    服务器开机以后执行将数据库最后的流水号写入到文件
    lbp0200
        23
    lbp0200  
       2015-09-06 16:00:07 +08:00
    guid 或者 redis 的原子加 1
    xyzasd01
        24
    xyzasd01  
       2015-09-08 11:10:52 +08:00
    如果自增主键从 1 开始。那该订单的流水号就是 100000000 + $自增 ID 。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2036 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 16:16 · PVG 00:16 · LAX 08:16 · JFK 11:16
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.