全局唯一ID设计方案 在分布式系统中,经常需要使用全局唯一ID查找对应的数据。产生这种ID需要保证系统全局唯一,而且要高性能以及占用相对较少的空间。

全局唯一ID在数据库中一般会被设成主键,这样为了保证数据插入时索引的快速建立,还需要保持一个有序的趋势。

这样全局唯一ID就需要保证这两个需求:
全局唯一
趋势有序
全局ID产生的几种方式

数据库自增
当服务使用的数据库只有单库单表时,可以利用数据库的auto_increment来生成全局唯一递增ID.

优势:
简单,无需程序任何附加操作
保持定长的增量
在单表中能保持唯一性

劣势:
高并发下性能不佳,主键产生的性能上限是数据库服务器单机的上限。
水平扩展困难,在分布式数据库环境下,无法保证唯一性。

UUID
一般的语言中会自带UUID的实现,比如Java中UUID方式UUID.randomUUID().toString(),可以通过服务程序本地产生,ID的生成不依赖数据库的实现。

优势:
本地生成ID,不需要进行远程调用。
全局唯一不重复。
水平扩展能力非常好。

劣势:
ID有128 bits,占用的空间较大,需要存成字符串类型,索引效率极低。
生成的ID中没有带Timestamp,无法保证趋势递增

Twitter Snowflake

snowflake是twitter开源的分布式ID生成算法,其核心思想是:产生一个long型的ID,使用其中41bit作为毫秒数,10bit作为机器编号,12bit作为毫秒内序列号。这个算法单机每秒内理论上最多可以生成1000*(2^12)个,也就是大约400W的ID,完全能满足业务的需求。

根据snowflake算法的思想,我们可以根据自己的业务场景,产生自己的全局唯一ID。因为Java中long类型的长度是64bits,所以我们设计的ID需要控制在64bits。

比如我们设计的ID包含以下信息:
| 41 bits: Timestamp | 3 bits: 区域 | 10 bits: 机器编号 | 10 bits: 序列号 |

产生唯一ID的Java代码:有修改

使用自定义的这种方法需要注意的几点:

为了保持增长的趋势,要避免有些服务器的时间早,有些服务器的时间晚,需要控制好所有服务器的时间,而且要避免NTP时间服务器回拨服务器的时间。
在跨毫秒时,序列号总是归0,会使得序列号为0的ID比较多,导致生成的ID取模后不均匀,所以序列号不是每次都归0,而是归一个0到9的随机数。
使用这个CustomUUID类,最好在一个系统中能保持单例模式运行。
原文地址:http://www.androidchina.net/4744.html