埋点高频采集让统计量失控:一千人在线每秒一条延迟上报,一分钟六万条,聚合成本超过业务本身。降采样在入口处按固定窗口归并:每 N 秒只留一个桶,桶内记总和、次数、最小与最大,窗口关闭时算出均值存入历史——数据量恒定,趋势不失真。
定窗采样与历史滚动。示例代码如下:
local STEP = 10
local cur = {}
local history = {}
local function sample(key, value)
local slot = math.floor(os.time() / STEP)
local b = cur[key]
if not b or b.slot ~= slot then
if b then
b.avg = math.floor(b.sum / b.n)
local h = history[key]
h[#h + 1] = b.slot .. "|" .. b.avg
if #h > 360 then
table.remove(h, 1)
end
else
history[key] = {}
end
cur[key] = { slot = slot, sum = value, n = 1,
min = value, max = value }
else
b.sum = b.sum + value
b.n = b.n + 1
if value < b.min then
b.min = value
end
if value > b.max then
b.max = value
end
end
end
历史窗口均值查询。示例代码如下:
local function recentAvg(key, windows)
local h = history[key] or {}
local total, n = 0, 0
for i = math.max(1, #h - windows + 1), #h do
local avg = tonumber(string.match(h[i], "|(%d+)$"))
if avg then
total = total + avg
n = n + 1
end
end
if n == 0 then
return 0
end
return math.floor(total / n)
end
千人在线每秒一条、STEP 为 10 秒:原始数据每分钟六万条;降采样后每键每分钟六条,量级缩到万分之一。历史每键限 360 条(一小时窗口),内存占用常数。采样动作本身每条只有一次取余与几次比较,微秒级。
三个不适用场景:一是事件型统计(击杀数、充值笔数)必须全量计数,降采样只适用于连续型指标(在线人数、延迟毫秒);二是窗口内突发尖峰会被均值掩盖——min 与 max 字段必须保留,尖峰告警单独挂 max 通道;三是需要精确总量对账的场景不能采样——对账用全量计数器,采样只服务趋势观测。
全站技术干货持续更新:996 引擎 / Lua 实战帖,语法、参数与示例一篇讲透。进入文章地图 · 查看全部 →
【游戏】 一、一行代码拆解:if CONTRIB = price then CONTRIB = CONTRIB - pric…
【语法】 一、隐蔽陷阱:三个物品的全排列共 6 种,手写三重循环出 27 种含大量重复——递归交换法:固定一位、递归排其余、…
【语法】 一、抛坑提问:成就池 50 项,玩家已解锁 32 项,剩下的怎么一遍筛出?差集运算——以全集为基准,遍历时查已有集…
【语法】 一、抛坑提问:3 根柱子 5 个盘子从甲柱挪到丙柱,每次只能移一个且大盘不压小盘——把"挪 n 个"分解成"挪 n…
【游戏】 一、一行代码拆解:CASTING[actor] = nil —— 回城打断的核心:施法期间被攻击即清空施法状态并返…
【游戏】 一、一行代码拆解:APPLY[acc] = os.time() —— 入会审批的全部骨架:申请进队列带时间戳,官员…