如何通過(guò)雪花算法用Python實(shí)現(xiàn)一個(gè)簡(jiǎn)單的發(fā)號(hào)器
實(shí)現(xiàn)一個(gè)簡(jiǎn)單的發(fā)號(hào)器
根據(jù)snowflake算法的原理實(shí)現(xiàn)一個(gè)簡(jiǎn)單的發(fā)號(hào)器,產(chǎn)生不重復(fù)、自增的id。
1.snowflake算法的簡(jiǎn)單描述

這里的snowflake算法是用二進(jìn)制的,有64位。其中41位的時(shí)間戳表示:當(dāng)前時(shí)間戳減去某個(gè)設(shè)定的起始時(shí)間,10位標(biāo)識(shí)表示:不同的機(jī)器、數(shù)據(jù)庫(kù)的標(biāo)識(shí)ID等等,序列號(hào)為每秒或每毫秒內(nèi)自增的id。
我做的時(shí)候沒(méi)有用位運(yùn)算去實(shí)現(xiàn),而是做了一個(gè)十進(jìn)制的,16位的(當(dāng)時(shí)項(xiàng)目要求是16位的)。但是實(shí)現(xiàn)發(fā)號(hào)器的基本策略是一樣的,通過(guò)時(shí)間戳和標(biāo)識(shí)來(lái)防止重復(fù),通過(guò)序列號(hào)實(shí)現(xiàn)自增。當(dāng)然啦,重點(diǎn)不是發(fā)號(hào)器多少位,而是根據(jù)項(xiàng)目的實(shí)際情況,利用snowflake算法的原理,實(shí)現(xiàn)一個(gè)適合自己項(xiàng)目的發(fā)號(hào)器。
2.Python實(shí)現(xiàn)
時(shí)間戳:9位,起始時(shí)間為2018-01-01 00:00:00 ,時(shí)間戳為當(dāng)前時(shí)間減去起始時(shí)間。時(shí)間戳有9為,可用時(shí)間為 999999999/(606024*365)≈31(年)。
標(biāo)識(shí)ID:2位,我用的時(shí)候比較簡(jiǎn)單,只是涉及一個(gè)數(shù)據(jù)庫(kù)的情況,所以用一張數(shù)據(jù)表對(duì)應(yīng)一個(gè)標(biāo)識(shí)ID,可用100張表。
序列號(hào):5位,我時(shí)間戳用的是秒級(jí)的,但是5位是10萬(wàn)個(gè)序列號(hào),經(jīng)過(guò)測(cè)試在一秒內(nèi)是完全夠用的。
所以時(shí)間戳、標(biāo)識(shí)ID、序列號(hào)的位數(shù)也沒(méi)規(guī)定說(shuō)一定要多少,根據(jù)自己項(xiàng)目的實(shí)際來(lái)即可。
代碼如下:
import time
class MySnow:
def __init__(self,dataID):
self.start = int(time.mktime(time.strptime('2018-01-01 00:00:00', "%Y-%m-%d %H:%M:%S")))
self.last = int(time.time())
self.countID = 0
self.dataID = dataID # 數(shù)據(jù)ID,這個(gè)自定義或是映射
def get_id(self):
# 時(shí)間差部分
now = int(time.time())
temp = now-self.start
if len(str(temp)) < 9: # 時(shí)間差不夠9位的在前面補(bǔ)0
length = len(str(temp))
s = "0" * (9-length)
temp = s + str(temp)
if now == self.last:
self.countID += 1 # 同一時(shí)間差,序列號(hào)自增
else:
self.countID = 0 # 不同時(shí)間差,序列號(hào)重新置為0
self.last = now
# 標(biāo)識(shí)ID部分
if len(str(self.dataID)) < 2:
length = len(str(self.dataID))
s = "0" * (2-length)
self.dataID = s + str(self.dataID)
# 自增序列號(hào)部分
if self.countID == 99999: # 序列號(hào)自增5位滿(mǎn)了,睡眠一秒鐘
time.sleep(1)
countIDdata = str(self.countID)
if len(countIDdata) < 5: # 序列號(hào)不夠5位的在前面補(bǔ)0
length = len(countIDdata)
s = "0"*(5-length)
countIDdata = s + countIDdata
id = str(temp) + str(self.dataID) + countIDdata
return id
使用方法:
snow = MySnow(dataID="00") print(snow.get_id())
其中dataID即為標(biāo)識(shí)ID,countID為自增序列號(hào)。dataID可以一個(gè)通過(guò)自定義的映射表獲得,這個(gè)視實(shí)際的項(xiàng)目情況而定。
3.關(guān)于并發(fā)
首先,直接用這個(gè)發(fā)號(hào)器是不能進(jìn)行并發(fā)操作,會(huì)產(chǎn)生重復(fù)的id。如果真的要進(jìn)行并發(fā),那么就要權(quán)衡一下并發(fā)和位數(shù)的哪個(gè)更重要了!
拿實(shí)際例子來(lái)說(shuō)吧,比如我并發(fā)的目的是為了節(jié)省時(shí)間,讓程序更快的跑完,這時(shí)候?yàn)榱瞬l(fā),我把dataID中拿出一位來(lái),標(biāo)識(shí)不同的子進(jìn)程,這樣可以防止產(chǎn)生重復(fù)的id。但是實(shí)際上這用了位數(shù)去換取時(shí)間,如果是id位數(shù)比較少的情況,比如16位的,dataID比較少,我個(gè)人認(rèn)為這樣是不值得的,有些奢侈。這時(shí)候便是位數(shù)比并發(fā)重要啦。
當(dāng)時(shí)如果位數(shù)充裕,比如20位的,需要并發(fā)就并發(fā)啦。
還有一種實(shí)現(xiàn)并發(fā)的方法,就是給發(fā)號(hào)器加鎖,發(fā)號(hào)的時(shí)候加鎖,發(fā)完了解鎖。這個(gè)我沒(méi)有試過(guò),有興趣的可以試一下哈哈。但是我有個(gè)疑惑啊,就是不斷加鎖和解鎖切換,帶來(lái)的時(shí)間和資源開(kāi)銷(xiāo)會(huì)不會(huì)很大呢。
相關(guān)文章
使用python進(jìn)行圖片的文字識(shí)別詳細(xì)代碼
Tesseract OCR是一款由Google團(tuán)隊(duì)開(kāi)發(fā)的開(kāi)源OCR引擎,用于將圖片、PDF 等格式中的文本轉(zhuǎn)換為可編輯的文本格式,本文主要介紹了Python進(jìn)行圖片的文字識(shí)別功能OCR的相關(guān)知識(shí),需要的朋友可以參考下2023-05-05
使用selenium模擬動(dòng)態(tài)登錄百度頁(yè)面的實(shí)現(xiàn)
本文主要介紹了使用selenium模擬動(dòng)態(tài)登錄百度頁(yè)面,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-05-05
Python?對(duì)象拷貝及深淺拷貝區(qū)別的詳細(xì)教程示例
這篇文章主要介紹了Python?對(duì)象拷貝及深淺拷貝區(qū)別的詳細(xì)教程示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-03-03
Python繪制圣誕樹(shù)+落葉+雪花+背景音樂(lè)+浪漫彈窗?五合一版圣誕樹(shù)
馬上不就到圣誕節(jié)了嘛,我看到朋友圈里很多小伙伴再紛紛炫耀自己收到的專(zhuān)屬圣誕樹(shù),今天小編給大家介紹的是通過(guò)Python繪制的五合一版圣誕樹(shù):圣誕樹(shù)+落葉+雪花+背景音樂(lè)+浪漫彈窗。感興趣的小伙伴快來(lái)學(xué)習(xí)一下吧2021-12-12
如何解決MNIST數(shù)據(jù)集下載速度較慢并失敗的問(wèn)題
這篇文章主要介紹了如何解決MNIST數(shù)據(jù)集下載速度較慢并失敗的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-06-06
通過(guò)實(shí)例解析python subprocess模塊原理及用法
這篇文章主要介紹了通過(guò)實(shí)例解析python subprocess模塊原理及用法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-10-10
使用pytorch實(shí)現(xiàn)可視化中間層的結(jié)果
今天小編就為大家分享一篇使用pytorch實(shí)現(xiàn)可視化中間層的結(jié)果,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2019-12-12

