一线大厂的分布式唯一ID生成方案是什么样的?
一、前言
分布式系统中我们会对一些数据量大的业务进行分拆,如:用户表,订单表。因为数据量巨大一张表无法承接,就会对其进行分库分表。
整个系统ID唯一
ID是数字类型,而且是趋势递增的
ID简短,查询效率快
代码实现简单。
本机生成,没有性能问题
因为是全球唯一的ID,所以迁移数据容易
每次生成的ID是无序的,无法保证趋势递增
UUID的字符串存储,查询效率慢
存储空间大
ID本事无业务含义,不可读
类似生成token令牌的场景
不适用一些要求有趋势递增的ID场景
2.2、MySQL主键自增
数字化,id递增
查询效率高
具有一定的业务可读
存在单点问题,如果mysql挂了,就没法生成iD了
数据库压力大,高并发抗不住
2.3、MySQL多实例主键自增
解决了单点问题
一旦把步长定好后,就无法扩容;而且单个数据库的压力大,数据库自身性能无法满足高并发
数据不需要扩容的场景
2.4、雪花snowflake算法
1位标识符:始终是0
41位时间戳:41位时间截不是存储当前时间的时间截,而是存储时间截的差值(当前时间截 - 开始时间截 )得到的值,这里的的开始时间截,一般是我们的id生成器开始使用的时间,由我们程序来指定的
10位机器标识码:可以部署在1024个节点,如果机器分机房(IDC)部署,这10位可以由 5位机房ID + 5位机器ID 组成
12位序列:毫秒内的计数,12位的计数顺序号支持每个节点每毫秒(同一机器,同一时间截)产生4096个ID序号
此方案每秒能够产生409.6万个ID,性能快
时间戳在高位,自增序列在低位,整个ID是趋势递增的,按照时间有序递增
灵活度高,可以根据业务需求,调整bit位的划分,满足不同的需求
依赖机器的时钟,如果服务器时钟回拨,会导致重复ID生成
2.5、Redis生成方案
有序递增,可读性强
占用带宽,每次要向redis进行请求
2、单任务平均耗时:74ms
3、单线程最小耗时:不到1ms
4、单线程最大耗时:4.1s
2.6、小结
三、一线大厂是如何设计的呢?
一线大厂的设计思路其实和小伙伴们思路差不多,只是多想了1~2层,设计上面多了1~2个环节。
3.1、改造数据库主键自增
一旦步长定下来,不容易扩容
数据库压力山大
1、id表示为主键,无业务含义。 2、biz_tag为了表示业务,因为整体系统中会有很多业务需要生成ID,这样可以共用一张表维护 3、max_id表示现在整体系统中已经分配的最大ID 4、desc描述 5、update_time表示每次取的ID时间
1、【用户服务】在注册一个用户时,需要一个用户ID;会请求【生成ID服务(是独立的应用)】的接口 2、【生成ID服务】会去查询数据库,找到user_tag的id,现在的max_id为0,step=1000 3、【生成ID服务】把max_id和step返回给【用户服务】;并且把max_id更新为max_id = max_id + step,即更新为1000 4、【用户服务】获得max_id=0,step=1000; 5、 这个用户服务可以用ID=【max_id + 1,max_id+step】区间的ID,即为【1,1000】 6、【用户服务】会把这个区间保存到jvm中 7、【用户服务】需要用到ID的时候,在区间【1,1000】中依次获取id,可采用AtomicLong中的getAndIncrement方法。 8、如果把区间的值用完了,再去请求【生产ID服务】接口,获取到max_id为1000,即可以用【max_id + 1,max_id+step】区间的ID,即为【1001,2000】
3.2、竞争问题
如用户服务A,取到的max_id=1000 ;用户服务B取到的也是max_id=1000,那就出现了问题,Id重复了。那怎么解决?
3.3、突发阻塞问题
小伙伴就会问,有这么巧吗?同时ID用完。我们这里举的是3个用户服务,感觉概率不大;如果是100个用户服务呢?概率是不是一下子大了。
3.4、双buffer方案
1、当前获取ID在buffer1中,每次获取ID在buffer1中获取 2、当buffer1中的Id已经使用到了100,也就是达到区间的10% 3、达到了10%,先判断buffer2中有没有去获取过,如果没有就立即发起请求获取ID线程,此线程把获取到的ID,设置到buffer2中。 4、如果buffer1用完了,会自动切换到buffer2 5、buffer2用到10%了,也会启动线程再次获取,设置到buffer1中 6、依次往返
四、总结
此方案是某团使用的分布式ID算法,小伙伴们如果想了解更深,可以去网上搜下,这里应该介绍了比较详细了。
当然此方案美团还做了一些别的优化,监控ID使用频率,自动设置步长step,从而达到对ID节省使用。
作者:今日头条号, 老顾聊技术
编辑:Java后端技术
地址:www.toutiao.com/i6682672464708764174