简介
在玩游戏的过程中,邮箱绝对是玩家喜欢的东西,邮箱代表着有新的更新说明,或者官方发放的奖励。特别是一键领取,看着亮晶晶的奖励不停弹出,那叫一个心情愉悦。但是对于服务器来说,邮件带来的负担可不小,需要小心设计。
功能需求
邮件系统一般有3个需求。
- 全服邮件。维护补偿,节日奖励等,需要发给每一个玩家。玩家不能重复领取。
- 个人邮件 。对特定的玩家发邮件,一般为 bug发现奖励,充值未到账 补发物品等。只需要发给特定的玩家。邮件内物品在不同的情况有很大不同,且不会提前知道要发此邮件。
- 多人邮件。一般用于排行榜奖励发放,论坛幸运玩家奖励。涉及多个玩家且奖励固定并预先知晓。
糟糕的设计方案
一种直觉的设计方案就是: 我要发一封邮件给哪个玩家,只要给数据库插入一条对应的邮件数据就可以了。
对于个人邮件来说,这样很OK。对于多人邮件来说,勉强也可以。但是对于全服邮件,比如这个服务器有100万玩家,就要往数据库插入100万条邮件数据,会严重影响数据库性能导致服务器延迟增大甚至不可用。
改进的设计方案
我们需要改进的是全服邮件的发放时机,不能在运营发送维护补偿邮件时就添加大量数据。需要安排一个添加数据的时机。
- 分而治之: 对于离线玩家,不需要马上插入邮件数据,一个很好的时机是在该玩家登录时。
- 减而治之: 对于在线玩家,需要广播通知玩家有新邮件并执行插入,当在线玩家数量很多,需要分批次广播,以分摊压力。
这样就把繁重的插入工作分摊到不同的时间段进行,保证服务器稳定流畅。
深入细节
系统邮件,在运营发送时,保存一封在数据库的系统邮件表中,通用数据结构如下:
列名 | 说明 |
---|---|
id | 自增的id |
titile | 标题 |
content | 内容 |
rewards | 奖励 |
filter | 过滤条件,比如玩家领取最低等级,过期时间 |
注意这里的自增id,用于保证玩家不会重复领取。
离线玩家登录过程中,检查系统邮件,检查过滤条件,并对比自身已领取最大系统邮件id,这里记为max_received_sysmailid
, 如果有系统邮件的id大于max_received_sysmailid
,则将此邮件转换为玩家的个人邮件,插入到玩家的个人邮件表中。并将max_received_sysmailid
设置为当前系统邮件id。
在线玩家分批次检查过滤条件,并将此系统邮件转换为玩家个人邮件,插入到玩家的个人邮件表中,然后通知该玩家有新邮件。并将max_received_sysmailid
设置为当前系统邮件id。
max_received_sysmailid
可以单独建表存储,也可以集成在玩家个人信息表中。
对于多人邮件,既可以按个人邮件那样实时分批次直接插入,也可以像系统邮件一样对比id,和过滤条件发放。(建议按系统邮件方式)
功能优化
对于全服邮件,特别是有几百个文字的补偿说明,在每个玩家领取后都会存一份,这样会造成大量的数据冗余,对于 缓存和数据库来说都很不友好。
- 解决方案一:对于未过期的全服邮件,放一份数据在缓存中,玩家的个人邮件表中只存对应全服邮件的id和领取状态。玩家每次拉取邮件数据时,需要拉取全服邮件进行组合。优点: 技术全解决,无需修改业务。 缺点: 需要额外的代码。
- 解决方案二:玩家在领取邮件后自动删除。优点:通过业务操作就得到了优化。缺点:策划可能想打人。
如果大家有更好的方案,欢迎留言分享。