Skip to content

Commit

Permalink
support snowflake
Browse files Browse the repository at this point in the history
  • Loading branch information
huahua132 committed Nov 14, 2024
1 parent 5ddeeea commit c5b8525
Show file tree
Hide file tree
Showing 4 changed files with 134 additions and 0 deletions.
87 changes: 87 additions & 0 deletions lualib/skynet-fly/snowflake.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
local service = require "skynet.service"
local skynet = require "skynet"

--雪花算法 用于生成唯一ID
local function snowflake_service()
local log = require "skynet-fly.log"
local skynet = require "skynet"
local skynet_util = require "skynet-fly.utils.skynet_util"

local assert = assert
local os = os
local tostring = tostring
local fmt = string.format

local MACHINE_ID_BIT = 13 --机器号位数 最大支持配置 8191
local TIME_BIT = 32 --时间位数 最大到时间 21060207 14:28:15
local INCR_BIT = 18 --自增序号数 最大同一秒分配 262143

local MACHINE_ID_BIT_MAX = (1 << MACHINE_ID_BIT) - 1
local TIME_BIT_MAX = (1 << TIME_BIT) - 1
local INCR_BIT_MAX = (1 << INCR_BIT) - 1

local MACHINE_SHIFT = TIME_BIT + INCR_BIT --机器号偏移量
local TIME_SHIFT = INCR_BIT --时间偏移量

local MACHINE_ID = nil
local g_pre_time = 0
local g_incr_num = 0

local CMD = {}

function CMD.new_guid()
local cur_time = os.time()
assert(cur_time <= TIME_BIT_MAX, "invild time")
if g_pre_time == cur_time then
assert(g_incr_num < INCR_BIT_MAX, "inval incr")
g_incr_num = g_incr_num + 1
else
g_pre_time = cur_time
g_incr_num = 0
end

return MACHINE_ID << MACHINE_SHIFT | g_pre_time << TIME_SHIFT | g_incr_num
end

skynet.start(function()
skynet_util.lua_dispatch(CMD)
MACHINE_ID = tonumber(skynet.getenv("machine_id"))
--检查机器ID
assert(MACHINE_ID and MACHINE_ID <= MACHINE_ID_BIT_MAX, "invild machine_id = " .. tostring(MACHINE_ID))

local cur_time = os.time()
--检查时间还有效没
assert(cur_time <= TIME_BIT_MAX, "invild time")

log.info_fmt("snowflake_m cur_time[%s] max_time[%s] max_machine_id[%s] max_incr[%s] cur_matchineid[%s]",
os.date("%Y%m%d %H:%M:%S", cur_time), os.date("%Y%m%d %H:%M:%S", TIME_BIT_MAX), MACHINE_ID_BIT_MAX, INCR_BIT_MAX, MACHINE_ID)
end)
end

local TIME_BIT = 32 --时间位数
local INCR_BIT = 18 --自增序号数
local MACHINE_SHIFT = TIME_BIT + INCR_BIT --机器号偏移量
local TIME_SHIFT = INCR_BIT --时间偏移量
local MACHINE_MASK = (1 << MACHINE_SHIFT) - 1 --机器号掩码
local MACHINE_TIME_MASK = (1 << TIME_SHIFT) - 1 --机器号time 掩码

local M = {}

function M.new_guid()
local snowflake = service.new("snowflake", snowflake_service)
return skynet.call(snowflake, 'lua', 'new_guid')
end

function M.get_machine_id(guid)
return guid >> MACHINE_SHIFT
end

function M.get_time(guid)
return (guid & MACHINE_MASK) >> TIME_SHIFT
end

function M.get_incr(guid)
return guid & MACHINE_TIME_MASK
end

return M
4 changes: 4 additions & 0 deletions script/lua/write_config.lua
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ local config = {
loadmodsfile = load_mods_name, --可热更服务启动配置
recordfile = recordfile, --播放录像的文件名
recordlimit = 1024 * 1024 * 100, --录像记录限制(字节数) 超过不再写录像
machine_id = 1, --机器ID(全局唯一)
}

config.lua_path = file_util.create_luapath(skynet_fly_path)
Expand Down Expand Up @@ -114,6 +115,9 @@ if load_mods_f and load_mods_f.share_config_m and load_mods_f.share_config_m.def
if cfg.recordlimit then --录像记录限制
config.recordlimit = cfg.recordlimit
end
if cfg.machine_id then
config.machine_id = cfg.machine_id
end
end

--重放录像时用一个工作线程即可
Expand Down
6 changes: 6 additions & 0 deletions test/load_mods_snowflake.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
return {
snowflake_test_m = {
launch_seq = 1,
launch_num = 1,
}
}
37 changes: 37 additions & 0 deletions test/module/snowflake_test_m.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
local log = require "skynet-fly.log"
local skynet = require "skynet"
local snowflake = require "skynet-fly.snowflake"

local CMD = {}

function CMD.start()
skynet.fork(function()
for i = 1, 10 do
local guid = snowflake.new_guid()
local machine_id = snowflake.get_machine_id(guid)
local time = snowflake.get_time(guid)
local incr = snowflake.get_incr(guid)
local data = os.date("%Y%m%d %H:%M:%S", time)

log.info_fmt("guid[%s] machine_id[%s] time[%s] data[%s] incr[%s]", guid, machine_id, time, data, incr)
end

local guid = 0
local pre_time = os.time()
for i = 1, 300000 do
guid = snowflake.new_guid()
end
local machine_id = snowflake.get_machine_id(guid)
local time = snowflake.get_time(guid)
local incr = snowflake.get_incr(guid)
local data = os.date("%Y%m%d %H:%M:%S", time)
log.info_fmt("over guid[%s] machine_id[%s] time[%s] data[%s] incr[%s] usetime[%s]", guid, machine_id, time, data, incr, os.time() - pre_time)
end)
return true
end

function CMD.exit()
return true
end

return CMD

0 comments on commit c5b8525

Please sign in to comment.