修改雪花算法生成唯一标识,对增加新的用户进行记录数据的生成

This commit is contained in:
wanglei 2025-10-22 08:46:41 +08:00
parent dcec20c66b
commit 1ad62eb252
4 changed files with 390 additions and 228 deletions

View File

@ -1,131 +1,146 @@
---
--- Generated by EmmyLua(https://github.com/EmmyLua)
--- Created by .
--- DateTime: 2025/9/25 08:19
--- 业务逻辑 对用户数据表进行数据表业务处理
local cjson = require('cjson')
local pgmoon = require('pgmoon')
local dbconf = require("config.database")
local status = require("config.status")
local _M = {}
--获取一个数据库操作连接
local function get_con(cfg)
local code = 0
-- 创建一个新的连接
local conn = pgmoon.new(cfg);
---- 连接到数据库
local ok, err = conn:connect()
if not ok then
print("Connection failed: " .. err)
code = 0x000002
end
--ngx.say("Connection success")
return code,conn
end
-- 查询数据表中的所有用户信息
function _M.getAllUser()
--组装sql语句
local sql = "select * from \"T_Users\""
--获取数据库连接
local code,conn = get_con(dbconf.postgres)
--设置数据库的编码格式
--conn:exec("SET NAMES UTF8")
--执行数据库操作
local res = conn:query(sql)
if not res then
print("get all users Query failed: "..sql)
return 0x000003,res
end
--整理数据库结果返回值
--for _, row in ipairs(res) do
-- for key, value in pairs(row) do
-- ngx.say(key .. ":" .. tostring(value))
-- end
--end
--关闭数据库
conn:disconnect()
return code,res
end
--根据用户id获取用户信息
function _M.getUser(id)
--组装sql语句
local sql = "select * from \"T_Users\" where id="..id
--获取数据库连接
local code,conn = get_con(dbconf.postgres)
--设置数据库的编码格式
--conn:exec("SET NAMES UTF8")
--执行数据库操作
local res = conn:query(sql)
if not res then
print("Query failed: "..sql)
return 0x000003,res
end
--关闭数据库
conn:disconnect()
return code,res
end
--增加用户信息到数据表
function _M.addUser(jsonData)
--ngx.say(jsonData)
local success, result = pcall(function()
return cjson.decode(jsonData)
end)
local res = nil
if success == false then
return 0x000001,res
end
--解析json中的键和数据值
local keys = ""
local values = ""
for key, value in pairs(result) do
keys = keys..key
local val = type(value)
if val == "string" then
values = values.."\'"..value.."\'"
else
values = values..value
end
keys = keys..","
values = values..","
end
local newKeys = keys:sub(1, #keys -1)
local newValues = values:sub(1, #values -1)
--组装sql语句
local sql = string.format("insert into \"T_Users\"(%s)values(%s)", newKeys, newValues)
--ngx.say(sql)
--获取数据库连接
local code,conn = get_con(dbconf.postgres)
--执行数据库操作
res = conn:query(sql)
if not res then
print("adduser sql failed: "..sql)
return 0x000003,res
end
--关闭数据库
conn:disconnect()
return code,res
end
--增加用户信息到数据表
function _M.delete_user(id)
--组装sql语句
local sql = "delete from \"T_Users\" where id="..id
--获取数据库连接
local code,conn = get_con(dbconf.postgres)
--执行数据库操作
local res = conn:query(sql)
if not res then
print("delete exec sql failed: "..sql)
return 0x000003,res
end
--关闭数据库
conn:disconnect()
return code,res
end
return _M
---
--- Generated by EmmyLua(https://github.com/EmmyLua)
--- Created by .
--- DateTime: 2025/9/25 08:19
--- 业务逻辑 对用户数据表进行数据表业务处理
local cjson = require('cjson')
local pgmoon = require('pgmoon')
local dbconf = require("config.database")
local status = require("config.status")
local snowflake = require("util.snowflake")
local _M = {}
--获取一个数据库操作连接
local function get_con(cfg)
local code = 0
-- 创建一个新的连接
local conn = pgmoon.new(cfg);
---- 连接到数据库
local ok, err = conn:connect()
if not ok then
print("Connection failed: " .. err)
code = 0x000002
end
--ngx.say("Connection success")
return code,conn
end
local function getUuid()
local workerId = 0 -- 假设当前机器的ID是1范围在[0, 31]之间
local datacenterId = 0 -- 数据中心ID范围在[0, 31]之间
local snow = snowflake.new(workerId, datacenterId)
local id = snow:generateUniqueId()-- 生成ID
--print("Generated ID:", snow.int64_to_string(id))
return snow.int64_to_string(id)
end
-- 查询数据表中的所有用户信息
function _M.getAllUser()
--组装sql语句
local sql = "select * from \"T_Users\""
--获取数据库连接
local code,conn = get_con(dbconf.postgres)
--设置数据库的编码格式
--conn:exec("SET NAMES UTF8")
--执行数据库操作
local res = conn:query(sql)
if not res then
print("get all users Query failed: "..sql)
return 0x000003,res
end
--整理数据库结果返回值
--for _, row in ipairs(res) do
-- for key, value in pairs(row) do
-- ngx.say(key .. ":" .. tostring(value))
-- end
--end
--关闭数据库
conn:disconnect()
return code,res
end
--根据用户id获取用户信息
function _M.getUser(id)
--组装sql语句
local sql = "select * from \"T_Users\" where id="..id
--获取数据库连接
local code,conn = get_con(dbconf.postgres)
--设置数据库的编码格式
--conn:exec("SET NAMES UTF8")
--执行数据库操作
local res = conn:query(sql)
if not res then
print("Query failed: "..sql)
return 0x000003,res
end
--关闭数据库
conn:disconnect()
return code,res
end
--增加用户信息到数据表
function _M.addUser(jsonData)
--ngx.say(jsonData)
local success, result = pcall(function()
return cjson.decode(jsonData)
end)
local res = nil
if success == false then
return 0x000001,res
end
--解析json中的键和数据值
local keys = ""
local values = ""
for key, value in pairs(result) do
keys = keys..key
local val = type(value)
if val == "string" then
values = values.."\'"..value.."\'"
else
values = values..value
end
keys = keys..","
values = values..","
end
--去掉组装最后一位逗号(,)
--local newKeys = keys:sub(1, #keys -1)
--local newValues = values:sub(1, #values -1)
--自己增加对应的uuid数据值
local newKeys = keys.."uuid"
local uuid = getUuid()
local newValues = values.."\'"..uuid.."\'"
--组装sql语句
local sql = string.format("insert into \"T_Users\"(%s)values(%s)", newKeys, newValues)
--ngx.say(sql)
--获取数据库连接
local code,conn = get_con(dbconf.postgres)
--执行数据库操作
res = conn:query(sql)
if not res then
print("adduser sql failed: "..sql)
return 0x000003,res
end
--关闭数据库
conn:disconnect()
return code,res
end
--增加用户信息到数据表
function _M.delete_user(id)
--组装sql语句
local sql = "delete from \"T_Users\" where id="..id
--获取数据库连接
local code,conn = get_con(dbconf.postgres)
--执行数据库操作
local res = conn:query(sql)
if not res then
print("delete exec sql failed: "..sql)
return 0x000003,res
end
--关闭数据库
conn:disconnect()
return code,res
end
return _M

View File

@ -1,51 +1,52 @@
---
--- Generated by EmmyLua(https://github.com/EmmyLua)
--- Created by admin.
--- DateTime: 2025/10/15 09:12
---
local calc = require("util.snowalgorithm")
local dataCenterId = 1 -- 根据实际情况配置数据中心 ID 和机器 ID
local machineId = 1 -- 同理配置机器 ID确保在所有机器中唯一且不超过最大值。
local id = calc.generateUuid(dataCenterId, machineId)
print("Generated UUID:", id)
--读取请求体的数据
ngx.req.read_body()
--获取请求数据
local body_data = ngx.req.get_body_data()
--if not body_data then
-- ngx.say("read file error:", err)
-- return ngx.exit(400)
--end
local len = #body_data
--local file_name = ngx.req.get_body_file()
ngx.say("file length:", len)
--ngx.req.read_body_in_buffer(ngx.var.request_body_file)
--ngx.say(body_data)
--local cjson = require("cjson")
--local file_path = "/home/frankly/work/test.dat"
--local file_length = 1024 * 1024 * 400
--local f, err = io.input(file_path, "r")
--if not f then
-- ngx.say("read file error:"..err)
-- return
--end
--local content = f:read(file_length) --读取文件内容
--f:close() --关闭文件
----ngx.say(content)
--local res = {
-- key = "data",
-- value = content
--}
----ngx.header["Length"] = #content
--ngx.header["Content-Type"] = 'application/json; charset=UTF-8'
--ngx.say(cjson.encode(res))
---
--- Generated by EmmyLua(https://github.com/EmmyLua)
--- Created by admin.
--- DateTime: 2025/10/15 09:12
---
local snowflake = require("util.snowflake")
local workerId = 0 -- 假设当前机器的ID是1范围在[0, 31]之间
local datacenterId = 0 -- 数据中心ID范围在[0, 31]之间
local snow = snowflake.new(workerId, datacenterId)
local id = snow:generateUniqueId()-- 生成ID
ngx.say("Generated ID:"..snow.int64_to_string(id))
--读取请求体的数据
--ngx.req.read_body()
--获取请求数据
--local body_data = ngx.req.get_body_data()
--if not body_data then
-- ngx.say("read file error:", err)
-- return ngx.exit(400)
--end
--local len = #body_data
--local file_name = ngx.req.get_body_file()
--ngx.say("file length:", len)
--ngx.req.read_body_in_buffer(ngx.var.request_body_file)
--ngx.say(body_data)
--local cjson = require("cjson")
--local file_path = "/home/frankly/work/test.dat"
--local file_length = 1024 * 1024 * 400
--local f, err = io.input(file_path, "r")
--if not f then
-- ngx.say("read file error:"..err)
-- return
--end
--local content = f:read(file_length) --读取文件内容
--f:close() --关闭文件
----ngx.say(content)
--local res = {
-- key = "data",
-- value = content
--}
----ngx.header["Length"] = #content
--ngx.header["Content-Type"] = 'application/json; charset=UTF-8'
--ngx.say(cjson.encode(res))
--ngx.log(ngx.INFO, "send data success")

View File

@ -1,47 +0,0 @@
---
--- Generated by EmmyLua(https://github.com/EmmyLua)
--- Created by admin.
--- DateTime: 2025/10/21 10:58
--- 雪花算法生成唯一的 ID
--具体使用方法
--local dataCenterId = 1 -- 根据实际情况配置数据中心 ID 和机器 ID
--local machineId = 1 -- 同理配置机器 ID确保在所有机器中唯一且不超过最大值。
--local id = generateUuid(dataCenterId, machineId)
--print("Generated ID:", id)
local _M = {}
local config = {
epoch = 1609459200000, -- 例如2021-01-01 的毫秒时间戳
dataCenterIdBits = 5,
machineIdBits = 5,
sequenceBits = 12, -- 序列号在毫秒内的唯一性
maxDataCenterId = -1 * math.pow(2, dataCenterIdBits),
maxMachineId = -1 * math.pow(2, machineIdBits),
maxSequence = -1 * math.pow(2, sequenceBits)
}
local function calculateOffsets()
local timestampShift = config.sequenceBits + config.machineIdBits + config.dataCenterIdBits
local dataCenterIdShift = config.sequenceBits + config.machineIdBits
local machineIdShift = config.sequenceBits
return {timestampShift = timestampShift, dataCenterIdShift = dataCenterIdShift, machineIdShift = machineIdShift}
end
local function currentTimeMillis()
return math.floor(os.time() * 1000) - config.epoch
end
function _M.generateUuid(dataCenterId, machineId)
local offsets = calculateOffsets()
local timestamp = currentTimeMillis()
local sequence = 0 -- 在实际应用中,你可能需要一个线程安全的序列号生成器来确保同一毫秒内的唯一性。
if sequence > config.maxSequence then return nil end -- 检查序列号是否溢出
local id = bit32.bor(bit32.lshift(timestamp, offsets.timestampShift),
bit32.lshift(dataCenterId, offsets.dataCenterIdShift),
bit32.lshift(machineId, offsets.machineIdShift),
sequence)
return id
end
return _M

193
src/util/snowflake.lua Normal file
View File

@ -0,0 +1,193 @@
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 = os.time()
return timestamp
end
--获取新的时间戳
function snowflake:getNextTimestamp(lastTimestamp)
local timestamp = math.floor(os.time());
while (timestamp <= lastTimestamp)
do
timestamp = math.floor(os.time());
end
return timestamp;
end
-- 雪花算法的实现
function snowflake:generateUniqueId()
--local curtime = os.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))