1)记录index,而不是具体的内容

原因:当策划配置发生了改变时,比如:本来让玩家领取银币,但是配置程了金币,这时如果是index,那么发放奖励时就没问题。

2)刷新:

在线玩家,需要及时的刷新。

凌晨5点的处理,自然过渡这种,考虑+1min。

用户登陆时的处理。

3)对于无法区分的周循环活动,不要用时间戳来标识,而是单独的期数

而是可以搞一个单独的表,记录的自增的long类型的id一期一期的这样子就可以清晰的区分开来。

每一期活动都是相同的sn,这样子很难区分本期还是下一期时登录。

4)将重复出现的数据操作封装为对象

原因:比如有一张表A,我有些操作是修改字段1,有些是修改字段2,甚至里面的bean都不存在还要初始化,那十分麻烦。因此可以定义一个统一的xxxColumn,加上readonly,那么就把所有的数据初始化和修改及其查询封装到里面了。

其实这是java封装的体现呀。

5)既然2个定时器无法搞,不知道以谁为主,那就以一个定时器呀。

目前我的做法:使用了2个。

6)用一个字段表示多个意思

用tag标识唯一的一场比赛:哪个门派、几强、哪一期。

排行榜:用score+时间戳编码为一个字段。

64位的long:前32位表示场景id,后32位表示分线。

一个code:模块号+命令号,如:17001

7)警惕全服邮件功能

假如榜单上有1W人,给榜单上的人都发送一份奖励,最开始 写的是:for循环1W次,都发送一个邮件。

其实这个看起来没问题,实际问题很大,因为可能8000人已经是流失用户,给他们发送邮件,其实是需要修改很多人的数据,但是他们可能已经不再登录 了,这样子会 占用数据库资源 ,23:00时特别卡。

正确做法:在线人直接发送。 离线人,则统一Record一下,所有没有领的人,而且记录保留3条。 上线后,统一检查发送。

而且:注意这个for循环很大,不要直接for发送,而是每个玩家都在各自的线程发送。

8)很多玩法允许一定的数据冗余

玩法1要求a,b,c,d字段

玩法2比如:多一个助战次数,那么其实是不应该直接设计1个数据结构的。 可以在通用的结构中冗余一个字段。

9)数据的刷新时机,如:每日登录、活动开启、玩家升级

方式1:在Column的构造函数中每次获取数据时进行checkRefresh();

有可能是升级后开启了功能模块,此时可以监听升级事件,从而进行处理。

方式2:在玩家登录和功能开启时,进行checkRefresh();  // 街霸的处理方式

10)XXXBeanColumn负责数据的初始化

     xxxQuery则负责数据的初始化,判断没初始化,则进行初始化。

    xxxDoSomething则负责修改数据,当判断没初始化则直接返回。

11)副本目标的设计

               goalSn关联一张表,可以配置是刷怪还是什么,然后再配置具体的内容。

12)定时器的使用

        逻辑服:走Schedule开启start和end线程监听任务的完成。

       场景服:走统一的场景tick,在进入场景时,传入时间戳,然后再tick中检测,并且超时后通知逻辑服更新数据。

13)面向接口编程

        如:我有各种逻辑的副本,但是我设置好一个SModLogic后,根据type,让不同的副本去实现这个接口,this.content = new xxxContent();  最终就可以根据接口的调用周期去实现。

14)LogicRole、SceneRole、db数据存储

LogicRole可以标记上玩家所在的场景信息

SceneRole是记录玩家所在的场景对象。游戏功能做成Module挂载在玩家身上。

db数据用于真正的缓存玩家的落地数据

15)在xxx时间后,可以领奖的问题(类似的还有:称号过期问题)

方法1:”客户端手动领取“,服务器进行校验,这样子很少有问题,很靠谱(推荐)。

方法2:“时间戳法“: 告诉客户端可以领取,客户端到了时间后,主动发起一次领取请求(虽然客户端和服务器时间不一致,但是基本上不会出什么大错,可能不会发,但是起码不会多发。但是最终发现,很多情况下甚至差1ms导致领取不了,最终做法是:领取时,时间戳做更新只是用于客户端显示,服务器只校验领取次数有没有达到上限,没有则发奖,并更新时间,让客户端 做新的倒计时(实际做法)。

同事建议:如果不能领取,则告诉领取的时间戳,客户端再次修正时间。

方法3:“场景tick法“:由于mmo玩家都是在场景中(除了切场景过程中),因此使用组件的HumanModule的tick中挂载定时器ticker不断进行检测(别人这么做的,没错,但是每个人身上永久挂了一个对象)。

16)2次活动bug排查

问题1:2个时间戳之间有很多期活动,周6和周7选择,周1领取。 最终发现可能会出现2次活动一起开。 解决办法:在end时间戳取为周1.

问题2:在周六的4点到5点之间不能进场景。 但是发现周6下午14:00打发现时间为负数。解决办法:如果是大于end,则判断为新的一期。

17)跨天的处理

对于23:59:59s结算的设计,定时器是不准确的,有可能还没跨天。这种实际处理是:非登录情况下+1min,登录情况下,则是不做处理。

18)继承的思考

副本类型:Content

玩法类型:SModLogic。

怪物类型,继承后,增加单位类型,从而让客户端知道是哪个类型的怪。而不是通过id区分。

19)组件的设计:循环引用

Scene:各种组件,人身上的各种组件。

UnitObject身上的各种组件。

其实最终又通过构造函数在构造时相互引用Scene,这样子每个类之间都可以相互访问。

20)优化的点

1.谁与争锋结算

     现在做法:

         由get+逻辑计算+奖励发放--》select+逻辑计算+奖励发放标记记录在杂项表中。

         离线的用户,存到list中,切最多保留3条记录。

    解决的问题:

           玩家可能已经流失,很久不上线,但是背包却满了,导致服务器内存浪费。

2.弹幕系统

        用一个队列,最多保留最近3条。 自己的能直接看到。防止新服玩家过多,直接服务器炸了。

3.观战系统

     不是立马观看,而是把消息都存起来。 序列化上传到oss中,让观战 的用户切换到单独的场景,慢慢下载。

4.多线程导表

     

21)3段论

情景1:oss上传,分为:startXxx  updateXxx endXxx

情景2:刷怪,startXxxx  .  .

情景3:战斗,startBattle   updateBattle   endBattle

好处:这样子设计非常的清晰,开始则是记录一场战斗,update则可以检测下是否有这场战斗  end则移除战斗。

22)context设计模式

xxxContext: 里面包装了各个需要的参数,包装了需要的ChannelHandlerContext,这样子就可以。

23)性能优化

功能未开启时,每次都select,都是执行sql语句导致新服性能压力很大。

修改为:即使没开始,也插入,下一次走缓存。

24)性能优化:票数

活动开启时,延迟到玩家查询数据时,才进行初始化。 同时添加:弹框提示活动开始,引导玩家开始。

25)CSUnionXxx、SCUnionXxx、UnionXxxNotify

cs和sc分别对应请求和相应,属于人为的触发。

notify属于系统自动引起的改变,比如:凌晨5点触发了重置。

Logo

openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构

更多推荐