有哪些問題?
時(shí)鐘回?fù)軉栴};
趨勢遞增,而不是絕對(duì)遞增;
不能在一臺(tái)服務(wù)器上部署多個(gè)分布式ID服務(wù);
如何解決時(shí)鐘回?fù)?
以百度的UidGenerator為例,CachedUidGenerator方式主要通過采取如下一些措施和方案規(guī)避了時(shí)鐘回?fù)軉栴}和增強(qiáng)唯一性:
自增列:UidGenerator的workerId在實(shí)例每次重啟時(shí)初始化,且就是數(shù)據(jù)庫的自增ID,從而完美的實(shí)現(xiàn)每個(gè)實(shí)例獲取到的workerId不會(huì)有任何沖突。
RingBuffer:UidGenerator不再在每次取ID時(shí)都實(shí)時(shí)計(jì)算分布式ID,而是利用RingBuffer數(shù)據(jù)結(jié)構(gòu)預(yù)先生成若干個(gè)分布式ID并保存。
時(shí)間遞增:傳統(tǒng)的雪花算法實(shí)現(xiàn)都是通過System.currentTimeMillis()來獲取時(shí)間并與上一次時(shí)間進(jìn)行比較,這樣的實(shí)現(xiàn)嚴(yán)重依賴服務(wù)器的時(shí)間。而UidGenerator的時(shí)間類型是AtomicLong,且通過incrementAndGet()方法獲取下一次的時(shí)間,從而脫離了對(duì)服務(wù)器時(shí)間的依賴,也就不會(huì)有時(shí)鐘回?fù)艿膯栴}
(這種做法也有一個(gè)小問題,即分布式ID中的時(shí)間信息可能并不是這個(gè)ID真正產(chǎn)生的時(shí)間點(diǎn),例如:獲取的某分布式ID的值為3200169789968523265,它的反解析結(jié)果為{"timestamp":"2019-05-02 23:26:39","workerId":"21","sequence":"1"},但是這個(gè)ID可能并不是在"2019-05-02 23:26:39"這個(gè)時(shí)間產(chǎn)生的)。