分布式系统中全局ID生成策略思考

-- Pageviews

snowflake

在我们的实际开发过程中,几乎所有的业务场景所产生的数据都需要一个唯一ID作为核心标识,用来流程化管理。比如常见的:

  • 订单:order_no, 查订单详情,物流状态等;
  • 支付:trade_no, 查询支付流水,支付状态等;
  • 短信:template_no, 查询短信模板详情;
  • 任务:task_no, 查询任务详情,任务状态等;
  • 版本:version, 数据的版本管理;

那么如何生成的唯一标识呢?网上大部分博客都会介绍UUID,SnowFlake算法、以及类雪花算法MongoDB ObjectId的生成算法。传送门

笔者的看法是,在考虑高效、全局唯一、安全等技术层面的同时,还应在不同使用场景中使用不同的唯一标识生成算法。

有规律

关键对象构建唯一标识

这种常被用在业务属性较强的场景,如订单编号order_no、支付流水号trade_no等。当然,此时生成无规律的唯一标识作为订单号或者流水号不是不可以,只是有规律的唯一标识可能会更好。

如下是一种生成订单编号算法的一个举例

DD前缀+8位用户标识+8位商品标识+2位购买次数 (位数不足要补足)

可以看出,这种生成方式生成的字串是有规律,拿到一个订单编号,就可知道多少位是用户标识,多少位是商品标识,不用查询订单相信信息即可获取两种关键对象标识,便于查问题和调试,同时后两位也标识了当前是指定用户多少次购买了。

同时该种设计,可以在数据库索引设计中使用前缀索引或者后缀索引,节省数据库索引空间和搜索效率。

自增唯一标识

这种常用于技术属性较强但需要限制长度的场景,如短信模板编号template_no、短链code等等,这种就是要求尽量短。

常用的方式

redis key inc --> 转换62进制编码

为什么是62进制?0-9,a-z,A-Z 刚好62位。其长度受限于位数限制,拿一个6位字符来说,其上限为62的5次方减一。

无规律

这种常用于技术属性较强场景,如版本号等。

相关的算法有上述说的 UUID,SnowFlake算法、以及类雪花算法MongoDB ObjectId的生成算法,此处不详述。