在分布式集群环境环境中,大量的业务场景需要使用到唯一ID的情况,如用户需要唯一身份标识、商品需要唯一标识、消息需要唯一标识、事件需要唯一标识等,都需要全局唯一ID,尤其是复杂的分布式业务场景中全局唯一ID更为重要那么,分布式唯一ID有哪些特性或要求呢?
① 唯一性:生成的ID全局唯一,在特定范围内冲突概率极小。
② 有序性:生成的ID按某种规则有序,便于数据库插入及排序。
③ 可用性:可保证高并发下的可用性, 确保任何时候都能正确的生成ID。
④ 自主性:分布式环境下不依赖中心认证即可自行生成ID。
⑤ 安全性:不暴露系统和业务的信息, 如:订单数,用户数等。
总的来说,大概有三大类方法,分别是:
数据库自增ID、
UUID生成、
redis生成、
snowflake雪花算法。
1、【数据库自增长ID】
【优缺点】
优点: 非常简单,有序递增,方便分页和排序;
缺点: 分库分表后,同一数据表的自增ID容易重复,无法直接使用(可以设置步长,但局限性很明显);性能吞吐量整个较低;ID号码不够随机,能够泄露发号数量的信息,不太安全。
【使用场景】
单数据库实例的表ID(包含主从同步场景),部分按天计数的流水号等;分库分表场景、全系统唯一性ID场景不适用
2、UUID生成
【生成原理】
UUID生成id需要用到以太网卡地址、纳秒级时间、芯片ID码和许多可能的数字。其生成的id由当前日期和时间(UUID的第一个部分与时间有关,如果你在生成一个UUID之后,过几秒又生成一个UUID,则第一个部分不同,其余相同),时钟序列,全局唯一的IEEE机器识别号。
【优缺点】
优点: 不依赖任何数据源,自行计算,没有网络ID,速度超快,并且全球唯一;
缺点: 没有顺序性,并且比较长(128bit),作为数据库主键、索引会导致索引效率下降,空间占用较多。
【使用场景】
只要对存储空间没有苛刻要求的都能够适用,比如各种链路追踪、日志存储等。
3、redis生成id
【生成原理】
依赖redis的数据源,通过redis的incr/incrby自增院子操作命令,能保证生成id肯定是唯一有序的,本质生成方式与数据库一致。
【优缺点】
优点: 整体吞吐量比数据库要高;
缺点:Redis是基于内存的数据库,其实例或集群宕机后,找回最新的ID值有点困难。由于使用自增,对外容易暴露业务数据总量
【应用场景】
比较适合计数场景,如用户访问量,订单流水号(日期+流水号)等。
4、雪花算法snowflake
【实现原理】
属于半依赖数据源方式,原理是使用Long类型(64位),按照一定的规则进行填充:时间(毫秒级)+集群ID+机器ID+序列号,每部分占用的位数可以根据实际需要分配,其中集群ID和机器ID这两部分,在实际应用场景中要依赖外部参数配置或数据库记录。
【优缺点】
优点: 高性能、低延迟、去中心化、按时间有序;
缺点: 要求机器时钟同步(到秒级即可),即时间回拨 会导致id重复。
【使用场景】
分布式应用环境的数据主键,大多数使用雪花算法来实现分布式id。
【如何解决时间回拨问题】
时间回拨是指,当机器出现问题,时间可能回到之前,此时雪花算法生成的id可能与之前的id值相同,从而导致id重复
【解决方式】
1、系统抛出异常,运维来手动调整时间;
2、延迟等待,对于偶然性的时间回拨,也许是机器出现了一次小故障,频繁出现的概率并不大,所以对于这种情况没必要中断业务,可以采用阻塞线程5ms,再获取时间,对比看时间是否比上一次请求的时间大,如果大了,说明恢复正常了,则不用管;如果还小,说明真出问题了,则抛出异常,呼唤程序员处理
3、备用机方式来解决,当前机器出现问题,迅速换一台机器,通过高可用解决