分布式全局唯一ID與自增序列


包含時間順序的ID

此場景最簡單的實現方案,就是采用 twitter 的 Snowflake 算法。
ID總長64位,第1位不可用,41位表示時間戳,10位表示生成機器的id,后12位表示序列號。

  • 為什么第一位不可用?第一位為0,可以確保ID在java的long類型數據一直為正整數遞增
  • 同一時間戳即毫秒內,能產生多少個ID? 2^12 = 4096 個ID [ 0 ~ 4095 ]
  • 唯一性?通過機器ID預先已經做了一次空間隔離,再通過時間戳做了一次時間隔離,最后通過時間戳內的計數實現了一定程度內的唯一
  • 高性能?可以通過增加IDWorker來緩解高並發時的單機負載壓力
  • 缺點?時間受限,41位可以表示69年(不過可以減少機器位來增加時間位數)

自增序列

原理

根據key獲取分布式鎖,獲得鎖后取得序號,並偏移配置的偏移量,替換原先的序號,最后釋放鎖。

基於zookeeper實現

基於zookeeper可以很快實現自增序列服務,引入apache的curator封裝的zookeeper客戶端。

1
2
3
4
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
</dependency>

建立zookeeper連接,打開zkclient后,如果重復會使用,可以將其放入全局map中,作統一管理。

address:zookeeper的地址
RetryNTimes:重連策略(重連重試次數,重連間隔毫秒)

1
2
CuratorFramework zkClient =  CuratorFrameworkFactory.newClient(address,new RetryNTimes(10, 5000));
zkClient.start();

獲取分布式鎖
按照業務邏輯,選擇合適的鎖,此處用的是可重入共享鎖,即一個客戶端在擁有鎖的同時,可以再請求獲取。

大專欄  分布式全局唯一ID與自增序列="gutter">
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
InterProcessMutex lock = new InterProcessMutex(zkClient, lockPath);
try {
if (lock.acquire(time, unit)) {
consumer.accept(lockPath);
return true;
}
return false;
} catch (Exception e) {
logger.error(e.getMessage(), e);
} finally {
try {
lock.release();
} catch (Exception e) {
logger.error(e.getMessage(), e);
}
}
return false;

獲取下個序號
判斷序列名稱是否已經存在,如果不存在創建,存在則增加step並寫入

creatingParentsIfNeeded:當zk節點的父級不存在的時候,迭代創建
sequenceName:序列名稱
step:自增步長

1
2
3
4
5
6
7
8
9
String path = "/seq/"+sequenceName;
boolean exists = zkClient.checkExists().forPath(path) != null;
if (!exists) {
zkClient.create().creatingParentsIfNeeded().withMode(CreateMode.PERSISTENT).forPath(path, (step + "").getBytes());
} else {
byte[] bytes = zkClient.getData().forPath(path);
Long seq = Long.valueOf(new String(bytes));
zkClient.setData().forPath(path, (seq + step + "").getBytes());
}

因為需要實時修改zookeeper的節點信息,可以考慮建立序列池,例如直接取走10000個序列,由各個服務內部自己去生成,具體實現主要依賴到CAS,通過compareAndSet去實現單機內部的序號遞增,避免鎖的濫用


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM