mysql 分库分表确实能解决不少问题,也能让数据库支撑更大的并发、大数据量业务,可是分库分表后必然面对的一个问题就是 id 咋生成?id 生成后如何保持全局唯一性。
5.1)、数据库自增id
系统里每次得到一个 id,都是往一个库的一个表里插入一条没什么业务含义的数据,然后获取一个数据库自增的一个 id。拿到这个 id 之后再往对应的分库分表里去写入。这样确实可以解决,但是在高并发业务场景下,就会发生瓶颈,瞬间那一刻会出现脏数据。所以这个办法只能适合非高并发下的分表分库,如何生成全局id。
5.2)、uuid
本地生成,不要基于数据库来了;不好之处就是,uuid 太长了,作为主键性能太差了,不适合用于主键。
如果你是要随机生成个什么文件名了,编号之类的,你可以用 uuid,但是作为主键是不能用 uuid 的。
5.3)、获取当前系统时间
这个就是获取当前时间即可,但是问题是,并发很高的时候,比如一秒并发几千,会有重复的情况,这个是肯定不合适的。
一般如果用这个方案,是将当前时间跟很多其他的业务字段拼接起来,作为一个 id,如果业务上你觉得可以接受,那么也是可以的。你可以将别的业务字段值跟当前时间拼接起来,组成一个全局唯一的标识,订单号,时间戳 + 用户 id + 业务唯一标识。
5.4)、snowflake 算法*
在系统小时,唯一标识的产生,可以利用公用模块来处理,比如数据库表的唯一键、或者缓存的唯一 id 等等方式。但在分布式高并发的系统中,如果还是这样使用公共模块,就会产生很大的风险和瓶颈。
snowflake 是 Twitter 开源的分布式 ID 生成算法,结果是一个 long 型的 ID。其核心思想是:使用 41 bit 作为毫秒数,10 bit 作为机器的 ID(5 个 bit 是数据中心,5 个 bit 的机器 ID),12bit 作为毫秒内的流水号(意味着每个节点在每毫秒可以产生 4096 个 ID),最后还有一个符号位,永远是 0。
这个算法单机每秒内理论上最多可以生成 1000 * ( 2 ^ 12 ),也就是 409.6 万个 ID,(吼吼,这个得了的快啊)。