数据库演进之路提到了当数据库的压力瓶颈到了,咱们能够采纳分库分表来分担数据库的压力,分库分表的状况下,主键是怎么设置的?
数据库主键自增长
失常状况下,如果每个数据库都自增长,那就会呈现多个数据库id反复的问题,比方下图所示,都呈现了id为1,2,3的主键。
为了防止上述的问题,咱们能够在每个数据库设置一个初始值,以及设置每次的增量,如下图所示,第一个数据库初始值是1,增量是3,id就是1,4,7。
尽管防止了ID反复,然而id的递增是没有方法保障的,比方数据库1的id是1,4,7,10。数据库2的id是2,5,数据库3的id是3。而且前面如果要扩容,也是很麻烦。
既然数据库自身没方法生成id,那咱们能够用一个专门的数据库生成自增长的id。尽管id能够自增长,不反复,递增,但此时所有的压力都在生成id的数据库上。
为了缓解数据库的压力,能够一次性生成N个主键,比方100,而后存在缓存利用中,数据库每次须要id的时候,去缓存利用取。
毛病就是又多了一层服务。取一个自增长id要缓存服务+数据库。
下面的主键生成用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位是计数顺序号,记录同一毫秒内生成的数量。
比方以后工夫为2020-01-01 00:00:00,转换工夫戳为1577808000000,再转二进制为10110111101011100101011110111010000000000。此时,后面42位为:
假如以后的机器码为100,转为二进制为1100100,因为不满10位,咱们在后面补3个0,后果为0001100100。此时,后面52位为:
如果同一毫秒,同一个机器的并发比拟大,此时生成的数据就有反复的,所以snowflake就有前面的12位作为计数器,比方第一个拜访的是1,第二个拜访的是2,假如咱们此时为以后毫秒的第200个获取id的,200转为二进制为11001000,补0后为000011001000,此时,后面64位为:
如果感觉前面的12位不够,咱们能够压缩后面机器码的位数,这样计数顺序号的值就能够更大了。
毛病也很显著,因为这个算法是依赖工夫戳的,所以当零碎的工夫回拨的时候,就可能造成id的反复
发表回复