对飚雪花ID,高并发下唯一订单号生成器

xiaoxiaogo · · 248 次点击 · · 开始浏览    
## 背景 产品需求是为订单生成一个10位长度的订单号,可以包含字母和数组,字母不区分大小写。 我们可能想到雪花ID,是的,雪花ID设计很巧妙,但是长度太长不满足产品的需要,不过我们可以对雪花ID改造。 ```text 0000 0000 0 0 时间戳 机器ID 序列号 ``` 我们把10位分为3组: 第一组是前8位用做时间戳,由于是字母+数字组合,所以一位就能表示36个数字,0-9a-z,也就是36进制,36^8 = 2821109907456 毫秒 > 89年 * 365 * 24 *3600 * 1000 也就是精确到毫秒能用89年,不错啦。 第二组是机器ID,也是36进制,能用36个实例,基本够了。 第三组是序列号,也是36进制,那一个实例一毫秒最多36个订单号。 我们不难看出这不就是雪花的ID的变形吗,只不过我们支持字母+数字组合,所以就能缩小一些位数,是的,没错! ## 功能 我们再来看看上面我们提出的方案,基本能满足并发量不大的需求,当并发量实在太多可以多创建几个实例,一毫秒需要的订单号超过36个,那就再等下一毫秒呗。 如果就要钻牛角尖,就不愿意等下一毫秒,那我们就要对扩大第三组的限制了,如果再扩大一位就能每毫秒36X36=1296个了,如果再扩大一位那就能一毫秒36X36X36=46656个了,如果还不满足还可以继续,但是我觉得意义不大了。 扩展倒是很容易,但是产品得同意订单号位数变长啊,有的能同意,有的就难沟通了,所以这里我打算把每毫秒的最多数量做成能动态设置的。 另外,我们上面提到我们能用89年,如果从1970年开始那我们也就是能用到2059年,那很快了啊,怎么办?其实我们大可不必从1970年开始,从2000年开始不香吗?从2020年开始不更香吗? 这里我也打算做成可设置的,只是要注意下,项目开始就要决定从哪年开始,不然来回变化有可能重复咯。 ## 使用 这里我们给出go版本的使用,很简单,[https://github.com/xingliuhua/leaf](https://github.com/xingliuhua/leaf) ```go go get github.com/xingliuhua/leaf ``` ```go err, node := leaf.NewNode(0) if err != nil { return } // 每毫秒200个 err = node.SetGenerateIDRate(200) if err != nil { return } startTime := time.Date(2020, 0, 0, 0, 0, 0, 0, time.UTC).UnixNano() / 1000000 // 从2020年开始 err = node.SetSince(startTime) if err != nil { return } for i := 0; i < 40; i++ { err, id := node.NextId() if err != nil { return } fmt.Println(id) } ``` 当然node.SetSince,node.SetGenerateIDRate方法都可以不写,使用默认的也可以。 ## 总结 站在巨人的肩膀上,我们能看得更远,说是对飚雪花ID,其实就是借鉴的雪花ID,大家也可以根据自己的需求自己实现雪花ID。 最后能帮忙点个star吗? [https://github.com/xingliuhua/leaf](https://github.com/xingliuhua/leaf)

有疑问加站长微信联系

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:812540095

248 次点击  ∙  1 赞  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传