思路
1、数据库自增长ID(mysql, redis, mongodb)
优势:无需编码
缺陷:大表不能做水平分表,否则插入删除时容易出现问题
高并发下插入数据需要加入事务机制
在业务操作父、子表(关联表)插入时,先要插入父表,再插入子表
2、本地hash模式,时间戳+随机数, 时间戳+会员ID, md5的update方式
优势:编码简单
缺陷:随机数存在重复问题,即使在相同的时间戳下。每次插入数据库前需要校验下是否已经存在相同的数值。
4、GUID/UUID
优势:简单
劣势:用户不友好,索引关联效率较低。还是会有重复的存在。
5、snowflake算法方式
time – 41 bits + configured machine id – 10 bits + sequence number – 12 bits的形式分配id,共63位,最高部分使用毫秒级的时间戳,保证了一定程度的有序性,机器标示使用10位,最多可容纳1024个分配器,最后的12位序列号可以支持在1ms内产生4096个不重复的id。但是这对服务器的时间依赖性很强。
实战
uuid+时间戳方式
import time
import uuid
def custom_uuid():
timestamp_41 = str(int(time.time() * 10000000000000000000000000000000))
jid = str(uuid.uuid3(uuid.NAMESPACE_DNS, timestamp_41))
return jid
while 1:
print(custom_uuid())
效果
py版snowflake算法模拟版
import datetime
import time
import random
class SnowflakeId:
def __init__(self):
# twitter's snowflake parameters
self.twepoch = random.randint(1, 100)
self.datacenter_id_bits = 5
self.worker_id_bits = 5
self.sequence_id_bits = 12
# 1 << datacenter_id_bits
self.max_datacenter_id = 32
# 1 << worker_id_bits
self.max_worker_id = 32
# 1 << sequence_id_bits
self.max_sequence_id = 4096
# 1 << (64 - datacenter_id_bits - worker_id_bits - sequence_id_bits)
self.max_timestamp = 4398046511104
def make_snowflake(self, timestamp_ms, datacenter_id, worker_id, sequence_id,):
sid = ((int(timestamp_ms) - self.twepoch) % self.max_timestamp) << self.datacenter_id_bits << self.worker_id_bits << self.sequence_id_bits
sid += (datacenter_id % self.max_datacenter_id) << self.worker_id_bits << self.sequence_id_bits
sid += (worker_id % self.max_worker_id) << self.sequence_id_bits
sid += sequence_id % self.max_sequence_id
return sid
def melt(self, snowflake_id):
sequence_id = snowflake_id & (self.max_sequence_id - 1)
worker_id = (snowflake_id >> self.sequence_id_bits) & (self.max_worker_id - 1)
datacenter_id = (snowflake_id >> self.sequence_id_bits >> self.worker_id_bits) & (self.max_datacenter_id - 1)
timestamp_ms = snowflake_id >> self.sequence_id_bits >> self.worker_id_bits >> self.datacenter_id_bits
# timestamp_ms += self.twepoch
return (timestamp_ms, datacenter_id, worker_id, sequence_id)
def local_datetime(self, timestamp_ms):
return datetime.datetime.fromtimestamp(timestamp_ms / 1000.)
def handle(self):
t0 = int(time.time() * 1000)
uuid = self.melt(self.make_snowflake(t0, 1, 0, 0))[0]
return uuid
if __name__ == '__main__':
while 1:
uuid = SnowflakeId().handle()
print(uuid)
效果