uuid怎么获取_分布式下的主键是怎么生成的

作者:大军

来源:SegmentFault 思否 


数据库演进之路提到了当数据库的压力瓶颈到了,我们可以采用分库分表来分担数据库的压力,分库分表的情况下,主键是怎么设置的?

数据库主键自增长

正常情况下,如果每个数据库都自增长,那就会出现多个数据库id重复的问题,比如下图所示,都出现了id为1,2,3的主键。 905a04f0224476f147750f7224cb9520.png 为了避免上述的问题,我们可以在每个数据库设置一个初始值,以及设置每次的增量,如下图所示,第一个数据库初始值是1,增量是3,id就是1,4,7。
虽然避免了ID重复,但是id的递增是没有办法保证的,比如数据库1的id是1,4,7,10。数据库2的id是2,5,数据库3的id是3。而且后面如果要扩容,也是很麻烦。 e5ac3a3aa67d917a27b8b239de39a4bf.png 既然数据库本身没办法生成id,那我们可以用一个专门的数据库生成自增长的id。虽然id可以自增长,不重复,递增,但此时所有的压力都在生成id的数据库上。 b0b55bbd0a1563173f0143ebd9b22f13.png 为了缓解数据库的压力,可以一次性生成N个主键,比如100,然后存在缓存应用中,数据库每次需要id的时候,去缓存应用取。
缺点就是又多了一层服务。取一个自增长id要缓存服务+数据库。 b328720cba1eb6975709cf64c13610f6.png 上面的主键生成用redis行不行?虽然redis速度比较快,但是没有实时持久化,可能造成主键的重复。比如此时为9,incr后变成10,然后挂了,此时还没持久化,再生成id的时候还是9,然后incr为10,就有两个id为10的数据。即便做了故障转移,由于是异步同步数据的,有可能数据还没到slave,master就挂了,此时id还是会重复。
除了数据库的压力,自增长的主键还可能泄露商业机密,别人很容易拆到下一个主键是什么。

UUID

才用数据库生成主键,数据库压力就很大,那可以采用应用来生成。比较简单的就是UUID,性能好,不重复。缺点就是不能保证递增,而且UUID字符串比较长,索引性能很差。

时间戳

以当前毫秒作为主键,优点就是简单、递增,缺点就是可能重复。比如当前毫秒同时有10个并发,此时就重复了。为了减少重复,降低到微秒级别,或者在时间戳后面加个随机字符串,依然有重复的风险。

snowflake

snowflake是twitter开源的分布式ID生成算法,生成64位的bit,第一位是0,保证id是正数。后面41位是当前时间戳的二进制形式,再后面10位机器码的二进制,最后12位是计数顺序号,记录同一毫秒内生成的数量。 a5e346d28a7816ff9a7c6f484592681b.png 比如当前时间为2020-01-01 00:00:00,转换时间戳为1577808000000,再转二进制为10110111101011100101011110111010000000000。此时,前面42位为: 08f4ea200ef354ec618ba1c8779ff4c7.png 假设当前的机器码为100,转为二进制为1100100,由于不满10位,我们在前面补3个0,结果为0001100100。此时,前面52位为: 51b4e168075136ce7e101f1711c4c6ee.png 如果同一毫秒,同一个机器的并发比较大,此时生成的数据就有重复的,所以snowflake就有后面的12位作为计数器,比如第一个访问的是1,第二个访问的是2,假设我们此时为当前毫秒的第200个获取id的,200转为二进制为11001000,补0后为000011001000,此时,前面64位为: 8ed246e4a21610c40b86c6ef8246a1a0.png 如果觉得后面的12位不够,我们可以压缩前面机器码的位数,这样计数顺序号的值就可以更大了。
缺点也很明显,由于这个算法是依赖时间戳的,所以当系统的时间回拨的时候,就可能造成id的重复。
- END -

5581f2b3da5065138e4441c6847b2a34.png

5db7b76ff686dda5d913da8fa2b81e51.gif

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值