关于订单号的生成

2015-08-14 13:03:02 查看评论 1350 人阅读    

最近面试某公司的时候被问到这个,一开始想法是以流水叠加的方式,借助redis的incr生成一个流水订单号,可以增加前缀。如:2015081400001,后面五位数进行递增。


面试官:如果不想让别人根据订单号来统计流水呢。

这时候第一想法是每日定时生成一批订单,然后存放在redis/mysql,使用的时候进行获取即可。但是仍然无法解决随机获取的问题,随机key的话又要考虑互斥问题。所以想到使用incr的进行random 1-5之间的递增。然后以index去获取order id。


面试官:如果要保证这批订单号都能使用上呢。

对于最后的这个问题当时并没有答得出来。

之后问了下面试官,答题是跟我的思路类似,也是使用incr做index,当时没有想明白。因为按照好我的方式话保证不了随机获取,而且所有的订单号都能获取到。

==================================================================================================

晚上回来之后突然想到,其实思路没问题的,只是纠结在存在redis/mysql是顺序生成的订单号,所以获取的时候也只能顺序获取。mysql倒是有rand()函数,但是性能不好,而且会导致索引失效。 但其实可以生成订单号的时候程序可以进行打乱这批订单号再存储!这样就可以解决这个问题了。

直接上代码

<?php
// 每日生成的最大订单流水号, 可以根据实际应用进行调整
define('NUM', 1000);

// 链接redis
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);

$order = null;
$pre = date('Ymd');

// 生成订单流水数组
$arr = range(0, NUM);

// 数组乱序
shuffle($arr);

$redis->delete('order');

// 插入订单号进入redis
foreach ($arr as $i) {
    $order = $pre . str_pad($i, 5, 0, STR_PAD_LEFT);
    $redis->rPush('order', $order);
}


// 获取订单号
$orders = [];
for($i = 0; $i < 10000; $i++) {
    $orders[] = $redis->lPop('order');
}
var_dump($orders);



分类: 随笔 标签: 订单号生成