更新時(shí)間:2023-05-22 來源:黑馬程序員 瀏覽量:
在集群高并發(fā)環(huán)境下保證分布式唯一全局ID生成,可以使用雪花算法(Snowflake)來實(shí)現(xiàn)。雪花算法是Twitter提出的一種分布式ID生成算法,可以在分布式系統(tǒng)中生成唯一的、遞增的ID。接下來我們通過一段Python代碼來演示一下:
import time class SnowflakeIDGenerator: def __init__(self, worker_id, datacenter_id, sequence_bits=12): self.worker_id = worker_id self.datacenter_id = datacenter_id self.sequence_bits = sequence_bits self.worker_id_bits = 5 self.datacenter_id_bits = 5 self.max_worker_id = -1 ^ (-1 << self.worker_id_bits) self.max_datacenter_id = -1 ^ (-1 << self.datacenter_id_bits) self.max_sequence = -1 ^ (-1 << self.sequence_bits) self.worker_id_shift = self.sequence_bits self.datacenter_id_shift = self.sequence_bits + self.worker_id_bits self.timestamp_shift = self.sequence_bits + self.worker_id_bits + self.datacenter_id_bits self.sequence = 0 self.last_timestamp = -1 if self.worker_id > self.max_worker_id or self.worker_id < 0: raise ValueError("Worker ID must be between 0 and {}".format(self.max_worker_id)) if self.datacenter_id > self.max_datacenter_id or self.datacenter_id < 0: raise ValueError("Datacenter ID must be between 0 and {}".format(self.max_datacenter_id)) def generate_id(self): timestamp = self._get_timestamp() if timestamp < self.last_timestamp: raise ValueError("Invalid system clock. Clock moved backwards.") if timestamp == self.last_timestamp: self.sequence = (self.sequence + 1) & self.max_sequence if self.sequence == 0: timestamp = self._wait_next_millisecond(self.last_timestamp) else: self.sequence = 0 self.last_timestamp = timestamp generated_id = ( (timestamp << self.timestamp_shift) | (self.datacenter_id << self.datacenter_id_shift) | (self.worker_id << self.worker_id_shift) | self.sequence ) return generated_id def _get_timestamp(self): return int(time.time() * 1000) def _wait_next_millisecond(self, last_timestamp): timestamp = self._get_timestamp() while timestamp <= last_timestamp: timestamp = self._get_timestamp() return timestamp
使用示例:
generator = SnowflakeIDGenerator(worker_id=1, datacenter_id=1) for _ in range(10): generated_id = generator.generate_id() print(generated_id)
這段示例代碼演示了使用雪花算法生成唯一全局ID的過程。在創(chuàng)建SnowflakeIDGenerator對(duì)象時(shí),需要指定worker_id和datacenter_id,它們分別用于標(biāo)識(shí)工作節(jié)點(diǎn)和數(shù)據(jù)中心。然后,通過調(diào)用generate_id()方法即可生成一個(gè)唯一的ID。
請(qǐng)注意,這只是一個(gè)基本示例代碼,并沒有包含高并發(fā)環(huán)境下的分布式鎖機(jī)制。在實(shí)際的生產(chǎn)環(huán)境中,我們可能需要使用分布式鎖來確保在高并發(fā)環(huán)境下確保分布式唯一全局ID生成,我們可以結(jié)合雪花算法和分布式鎖機(jī)制來實(shí)現(xiàn)。以下是一個(gè)使用Redis作為分布式鎖的示例代碼:
import time import redis class SnowflakeIDGenerator: def __init__(self, worker_id, datacenter_id, sequence_bits=12): # 初始化雪花算法相關(guān)參數(shù) # 初始化Redis連接 self.redis_client = redis.Redis(host='localhost', port=6379) # 其他參數(shù)... def generate_id(self): lock_key = 'id_generator_lock' # 獲取分布式鎖 acquired_lock = self.redis_client.set(lock_key, 'lock', nx=True, ex=10) if not acquired_lock: raise ValueError("Failed to acquire the distributed lock.") try: # 生成ID邏輯... generated_id = ... return generated_id finally: # 釋放分布式鎖 self.redis_client.delete(lock_key)
在示例代碼中,我們使用了Redis作為分布式鎖的實(shí)現(xiàn)。在generate_id()方法中,首先嘗試獲取分布式鎖,即在Redis中設(shè)置一個(gè)特定的鍵(lock_key),并指定nx=True參數(shù)以確保只有一個(gè)線程能夠成功設(shè)置該鍵。如果獲取鎖成功,就可以執(zhí)行生成ID的邏輯;否則,拋出異?;蜻M(jìn)行相應(yīng)的處理。
在生成ID的邏輯中,我們可以繼續(xù)使用雪花算法的代碼邏輯,生成唯一的全局ID。在方法最后,無論是否生成成功,都需要釋放分布式鎖,即從Redis中刪除相應(yīng)的鍵。
需要注意的是,示例中使用了Redis作為分布式鎖的實(shí)現(xiàn),我們可以根據(jù)自己的實(shí)際情況選擇合適的分布式鎖實(shí)現(xiàn)方式,如ZooKeeper、etcd等。另外,示例代碼中省略了部分參數(shù)和細(xì)節(jié)實(shí)現(xiàn),我們可以根據(jù)自己的需求進(jìn)行適當(dāng)?shù)男薷暮脱a(bǔ)充。