在互联网服务中,经常需要使用唯一ID。其中一个常见的应用场景是作为业务中请求的幂等ID。
分布式唯一ID生成方案
- uuid
- snowflake
- 包含业务属性的唯一ID,如 timestamp+ uid(10-11位)+ 随机3位数字(或递增)
- 其他方案
优劣不在这里讨论
业务场景分析
结合目前工作中的现状进行分析
- 唯一ID的存储方式:MySQL-bigint(20)
- 唯一ID生成方式:snowflake-64位:42位时间戳+5位机器码+5位进程worker标识码+12位自增id(42|5|5|12 = 64)
我们把幂等ID作为数据库的唯一键,从而保证幂等;而当数据量越来越大是,我们对数据按月进行分表,提升处理性能。
我们在数据库中除了有幂等ID(orderId)字段之外,还有添加时间字段(addTime);当请求进来之后,根据addTime找到相应的月表。所以实际上要保证请求处理幂等,依赖的是orderId+addTime 不变(或addTime保证始终落在同一个月)
为什么要依赖addTime保证幂等?
基础组件提供的唯一ID生成服务,对snowflake进行个性化的改造,只能保证ID是唯一的,然而ID的属性并不明显,无法方便的使用唯一ID进行分库(实际上snowflake算法的前n位是时间戳,可以考虑作为分库的属性)
一些常见唯一ID的例子
交易单号:4008722001201707283057762612 商户单号:2017072809364399365840049582 订单编号: 60310040822721833 支付宝交易号: 2017092021001001150522558267 大众点评订单号36611441412777832
像“商户单号”和“支付宝交易号”,很明显可以使用日期“基因”来分库,不过这种唯一ID不能使用bigint 存储,因为超过64位了
总结
一个好的唯一ID算法生成的ID,应该具备易用的“基因”。像UUID这种就不是很满足。