local bit = require("bit") --创建一个雪花算法的类 local snowflake = {} snowflake.__index = snowflake local sequence = 0 --序列号 -- 基础配置 local twepoch = 1420041600 -- 时间戳起点(2015-01-01) local workerIdBits = 5 -- 机器ID位数 local datacenterIdBits = 5 -- 数据中心ID位数 local timestampBits = 41 -- 时间戳位数 local sequenceBits = 12 -- 序列号位数 local max = math.pow(2, 32) --4294967296 local max_workerId = bit.lshift(1 , workerIdBits) - 1 local max_datacenterId = bit.lshift(1 , datacenterIdBits) - 1 -- 位移偏移量 local timestampShift = sequenceBits + workerIdBits + datacenterIdBits -- 时间戳左移22位 local datacenterIdShift = sequenceBits + datacenterIdBits -- 机器ID左移位数12位 local workerIdShift = sequenceBits -- 数据中心ID左移位数17位 -- 生成序列的掩码,这里为4095 (0b111111111111=0xfff=4095) local sequenceMask = bit.lshift(1, sequenceBits) - 1; --print("sequenceMask:", sequenceMask) local lastTimestamp = -1; --上次生成ID的时间戳 --大数据数据左移 local function bit_lshift(x, n) if n == 0 then return x end return x * (2 ^ n) end --大数据数据右移 local function bit_rshift(x, n) if n == 0 then return x end x = x % 2^32 -- 处理负数问题 local res = x / 2^n return res - res % 1 -- 取整操作,处理小数部分 end -- 将一个大整数转换为32位整数数组 local function split_into_32bit_chunks(n) local chunks = {} while n > 0 do table.insert(chunks, 1, n % 0x100000000) -- 取32位部分 n = math.floor(n / 0x100000000) -- 移除已处理的32位 end return chunks end -- 执行按位与操作 local function bitwise_and(a, b) local chunks_a = split_into_32bit_chunks(a) local chunks_b = split_into_32bit_chunks(b) local result = 0 local max_len = math.max(#chunks_a, #chunks_b) print("max_len:", max_len) for i = 0, max_len do local chunk_a = chunks_a[i] or 0 local chunk_b = chunks_b[i] or 0 result = result * 0x100000000 + bit.band(chunk_a, chunk_b) end return result end local function bitwise_or(num1, num2) local tmp1 = num1 local tmp2 = num2 local str = "" while (tmp1 ~= 0 or tmp2 ~= 0) do local bit1 = tmp1 % 2 local bit2 = tmp2 % 2 if bit1 == 0 and bit2 == 0 then str = "0" .. str elseif bit1 == 1 or bit2 == 1 then str = "1" .. str else str = "0" .. str end tmp1 = math.modf(tmp1 / 2) tmp2 = math.modf(tmp2 / 2) --print("tmp1:", tmp1) --print("tmp2:", tmp2) end return tonumber(str, 2) end local function format_number(n, base) local str = tostring(n) --print("str:", str) if base == 16 then -- 十六进制处理示例 return str:gsub("^0[xX]0*", "0x") -- 处理前导零和可能的'0x' elseif base == 10 then -- 十进制处理示例 --print("value11:", str:gsub("^%-0*", "")) --return str:gsub("^%-0*", "") -- 处理负数和前导零 return str:gsub("^0*([1-9]%d*)$", "%1") else -- 其他基数可以按需添加处理逻辑 return str -- 或者根据需要返回其他格式化结果 end end function snowflake.int64_to_string(n) local result = "" local base = 100000000 -- 选择一个基数,例如10^8 while n > 0 do local part = n % base result = string.format("%08d", part) .. result n = math.floor(n / base) end local value = format_number(result, 10) --print("value:", value) return value end --构造函数 function snowflake.new(workerId, datacenterId) if workerId < 0 then workerId = 0 end if workerId > max_workerId then workerId = max_workerId end if datacenterId < 0 then datacenterId = 0 end if datacenterId > max_datacenterId then datacenterId = max_datacenterId end local instance = {workerId = workerId, datacenterId = datacenterId} return setmetatable(instance, snowflake) end --获取当前时间戳(毫秒) function snowflake:getCurrentTimestamp() local timestamp = ngx.time() return timestamp end --获取新的时间戳 function snowflake:getNextTimestamp(lastTimestamp) local timestamp = math.floor(ngx.time()); while (timestamp <= lastTimestamp) do timestamp = math.floor(ngx.time()); end return timestamp; end -- 雪花算法的实现 function snowflake:generateUniqueId() --local curtime = ngx.time() --print("current time: ", curtime) local timestamp = self.getCurrentTimestamp() -- 当前时间戳(毫秒) -- 如果是同一时间生成的,则进行毫秒内序列 if lastTimestamp == timestamp then sequence = bit.band((sequence + 1), sequenceMask); -- 毫秒内序列溢出 if sequence == 0 then --阻塞到下一个毫秒,获得新的时间戳 timestamp = self.getNextTimestamp(lastTimestamp) end else sequence = 0 end lastTimestamp = timestamp; --print("sequence:", sequence) --print("lastTimestamp:", lastTimestamp) local current_time = lastTimestamp - twepoch --print("current time: ", current_time) -- 位运算生成ID --((timestamp - twepoch) << timestampLeftShift) local timeNew = bit_lshift(current_time, timestampShift) --print("timeNew: ", timeNew) --(datacenterId << datacenterIdShift) local centerIdNew = bit_lshift(self.datacenterId, datacenterIdShift) --print("centerIdNew: ", centerIdNew) --(workerId << workerIdShift) local workerIdNew = bit_lshift(self.workerId, workerIdShift) --print("workerIdNew: ", workerIdNew) --((timestamp - twepoch) << timestampLeftShift) --| (datacenterId << datacenterIdShift) --| (workerId << workerIdShift) | sequence --将相关数据值进行位或操作 local tmp1 = bitwise_or(timeNew, centerIdNew) local tmp2 = bitwise_or(tmp1, workerIdNew) local id = bitwise_or(tmp2, sequence) return id end return snowflake --使用方法示例 --local workerId = 0 -- 假设当前机器的ID是1,范围在[0, 31]之间 --local datacenterId = 0 -- 数据中心ID,范围在[0, 31]之间 --local test = snowflake.new(workerId, datacenterId) --local id = test:generateUniqueId()-- 生成ID --print("Generated ID:", test:int64_to_string(id))