集群实现细节(5)-登陆流程修改
回顾
之前的登陆流程在这篇里。之前的登陆流程简述:
(1)先检查是否同服已登陆,是则两个链接都踢掉,否则进入下步;
(2)判断是否异服已登陆,是则告诉异服踢老链接,随后踢自己这的新链接。否则进入下步;
(3)当前服务器登陆相关流程走完后,向玩家在线列表汇报(写入这个玩家登陆的服务器 ID 为我)。这时的汇报写入为 Redis 的 CAS 操作,为了检查是否发生了那篇里介绍的同账号瞬间多起登陆事件。CAS 操作成功,本服链接登陆完成,做后续操作。否则 CAS 操作失败,表示瞬时登陆的异服同账号的另一个链接的登陆流程走的快,已经完成整个流程,包括汇报进在线列表。这时的处理只用将慢拍的本服链接关闭就行了。
存储架构变为 Redis + MySQL 后的问题
现在玩家上线时需要从 MySQL 加载玩家离线数据到 Redis,需要考虑这个数据加载放到上边登陆流程哪一步里。
首先数据加载有可能会失败,如果数据加载出问题,就不能让该玩家登陆。
如果放到(2)(3)之间,就是 Redis 的 CAS 之前,这样瞬间同一账号多起登陆都有可能开始进行加载数据步骤,而处理的快的那个客户端就有可能汇报登陆完成之后立即玩游戏并更新了自己在 Redis 里的数据,处理的慢的客户端还这时还在将 MySQL 的数据往 Redis 的加载,会覆盖快的客户端更新的数据。
如果放到(3)里 Redis 的 CAS 之后,数据加载失败,就需要回退 CAS 的操作。
可见第二种至少可以保证数据正确性。这种情况抽象下,就是第一种里没有提供事务操作的回滚(慢客户端覆盖数据后发现干了坏事却不方便回滚自己的破坏)。
(2)这个操作当时是为了区分异服登陆并玩游戏很久了和瞬间多起登陆这两种情况的。现在想想这两种情况的处理统一为直接踢掉新旧两个链接也没什么,毕竟瞬时登陆的情况不多。
新流程
根据上边的结论,新的流程为:
(1)先检查是否同服已登陆,是则两个链接都踢掉,否则进入下步;
(2)向玩家在线列表 CAS 报告自己登陆。如果失败告诉异服踢掉该账号老链接,自己这边踢掉该账号新链接即可。成功则进入下步;
(3)加载数据,成功就进入正常游戏流程。加载失败,就去在线列表里清掉自己。