游戏开发:排行榜结算的方案设计
对玩法、活动的排行榜排名进行结算发奖,是常见的业务需求。结算以榜单为单位,根据排名对上榜单位(可能是玩家/联盟/单服)进行发奖,由相关的业务服务负责。讨论几种实现思路;
- 实时顺序结算
使用定时器驱动结算服务对业务的结算检查:
local function doSettle()
local function pickReward(pos, unit)
local id = unit.id
if not rewardFlag then -- 奖励已领取标记
setFlagAndPick(id)
end
end
-- settle rank
local pos2rankUnit = {--[[ get data from sort zset --]]}
for pos=minRankIdx, maxRankIdx do
local unit = pos2rankUnit[pos]
pickReward(pos, unit)
skynet.sleep(100) -- 削峰
end
end
local function checkSettle()
local function checkSchedule()
-- time to settle
end
if _check_lock then
return
end
_check_lock = true
if checkSchedule() then
skynet.fork(function ()
doSettle()
_check_lock = nil
end)
end
end
skynet.timeout(100, checkSettle)
方案需要:
1)处理临界区保护,将核心结算逻辑通过_check_lock标记保护起来,避免被重复执行;
2)支持重入,发奖单位记录领取标记,避免重复发奖;
3)削峰,结算流程做定时休眠让出执行权,减少性能波动;
方案适用于对有限的榜单有限的排名进行结算。方案实时发奖结算,性能可控(单位时间内处理的业务量是固定的),消耗线性(榜单数量+每个榜单需要发奖的单位数量),一次性结算的榜单越多,需要的时间就越久(主要是削峰的时间),一般对全服性排名的玩法适用,比如某个赛季制玩法,赛季内全服排名,赛季结算时只对一个榜的前N名进行结算发奖;
单服内的玩法,比如新服冲榜,每个单服有固定数量的榜单,当同一时间需要结算的新服数量越多,完整结算完成需要的时间也越长,逻辑的滞后性会比较明显,当然实现需求没有问题;
- 多服务协作实时结算
一些业务场景下,可以明显地将结算分摊到多个结算服务中,比如多分组的玩法,每个分组独立排名结算,这时候结算更适合由每个分组的服务独立负责结算,各分组并行处理,最后只到玩法的中央服务标记完成,统计所有分组结算情况来判断结算全部完成;
方案是对1方案结算效率上的补充,总耗时大致等于单个分组的耗时,需要处理的是性能峰值问题,峰值取决于同时结算的分组数量,需要做时间分摊:
-- run on every group
local RANGE_SEC = 10 * 60 -- 10分钟结算完
local function doSettle()
-- ...
end
-- 随机一个时间开始结算
skynet.timeout(math.random(RANGE_SEC), doSettle)
- 惰性触发式结算
通过上榜单位的行为(比如玩家登录)触发领奖计算检查,结算服务只在结算时刻保存榜单数据的快照,对外提供领奖检查API:
local function makeSnapshot()
local function checkSchedule()
-- time to settle
end
if checkSchedule() then
if not picture then
take_rank_picture() -- 保存排行榜数据
end
end
end
skynet.timeout(100, makeSnapshot)
function API_tryPickReward(id)
local pos = picture[id]
if pos and not rewardFlag then -- 奖励已领取标记
setFlagAndPick(id)
end
end
方案没有明显的性能边界情况,触发式的领奖方式可以将发奖流程分散到各个异步的请求动作里,受skynet的消息队列调度,性能上没有问题。非实时的方式,需要依赖上榜单位的触发,可能存在未领奖励的情况。更适合大范围的结算发奖,比如全服玩家发奖,登录和在线跨天触发,不登录的玩家不发奖,可以依据不同的业务需求考虑。
本文来自博客园,作者:linxx-,转载请注明原文链接:https://www.cnblogs.com/linxx-/p/18892210
浙公网安备 33010602011771号