分布式系统全局惟一ID生成

一 什么是分布式系统惟一ID

在复杂分布式系统中,每每须要对大量的数据和消息进行惟一标识。node

如在金融、电商、支付、等产品的系统中,数据日渐增加,对数据分库分表后须要有一个惟一ID来标识一条数据或消息,数据库的自增ID显然不能知足需求,此时一个可以生成全局惟一ID的系统是很是必要的。算法

2、分布式系统惟一ID的特色

 

  1. 全局惟一性:不能出现重复的ID号,既然是惟一标识,这是最基本的要求。
  2. 趋势递增:在MySQL InnoDB引擎中使用的是汇集索引,因为多数RDBMS使用B-tree的数据结构来存储索引数据,在主键的选择上面咱们应该尽可能使用有序的主键保证写入性能。
  3. 单调递增:保证下一个ID必定大于上一个ID,例如事务版本号、IM增量消息、排序等特殊需求。
  4. 信息安全:若是ID是连续的,恶意用户的扒取工做就很是容易作了,直接按照顺序下载指定URL便可;若是是订单号就更危险了,竞对能够直接知道咱们一天的单量。因此在一些应用场景下,会须要ID无规则、不规则。

同时除了对ID号码自身的要求,业务还对ID号生成系统的可用性要求极高,想象一下,若是ID生成系统瘫痪,这就会带来一场灾难。数据库

由此总结下一个ID生成系统应该作到以下几点:安全

  1. 平均延迟和TP999延迟都要尽量低(TP90就是知足百分之九十的网络请求所须要的最低耗时。TP99就是知足百分之九十九的网络请求所须要的最低耗时。同理TP999就是知足千分之九百九十九的网络请求所须要的最低耗时);
  2. 可用性5个9(99.999%);
  3. 高QPS。

补充:QPS和TPS

QPS:Queries Per Second意思是“每秒查询率”,是一台服务器每秒可以相应的查询次数,是对一个特定的查询服务器在规定时间内所处理流量多少的衡量标准。
TPS:是TransactionsPerSecond的缩写,也就是事务数/秒。它是软件测试结果的测量单位。一个事务是指一个客户机向服务器发送请求而后服务器作出反应的过程。客户机在发送请时开始计时,收到服务器响应后结束计时,以此来计算使用的时间和完成的事务个数服务器

3、分布式系统惟一ID的实现方案

1.UUID

UUID(Universally Unique Identifier)的标准型式包含32个16进制数字,以连字号分为五段,形式为8-4-4-4-12的36个字符,示例:550e8400-e29b-41d4-a716-446655440000,到目前为止业界一共有5种方式生成UUID,详情见IETF发布的UUID规范 A Universally Unique IDentifier (UUID) URN Namespace。网络

优势:数据结构

  • 性能很是高:本地生成,没有网络消耗。

缺点:并发

  • 不易于存储:UUID太长,16字节128位,一般以36长度的字符串表示,不少场景不适用。
  • 信息不安全:基于MAC地址生成UUID的算法可能会形成MAC地址泄露,这个漏洞曾被用于寻找梅丽莎病毒的制做者位置。
  • ID做为主键时在特定的环境会存在一些问题,好比作DB主键的场景下,UUID就很是不适用

2.数据库生成

以MySQL举例,利用给字段设置auto_increment_increment和auto_increment_offset来保证ID自增,每次业务使用下列SQL读写MySQL获得ID号。分布式

 

这种方案的优缺点以下:高并发

优势:

  • 很是简单,利用现有数据库系统的功能实现,成本小,有DBA专业维护。
  • ID号单调自增,能够实现一些对ID有特殊要求的业务。

缺点:

  • 强依赖DB,当DB异常时整个系统不可用,属于致命问题。配置主从复制能够尽量的增长可用性,可是数据一致性在特殊状况下难以保证。主从切换时的不一致可能会致使重复发号。
  • ID发号性能瓶颈限制在单台MySQL的读写性能。

3.Redis生成ID

当使用数据库来生成ID性能不够要求的时候,咱们能够尝试使用Redis来生成ID。

这主要依赖于Redis是单线程的,因此也能够用生成全局惟一的ID。能够用Redis的原子操做 INCR和INCRBY来实现。

比较适合使用Redis来生成天天从0开始的流水号。好比订单号=日期+当日自增加号。能够天天在Redis中生成一个Key,使用INCR进行累加。

优势:

1)不依赖于数据库,灵活方便,且性能优于数据库。

2)数字ID自然排序,对分页或者须要排序的结果颇有帮助。

缺点:

1)若是系统中没有Redis,还须要引入新的组件,增长系统复杂度。

2)须要编码和配置的工做量比较大。

4.利用zookeeper(分布式应用程序协调服务)生成惟一ID

zookeeper主要经过其znode数据版原本生成序列号,能够生成32位和64位的数据版本号,客户端可使用这个版本号来做为惟一的序列号。

不多会使用zookeeper来生成惟一ID。主要是因为须要依赖zookeeper,而且是多步调用API,若是在竞争较大的状况下,须要考虑使用分布式锁。所以,性能在高并发的分布式环境下,也不甚理想。

5.snowflake(雪花算法)方案

这种方案大体来讲是一种以划分命名空间(UUID也算,因为比较常见,因此单独分析)来生成ID的一种算法,这种方案把64-bit分别划分红多段,分开来标示机器、时间等,好比在snowflake中的64-bit分别表示以下图(图片来自网络)所示:

41-bit的时间能够表示(1L<<41)/(1000L*3600*24*365)=69年的时间,10-bit机器能够分别表示1024台机器。若是咱们对IDC划分有需求,还能够将10-bit分5-bit给IDC,分5-bit给工做机器。这样就能够表示32个IDC,每一个IDC下能够有32台机器,能够根据自身需求定义。12个自增序列号能够表示2^12个ID,理论上snowflake方案的QPS约为409.6w/s,这种分配方式能够保证在任何一个IDC的任何一台机器在任意毫秒内生成的ID都是不一样的。

这种方式的优缺点是:

优势:

  • 毫秒数在高位,自增序列在低位,整个ID都是趋势递增的。
  • 不依赖数据库等第三方系统,以服务的方式部署,稳定性更高,生成ID的性能也是很是高的。
  • 能够根据自身业务特性分配bit位,很是灵活。

缺点:

  • 强依赖机器时钟,若是机器上时钟回拨,会致使发号重复或者服务会处于不可用状态。
相关文章
相关标签/搜索