在分佈式系統中,有一些場景須要使用全局惟一 ID ,能夠和業務場景有關,好比支付流水號,也能夠和業務場景無關,好比分庫分表後須要有一個全局惟一 ID,或者用做事務版本號、分佈式鏈路追蹤等等,好的全局惟一 ID 須要具有這些特色:java
那麼分佈式場景下有哪些生成惟一 ID 的方案呢?node
先說最容易理解的方案,利用數據庫的自增加序列生成:數據庫生成惟一主鍵,並經過服務提供給其餘系統;若是是小型系統,數據總量和併發量都不是很大的狀況下,這種方案足夠支撐。web
若是每次生成一個 ID 可能會對數據庫有壓力,能夠考慮一次性生成 N 個 ID 放入緩存中,若是緩存中的 ID 被取光,再經過數據庫生成下一批 ID 。算法
利用 Redis / MongoDB / zookeeper 生成:Redis 利用 incr 和 increby ;MongoDB 的 ObjectId;zk 經過 znode 數據版本;均可以生成全局的惟一標識碼。數據庫
咱們用 MongoDB 的 ObjectId 來舉例:json
{"_id": ObjectId("5d47ca7528021724ac19f745")}
複製代碼
MongoDB 的 ObjectId 共佔 12 個字節,其中:緩存
不論是老版本仍是新版本,MongoDB 的 ObjectId 至少均可以保證集羣內的惟一,咱們能夠搭建一個全局惟一 ID 生成的服務,利用 MongoDB 生成 ObjectId 並對外提供服務(MongoDB 的各語言驅動都實現了 ObjectId 的生成算法)。安全
這個是分佈式架構中,生成惟一標識碼最經常使用的算法。爲了保證 UUID 的惟一性,生成因素包括了MAC地址、時間戳、名字空間(Namespace)、隨機或僞隨機數、時序等元素;UUID 有多個版本,每一個版本的算法不一樣,應用範圍也不一樣:網絡
public class CreateUUID {
public static void main(String[] args) {
String uuid = UUID.randomUUID().toString();
System.out.println("uuid : " + uuid);
uuid = UUID.randomUUID().toString().replaceAll("-","");
System.out.println("uuid : " + uuid);
}
}
複製代碼
若是但願 ID 能夠本地生成,可是又不要和 UUID 那樣無序,能夠考慮使用 Snowflake 算法(Twitter開源)。架構
SnowFlake 算法生成 ID 是一個 64 bit 的整數,包括:
在Java中,SnowFlake 算法生成的 ID 正好能夠用 long 來進行存儲。
此外,還有不少優秀的互聯網公司也提供了惟一 ID 生成的方案或框架,好比美團開源的 Leaf ,百度開源的 UidGenerator 等等。
@Resource
private UidGenerator uidGenerator;
@Test
public void testSerialGenerate() {
// Generate UID
long uid = uidGenerator.getUID();
System.out.println(uidGenerator.parseUID(uid));
}
複製代碼
會點代碼的大叔 | 文【原創】