過去的項目開發中,我們常常選用的資料庫是mysql,mysql以其體積小、速度快等優勢,備受中小型項目的青睐。随着項目資料量的迅速增長,mysql已無法滿足我們的項目需求,資料遷移迫在眉睫。經多方對比綜合考慮,我們選擇了tidb分布式資料庫。但是資料遷移後我們遇到一個問題,之前mysql資料庫中,我們采用的是自增id主鍵,可選用的tidb又對自增主鍵不是很友好,是以我們選用了另一種主鍵生成方式:Snowflake算法。
算法原理
SnowFlake算法是Twitter設計的一個可以在分布式系統中生成唯一的ID的算法,它可以滿足每秒上萬條消息ID配置設定的請求,這些消息ID是唯一的且有大緻的遞增順序。
SnowFlake算法産生的ID是一個64位的整型,結構如下:
第一位是辨別位,一般不使用,接下來的41位為毫秒級時間差(以1970年為起始時間,41位的長度可以使用69年,從1970-01-01 08:00:00,年 = (1L << 41) / (1000L * 60 * 60 * 24 * 365) = 69),然後是5位datacenterId(最大支援25=32個,二進制表示從00000-11111,也即是十進制0-31),和5位workerId(最大支援25=32個,原理同datacenterId),是以datacenterId*workerId最多支援部署1024個節點,最後12位是毫秒内的計數(12位的計數順序号支援每個節點每毫秒産生2^12=4096個ID序号)。
所有位數加起來共64位,恰好是一個Long型。
當然,實際使用過程中,時間戳、工作機id、序列号的位數是可以根據需要調整的。
優缺點
優點:
01
趨勢遞增:毫秒數在高位,序列号在低位
02
性能高無單點:本地計算不依賴資料庫等第三方
03
使用靈活:三個組成部分的位數可按需求調整
缺點:
01
序列不連續
02
無法控制生成規則(比如序列起始等)
03
強依賴機器時鐘,如果時鐘回撥,會導緻序列重複或者系統不可用
實作代碼
#coding: utf-8
import datetime
# 起始時間, 不能改變, 2020-04-10
twepoch = 1586448000000
datacenter_id_bits = 5
worker_id_bits = 15
sequence_id_bits = 2
max_datacenter_id = 1 << datacenter_id_bits
max_worker_id = 1 << worker_id_bits
max_sequence_id = 1 << sequence_id_bits
max_timestamp = 1 << (64 - datacenter_id_bits - worker_id_bits - sequence_id_bits)
def make_snowflake(timestamp_ms, datacenter_id, worker_id, sequence_id, twepoch=twepoch):
"""generate a twitter-snowflake id, based on
:param timestamp_ms: time since UNIX epoch in milliseconds
:param datacenter_id: exec ip
:param worker_id: process id,max is 32767, min is 0
:param sequence_id: thread id, max is 3, min is 0
:param twepoch: start time stamp
:return:
"""
sid = ((int(timestamp_ms) - twepoch) % max_timestamp) << datacenter_id_bits << worker_id_bits << sequence_id_bits
sid += (datacenter_id % max_datacenter_id) << worker_id_bits << sequence_id_bits
sid += (worker_id % max_worker_id) << sequence_id_bits
sid += sequence_id % max_sequence_id
效果
采用Snowflake算法後,資料id可以保持時間遞增并且全局唯一。
總結
Snowflake是分布式系統中,用來生成全局唯一ID的一種常用算法。和UUID相比,Snowflake具有簡單、占用空間小、有序等優點。但Snowflake算法也有它的弊端,時鐘回撥、時鐘錯亂問題,将是我們程式中需要考慮的問題。
[更多技術文章](https://qrcode.ceba.ceshiren.com/link?name=article&project_id=qrcode&from=toutiao×tamp=1662397200&author=Muller)