一般用到一个函数:

uniqid(prefix,more_entropy)
参数 描述
prefix 可选。为 ID 规定前缀。如果两个脚本恰好在相同的微秒生成 ID,该参数很有用。
more_entropy 可选。规定位于返回值末尾的更多的熵。

说明

如果 prefix 参数为空,则返回的字符串有 13 个字符串长。如果 more_entropy 参数设置为 true,则是 23 个字符串长。

如果 more_entropy 参数设置为 true,则在返回值的末尾添加额外的熵(使用组合线形同余数生成程序),这样可以结果的唯一性更好。

由于基于系统时间,通过该函数生成的 ID 不是最佳的。如需生成绝对唯一的 ID,请使用 md5() 函数(请在字符串函数参考中查找)

最简单的生成

md5(uniqid(rand(), true)); rand()可以换成'',空

一篇文章:

关于生成订单号的解决方案
电子商务及类电子商务的系统越来越多,我相信订单号问题是这类系统中最常见不过的一个问题了,但今天还是想谈谈。
这几天由于工作需要接手了另外一同事前期开发的一个交易系统,原本使用的是uniqid()函数生成的。uniqid()是根据系统时间经过一定算法得到的一个结果,关于uniqid()的详情手册上很清楚。
当时的生产方式是:

$order_sn = str_replace('.', '', uniqid('', true));

这种方式理论上说会重复,但是在实际应用中我相信这种重复可以认为是不可能事件。但是,如果这件事情到此就结束的话我也就不会再写这篇文章。这几天做支付接入,国内某大型网络支付机构只支持传递最多16位的订单号,无奈我只得调整订单号的生产规则。
其实关于生成订单号的方式非常多,大致有以下几个参数被用到:1、自增字段,2、系统时间,3、随机数,4、流水号。
一、数据库自增字段
二、简单的使用系统时间
三、系统时间加随机数
四、系统时间加流水号
先说说数据库自增字段,这种方式是最简单有效的方式,但同时也存在很大的弊端:
1、以mysql为例的int类型最多存储10位的数字,如果使用bigint则在使用php的mysql_insert_id()取上次插入id时会出现错误,当然这个错误是可以采用某些方法避免的。
2、很多时候业务逻辑需要在数据未插入系统之前就获得订单号以进行一系列的处理,这样就容易出错。比如当并发较高的时候系统获取到下一次插入的ID应该是10000,可是当真正insert的时候发现10000已经被其他插入行使用。
3、很容易透露出系统的销量,从商业层面说这种方式不太合适。
4、表现不够直观,不能通过订单号简表达订单信息
简单的使用系统时间也可以有多种方式比如直接使用time()生成10位数字,这种方式基本避免了数据库自增字段的大部分弊端,但同时也产生的一些新的问题,比如:并发量稍高(峰值每秒一次以上,相信这是个很小的值)就会产生相同订单号,而这是业务逻辑所不允许的。为了解决重复订单问题而使用随机数或者流水号。
先说随机数,这东西就跟看上去的字面意思一样,总显得不那么可靠,我认为尽量不使用它参与唯一标识。
再说流水号,既然叫流水号,它的性质其实和自增字段一样,不同的是或许每天或者每月流水号又会重新计数。总得有个地方来保存下一个(或者当前使用过的最大)流水号的值,如果存在文件中那就需要考虑这个文件的读写锁的问题,就这个问题估计足够写书了,在此不予讨论。如果以自增方式存在DB中,那么我们在程序生成订单号之前需要多访问(至少)一次DB,这也就降低了程序性能,要知道数据库访问对程序的性能影响是非常明显的

上面是一大堆废话,说说我的解决思路(PHP),当然同时别忘了大前提是:限制长度16位
第一步:

$order_sn = date('ymdHis').substr(microtime(),2,4);

其实这种方式基本已经满足需求了,无需访问DB无随机数参与。但是如果两次请求在相同的十万分之一秒内产生,那么相同订单就产生了,看能否有办法继续提高。
date(‘His’)所表达的结果其实就是000000到235959,而且其中很多数字不会被用到比如126998。一天86400秒,如果从一天的0:0:0算起直到23:59:59使用00000-86400就可以完全表示,这样下来我们就完全可以把date(‘His’)换成五位数字。既然time()函数就是按秒计数,那咱就取time()结果的后五位,同一天之内后五位不会重复出现,比如今天0:0:0后五位是98765,那么到今天23:59:59后五位就应该是98765+86400去掉最高位,相信这个应该是很好理解的。
这就产生了第二步的结果:

$order_sn = date('ymd').substr(time(),-5).substr(microtime(),2,5);

这样一来也导致无法直观的表达出订单生成的时分秒,但我认为(或者说从业务角度理解)这个属于可接受范围。同时这样处理出现重复订单的概率就降低到了第一步的1/10,我以为这应该不算一个小数字。还不满意?OK,那继续!
想要继续降低重复可能性那就继续提高时间精度,但是我们的长度限制只有16位,看来只有减少部分不长变动的字符。
date(‘ymd’)产生6位字符,而前两位在一年之内都不会变化,第三到第四位也就是01-12。
前两位我们可以使用A-Z的字母来表示,系统开始运行的那一年用A,第二年用B,第三年用C……类推,我相信我写的这程序运行不了10年。第三第四位完全可以使用一位16进制数表示,这样咱就又节约了两位字符,这就可以在末尾加上00-99的随机数。
现在看第三步的结果

$year_code = array('A','B','C','D','E','F','G','H','I','J');
$order_sn = $year_code[intval(date('Y'))-2010].
strtoupper(dechex(date('m'))).date('d').
substr(time(),-5).substr(microtime(),2,5).sprintf('%02d',rand(0,99));

理论上说出现重复订单号的概率又降到了第二步的1/100。
做个简单测试,写个php文件,连续10次echo出这三步结果得到的$order_sn,中间无任何多余程序。
第一种方案基本得到10个相同的结果。
第二种方案基本得到10个不同的结果,主要是后两位不同,一般末位差一。
第三种方案得到10个不同结果末四位不同
当然这个测试不具备多少说服力
优点:
1、不用操作数据库,性能较高。
2、较为直观,不难看出订单产生的大致时间
3、订单号重复的概率极小,只有程序在百万分之一秒内同时处理一个以上的生成订单号请求,而且同时生成的0-99的随机数也一样才会出现重复的订单号。

转自:http://www.redtamo.com/default/create_order_sn.html

更多:
http://segmentfault.com/q/1010000000095834
http://blog.sina.com.cn/s/blog_4c925dca0100ay4b.html

php订单生成唯一Id的更多相关文章

  1. php生成唯一id/唯一标识符/唯一订单号

    /** * php 生成唯一id * https://blog.csdn.net/hzqghost/article/details/18914681 */ function guid($factor= ...

  2. PHP生成唯一ID的方法

    PHP自带生成唯一id的函数:uniqid() 它是基于当前时间微秒数的 用法如下: echo uniqid(); //13位的字符串 echo uniqid("php_"); / ...

  3. php 生成唯一id的几种解决方法

    php 生成唯一id的几种解决方法   网上查了下,有很多的方法 1.md5(time() . mt_rand(1,1000000)); 这种方法有一定的概率会出现重复 2.php内置函数uniqid ...

  4. PHP使用SnowFlake算法生成唯一ID

    前言:最近需要做一套CMS系统,由于功能比较单一,而且要求灵活,所以放弃了WP这样的成熟系统,自己做一套相对简单一点的.文章的详情页URL想要做成url伪静态的格式即xxx.html 其中xxx考虑过 ...

  5. 如何使用php生成唯一ID的4种方法

    php生成唯一ID的应用场景非常普遍,如临时缓存文件名称,临时变量,临时安全码等,uniqid()函数基于以微秒计的当前时间,生成一个唯一的 ID.由于生成唯一ID与微秒时间关联,因此ID的唯一性非常 ...

  6. PHP获取时间戳和微秒数以及生成唯一ID

    microtime函数 描述:返回当前Unix时间戳和微秒数 语法:mixed microtime( [ bool $get_as_float ] ) //直接输出 echo microtime(); ...

  7. 根据twitter的snowflake算法生成唯一ID

    C#版本 /// <summary> /// 根据twitter的snowflake算法生成唯一ID /// snowflake算法 64 位 /// 0---0000000000 000 ...

  8. C# 根据twitter的snowflake算法生成唯一ID

    C# 版算法: using System; using System.Collections.Generic; using System.Linq; using System.Text; using ...

  9. php 生成唯一id的几种解决方法(实例)

    php 生成唯一id,网上查了下,有很多的方法 1.md5(time() . mt_rand(1,1000000)); 这种方法有一定的概率会出现重复 2.php内置函数uniqid() uniqid ...

随机推荐

  1. English - allow to do 与 allow doing 的区别

    英语中并没有allow to do sth这种结构,只有allow doing sth 及allow sb to do sth这两个结构. 你这样记忆可能方便一些: 1. 在主动语态中,如果allow ...

  2. 【转】在SQL Server 2008中SA密码丢失了怎么办?

    sql server 2008的sa用户莫名其妙就登陆不进去了.提示如下: 以上提示就表明是密码错误,但密码我可是记得牢牢的,也许是系统被黑的原因吧.一直以来我的Windows身份验证就用不起,以下方 ...

  3. Android数据的四种存储方式SharedPreferences、SQLite、Content Provider和File (三) —— SharePreferences

    除了SQLite数据库外,SharedPreferences也是一种轻型的数据存储方式,它的本质是基于XML文件存储key-value键值对数据,通常用来存储一些简单的配置信息.其存储位置在/data ...

  4. 最新版SDWebImage的使用

    我之前写过一篇博客,介绍缓存处理的三种方式,其中最难,最麻烦,最占内存资源的还是图片缓存,最近做的项目有大量的图片处理,还是采用了SDWebImage来处理,但是发现之前封装好的代码报错了.研究发现, ...

  5. pushViewController自定义动画

    实现的主要代码如下: CATransition *transition = [CATransition animation]; transition.duration = 1.0f; transiti ...

  6. cocostudio导出plist文件

    今天在用Armature类时用到cocostudio导出文件,由于美术的原因他使用的是中文命名法(这你敢相信),后面在导入程序中跟了下代码发现是解析plist文件有误,我就来比较正常功能文件和有错文件 ...

  7. 搭建Hadoop集群 (一)

    上面讲了如何搭建Hadoop的Standalone和Pseudo-Distributed Mode(搭建单节点Hadoop应用环境), 现在我们来搭建一个Fully-Distributed Mode的 ...

  8. Android 常用动画小结

    1. 渐入动画 // Request the next activity transition (here starting a new one). startActivity(new Intent( ...

  9. 电脑硬件扫盲--CPU 显卡

    CPU: 主要2个厂商 Inter:core(酷睿) > pentinum(奔腾) > celeron(赛扬) AMD:athlon(速龙) > semporn(闪龙) 主频(GHz ...

  10. Analysis about different methods for reading and writing file in Java language

    referee:Java Programming Tutorial Advanced Input & Output (I/O) JDK 1.4+ introduced the so-calle ...