再问订单号生成算法?

主编 发布于 2015/01/21 15:34
阅读 7K+
收藏 15

业务场景,高并发,多用户操作

使用microtime生成的时间戳生成唯一订单序列号,事实上高并发情况下有一定的重复几率,就连uniqid($more_entropy参数为false)函数生成的序列号都可能有重复的可能(真坑爹),而$more_entropy设置为true的话返回的序列号又太长了

我想用:业务号+年月日+(当天订单数据+1)+用户ID

可是,光查询订单数量这一步就耗时210毫秒左右,太耗资源了

SELECT COUNT(nid)
  FROM `node`
 WHERE type= 'mobile_number'
   AND DATE_FORMAT(FROM_UNIXTIME(created), '%Y-%m-%d')= DATE_FORMAT(NOW(), '%Y-%m-%d')

请问,大家是如何处理这一问题的

------------------------------------------------------------------------

暂时使用@_Yud 同学的建议,添加个每天清表的事件

CREATE TABLE `order_seq` (
  `pkid` int(4) unsigned NOT NULL AUTO_INCREMENT,
  PRIMARY KEY (`pkid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8


drop event `com`.`truncate_1`;
CREATE EVENT `com`.`truncate_1` 
  ON SCHEDULE EVERY 1 DAY 
  STARTS  '2015-01-21 00:00:00'  ON COMPLETION NOT PRESERVE  
  ENABLE  
  COMMENT 'order_seq'  
  DO begin

/**event body**/
truncate table order_seq;

end



加载中
2
_
_Yud

order_seq:

pkid | autoincrement


insert into order_seq set pkid=null;

得到返回的主键为(当天订单数据+1)部分

每天对pkid做清0

主编
主编
有意思,符合我的设想
0
傲罗
傲罗
sql语句中尽量少使用函数,你可以在字段中加一个date字段,直接用日期查。
主编
主编
很好的建议,查订单数量,已经满足不了需求了
0
甘薯
甘薯

楼上的办法也可以, 或者楼主可以采用拆分字段的办法,

年月日+(当天订单数据+1)单独作为一个整数唯一索引存放, 对这种整数的查询是非常快的.

不过我还是质疑你的业务是否真的需要那么长的订单号...

主编
主编
这是为某运营商做的一个实名认证采集系统的子业务,它们要求要高逼格
0
你小舅子爱空姐
你小舅子爱空姐

搞个 Redis,年月日时分秒+(incr mod x) 保证不重复

赵伊凡
赵伊凡
+1,
0
聽雨人
聽雨人
我是用自增id作为单号。
public static function order_sign($type){
        $rs = static::caller()->_order_sign($type);
        return $rs->is_success()?$rs->data():false;
    }

    public static function id($order_sign){
        $id = (int) substr($order_sign,1);
        return self::BASE_NUMBER^$id;
    }

    public function _order_sign($type){
        if (!self::_check_type($type)) {
            return $this->result()->is_success(false);
        }
        #获取自增id
        $id = $this->_get_id();
        if (!$id) {
            return $this->result()->is_success(false);
        }
        return $this->result()->data(
            self::type_to_char($type).(self::BASE_NUMBER^$id)
        );
    }


获取id如下:

$id = $order_sign_table->insert(
            array(
                'id'=>null
            )
);




0
saintatgod
saintatgod
我们是 业务id + date('Ymd') + kid, kid每日清零,kid是自增的
0
零下三度
零下三度
生成的订单是否必须连续的,如果可以不连续的,你可以做一个数据库的配置,计算放在内存中,能够适用于分布式和高并发的情况下。数据库大致设计 keyId,minValue,currValue,maxValue,stepLen。将读取和更新放在一个事物中,每次更新的时候,currValue=currValue+stepLen,最好加上每个序列号在加上时间字符串作为前缀,这样随着你的业务发展并发高的时候,调整stepLen就行了,宕机的时候,把内存中的扔掉就可以了。
0
xialeistudio
xialeistudio

我的订单号是

年月日时分秒(14位)(6位随即字符串)

一起20位


0
陈洁新
陈洁新
我是这样的:Ymd 加时间戳后5位 ,加4位微秒数,加10到99的随机数,共19位。这样有重复的可能吗?
返回顶部
顶部