首页 Golang

电商生成订单号规则,高并发下生成订单号逻辑

pyweeX 发布于 02-27
Golang
pyweeX

每个公司都有其业务的特殊性,有些公司对生成订单号比较讲究,使用字母+数字组合的方式生成订单号。如果没什么特殊要求,使用纯数字就够了。

历史原因,早期工作中使用的订单号组成比较简单,主要格式就是年月日+若干位随机数。这种做法其实很随意,因为后来业务扩展很快,线上postgreSQL数据库时不时出现duplicate key value violates这类错误。也就是说生成订单号重复了,当有用户同时下单的时候,偶现了这类问题。

为了平滑扩展,重新修改了订单号生成规则,个人推荐一种比较规范的做法。


订单号生成规则

年月日时分秒+用户id+四位随机数,如果嫌太长的话,年份可以只取后面两位,这样总共就生成22位数字组成的订单号。

上述规则中的用户id可以根据自己的业务调整,如果用户量只有二、三十万,可以只取6位数,数字不够的情况下前面补0。比如,此时uid为1的用户下单,生成的订单号就是:2302271430590000010000

  1. // fetchOrderNum 生成订单号
  2. func fetchOrderNum() string {
  3. uid := 1
  4. uidChart := fmt.Sprintf("%06d", uid)
  5. return time.Now().Local().Format("060102150405") + uidChart + randChars(4)
  6. }
  7. // randChars 生成随机数字
  8. func randChars(l int, chs []byte) string {
  9. var bs []byte
  10. for i := 0; i < l; i++ {
  11. // 下种子一定要在循环内 否则容易出现随机数相同的情况
  12. rand.Seed(time.Now().UnixNano())
  13. bs = append(bs, chs[rand.Intn(len(chs))])
  14. }
  15. return string(bs)
  16. }

如果订单号还需要用作其他业务,还可以多加一个渠道号、平台类型,如:1表示安卓,2表示IOS等。

经过上述改造之后,在正常的下单场景中,订单号重复的几率几乎为0,因为它已经默认绑定了用户id。理论上而言,单个用户在如果在1秒内生成两个订单号,重复的概率为 1/9999。既兼顾了性能,又解决了重复问题。

对于订单号生成有十分要求,在高并发场景下也一定不允许重复的情况,可以预先通过脚本生成好一定量的订单号放入队列中,在抢购时从队列里取出即可,这种做法也可以防止商品超卖,例如,提前生成10个订单,列队为空时表示卖完了。

这种问题一般面试的时候问得比较多。

声明: 因编程语言版本更新较快,当前文章所涉及的语法或某些特性相关的信息并不一定完全适用于您当前所使用的版本,请仔细甄别。文章内容仅作为学习和参考,若有错误,欢迎指正。

讨论 支持 Markdown 语法 点击演示
回复
评论预览框

开发者

开发者·注册登录
  • 获取验证码
  • 取消