背景
在分布式微服务系统中,通常需要全局唯一的序列号,需求实现简单高效,通常的做法可以用数据库的自增id,UUID生成等。但数据库自增id局限在于依赖于数据库表,在效率上有所折扣,尤其是高并发量的场景。而UUID一般比较长,关键是无序的。twitter的snowflake解决了这种需求,最初Twitter把存储系统从MySQL迁移到Cassandra,因为Cassandra没有顺序ID生成机制,所以开发了这样一套全局唯一ID生成服务。
snowflake结构
Bits | 名字 | 说明 |
---|---|---|
1 | 符号位 | 0,通常不使用 |
41 | 时间戳 | 精确到毫秒数,支持 2 ^41 /365/24/60/60/1000=69.7年 |
10 | 工作进程编号 | 支持 1024 个进程 |
12 | 序列号 | 每毫秒从 0 开始自增,支持 4096 个编号 |
snowflake生成的ID整体上按照时间自增排序,一共加起来刚好64位,为一个Long型(转换成字符串后长度最多19)。并且整个分布式系统内不会产生ID碰撞(由datacenter和workerId作区分),工作效率较高,经测试snowflake每秒能够产生26万个ID。
应用与实现
定义接口KeyGenerator,有方法generateKey()。实现类DefaultKeyGenerator,是默认的id生成器。对于工作线程的确定,可以借助通过 Zookeeper、Consul、Etcd 等提供分布式配置功能的中间件,也可以直接通过该机器的ip获取工作进程编号。
目前,国内很多大型互联网公司都是基于这种方式实现的id生成器,一些开元的分布式数据库中间件也是基于此算法实现数据库主键的,比如myCat, sharding-JDBC等。