挺久没更新文章了,这一年以来个人经历了许多事情,去年下半年开始稳定下来了,但今年初始又赶上疫情,公司的项目进度也推迟了,现在好不容易复工,登录了许久不上的博客,发现自己收到了很多新的关注和私信,也有很多网友表达了对自己文章的支持,在这里先表达自己的感谢。其次对于一些网友询问的问题,在这里统一回复下:之前那一系列对于英雄远征源码分析的文章质量其实不高,各位随便看看就行了...至于交流,本人工作经验尚浅,不是什么大神,就不打扰浪费大家时间了...至于上一篇英雄远征的Erlang源码,有时间会重新整理一遍,附加一些运行说明,确保都能跑起来。
闲话不多说了,最近在参与公司的新项目,对涉及到好友系统的部分有一些自己的理解和疑惑,在此随手记录一下
确认几个前提:
游戏中每个玩家是一个语言级别的轻量级的进程,A进程要给B进程发送消息需要使用语言层面的RPC调用。
玩家的好友数据保存在数据库和内存缓存中。
离线事件:有专门的离线事件管理进程,当给离线玩家派发一个事件(比如有人给其发送了好友申请),进程会将事件先进行保存(数据库,缓存),玩家上线时通过离线事件管理进程取出,并执行其中的操作(收到该好友申请)。
保存的好友结构:
好友列表
临时好友列表
申请列表
黑名单列表
先抽出一个最简单的过程:
添加好友:A向B申请好友,B收到A的申请,弹出“XXX请求添加你为好友 确认 拒绝”,B点了确认,则A出现在了B的好友列表中,B自己也被添加到了A的好友列表
删除好友:A把B从好友列表删除,则A自己也从B的好友列表消失了
黑名单:不再赘述
这些操作在对方离线的时候也是可执行的。
加好友过程:
A申请B:A向B发送申请请求,B收到请求后将A放入申请列表
B同意A:B向A发送同意信息,将A从申请列表中删除,放入临时好友列表
B拒绝A:B向A发送拒绝信息,将A从申请列表中删除
A收到B的同意:A自动向B发送确认同意信息,将B放入好友正式列表
B收到A的确认:B将A放入好友正式列表
有点像TCP三次握手
(1)A -> B:请求好友(请求建立连接)
(2)A <- B:同意好友(同意建立连接)
(3)A -> B:确认好友(确认建立连接)
中间任一个阶段条件检查未通过都不能成功加好友
条件检查涉及几个地方:目标玩家是否存在,自己的好友列表是否已满,对方的好友列表是否已满,是否已经建立关系,是否被拉黑
需要进行条件检查的地方:A给B发申请前;B收到申请时;B给A回复同意时;A给B发送确认时;B收到A的确认时。
其中每个阶段,任一方都有可能离线,需要进行离线事件的处理
在线的情况:
A向B发出申请时,B将A放入申请列表。
B选择同意好友,将A从申请列表中删除,同时加入自己的临时好友列表(因为A那边没确认),给A发出同意信息
A给B发出确认添加好友的信息,B收到A的确认信息后不用再回复,只要把A从临时列表删除,加入到好友列表中即可。
离线的情况:
一个原则:任一玩家无法修改其他离线玩家的数据。
A向B发出申请,B离线,给B发离线事件,A下线。
B上线,取出离线事件,把A加入申请列表;同意A的申请,把A从申请列表删除,加入自己的临时列表。此时A离线,但又不能让B等待A返回的确认结果(玩游戏的时候确实没等),于是决定让离线进程代替A进行确认的判断,把加好友的数据写入离线进程,给B返回确认的结果。等A上线后从离线进程取出离线期间加好友的数据,再写回给A。
离线进程/A在线,返回了确认的结果但B离线(刚同意完以很快的速度下线了,或者网比较卡),给B发同意的离线事件。
B上线,取出离线事件,把A从临时列表删除,加入正式的好友列表。
也有直接使用公共缓存保存好友数据的方式,每次好友关系的变动无论对方是否在线都只需要修改公共缓存,缓存定期同步到数据库中。离线转换为在线状态时,只需要从公共缓存中加载自己的好友数据。
删除好友步骤(双向):
A想删掉B,此时先把B从好友列表删除。
如果B在线,则把B列表中的A删除;如果B离线,则给B派发离线事件,等B上线把A从B的好友列表中删除
黑名单步骤(单向):
A拉黑B,直接把B加入黑名单列表中。
推荐好友列表:
随便随机几个
极端情况考虑:
现在我们有三个人:A,B和C,
情况1:A和B同时向C发出申请,但C只有一个好友位置
此时C首先同意了A的申请,将A加入自己的好友列表,同时C的好友列表已满,则C无法再同意B的申请。需要在C同意B时对C的好友列表进行检查。是需要在同意阶段(2)检查被申请方的好友列表长度。
情况2:A向B发出申请,B向C发出申请,但B只有一个好友位置
若B先同意了A发出的申请,则C无法再同意B的申请。是需要在确认阶段(3)对申请方好友列表长度进行检查。
若C先同意了B的申请,则B无法同意A的申请。是需要在同意阶段(2)检查被申请方的好友列表长度。
情况3:A申请B,B申请C,C申请A,此时每个人都是只有一个好友列表
其实也没那么复杂:若B同意了A,则C无法同意B,A无法同意C。需要在好友确认阶段(3)检查申请方好友列表长度,在同意阶段(2)检查被申请方好友列表长度。
情况4:A向B申请了,B也向A申请了
此时A和B都在相互的申请列表中,申请过程中只要做好是否已经是好友的检查问题应该不大。
要防止超出好友列表长度,只需要在同意阶段(2)检查被申请方好友列表长度,确认阶段(3)检查申请方好友列表长度即可。不过考虑实际需求变化和保险起见,最好能想到的地方都加上相关检查。
几个疑问:
参考了一些网络上的文章,好友系统的设计只有两个步骤:请求好友(1)和同意好友(2),那么本文中的第三个步骤确认好友(3)是否是多余的,正如TCP的三次握手,如果涉及到“确认”这一步,可能会掉入A给B发送消息,B给A发送确认消息,A给B发送确认消息的确认...一种循环中,而如果将TCP三次握手中的第三次去掉的话,影响会和好友系统中去掉确认好友(3)步骤一样吗。说到底,拿添加好友的过程类比TCP三次握手是否恰当...
...