单库的时候,主键唯一ID是自增的,现在好了,我们的数据被分到多个库的多个表里面了,如果我们还是使用之前的主键自增策略,那么这样就会出现两个数据插入到了两个不同的表会出现相同的ID值,这时我们该怎么去使用呢?

一.UUID

直接在业务代码中使用UUID,生成随机的主键。UUID是一种通用唯一识别码,是全球唯一的,不会重复,所以可以作为唯一主键使用,而且本机生成不耗费资源,目的是用于分布式环境中唯一生成标志码,是由32个16进制数组成.

主要包括三部分:
(1)当前日期和时间,UUID的第一个部分是当前日期和时间,如果你在生成一个UUID之后,过几秒又生成一个UUID,则第一个部分不同,其余相同。

(2)时钟序列

(3)全局唯一的IEEE机器识别号(如果有网卡,从网卡获得,没有网卡以其他方式获得)

UUID存在的问题:

  1. UUID字符串占用的空间比较大。
  2. 索引效率很低。每一次新的UUID数据的插入,为了查询的优化,都会对索引底层的b+树进行修改,因为UUID数据都是无序的,所以每一次UUID数据的插入都会对主键的b+树进行很大的修改,这一点很不好,插入完全无序,不但会导致一些中间节点产生分裂,也会白白创造出很多不饱和的节点,这样大大降低了数据库插入的性能。
  3. 做不了递增,如果要排序的话,基本不太可能。

二.redis

使用Redis生成ID,主要利用Redis是单线程的,所以也可以用来生成唯一ID。当使用的是Redis集群的时候,比如集群中有5台Redis,初始化每台Redis的值为1,2,3,4,5,设置步长为5,并且确定一个不随机的负载均衡策略,能够保证有序,唯一。

优点:不依赖数据库,灵活,且性能相对于数据库有一定提高;使用Redis集群策略还能排除单点故障问题;ID天然有序

缺点:如果系统中没有Redis,还需要引入新的组件;编码和配置工作量大。

三.设置步长

1.每个Id前面加上机器号
2.如果有3个机器,初始化值分别设置为1,2,3,然后步长设置为3,每次新ID生成都是上一个ID(同一个机器)+3。保证ID唯一性。

缺点:不方便加机器。

四.雪花算法

其核心思想是一个64位long型ID,使用41bit作为毫秒数,10bit作为机器的ID(5个bit是数据中心,5个bit的机器ID),12bit作为毫秒内的流水号(意味着每个节点在每毫秒可以产生 4096 个 ID),最后还有一个符号位,永远是0。具体实现的代码可以参看https://github.com/twitter/snowflake。可以根据自身需求进行一定的修改。

优点:不依赖数据库,灵活方便,性能优于数据库;ID按照时间在单机上是递增的

缺点:单机上递增,但是当分布式环境下每台机器的时钟不可能完全同步,有时并不能做做全局递增。