一、问题
1、分库分表之后,id主键如何处理?
分析:其实这是分库分表之后你必然要面对的一个问题,就是id咋生成?因为要是分成多个表之后,每个表都是从1开始累加,那肯定不对啊,需要1个全局唯一的id来支撑,所以这都是实际生产环境中必须要考虑的问题。
01_分库分表的主键id问题
逻辑上还是一张表,id都为1,这显然不符合要求。
二、方案
1、通过自增id
生成主键的库,全局1个。
这就是说,系统里每次得到一个id,都是往一个库里的一张表里插入一条没什么业务含义的数据,然后获取一个数据库自增的id。拿到这个id之后再往对应的分库分表里去写入。
这个方案的好处就是方便简单,谁都会用。缺点是单个库生成自增ID,要是高并发的话就会有瓶颈。如果你硬是要改进一下的话,那么就专门开1个服务出来。这个服务每次都拿到当前id的最大值,然后自己递增几个id,一次性返回一批id,然后再把最大id的值修改成递增几个id之后的一个值。但是无论怎么说都是基于单个数据库的。
适合的场景:你分库分表的原因,要么就是单库并发太高,要么就是单库数据量太多。如果你的并发不高,但是数据量太大就可以使用这个方案。因为可能每秒并发最高并发也就几百,那么就走单独单独一个库和表来生成主键自增id即可。
2、UUID
好处就是本地生成,不基于数据库,不好之处就是uuid太长了,作为主键性能太差了。不适合用于主键。适合的场景是:如果你要随机生成个文件名,编号之类的,你可以用uuid,但是作为主键是不能用uuid的。
3、雪花算法
哪个机房+哪个机器+当时的毫秒时间戳+当前毫秒的第几个请求。
雪花算法会判断一下,当前这个请求是否是机房17的机器25在某个时间点发过来的请求,如果是第一个请求。生成即可。如果同一机房、同一机器、在同一个毫秒内,再次要求生成1个id。只能加1。
给大家举个例子吧,比如下面那个 64 bit 的 long 型数字:
第一个部分,是 1 个 bit:0,这个是无意义的。
第二个部分是 41 个 bit:表示的是时间戳。
第三个部分是 5 个 bit:表示的是机房 id,10001。
第四个部分是 5 个 bit:表示的是机器 id,1 1001。
第五个部分是 12 个 bit:表示的序号,就是某个机房某台机器上这一毫秒内同时生成的 id 的序号,0000 00000000。