一、玩家数据在redis与mysql之间的同步
由于redis操作可以保证多个进程读写同一个玩家数据时的原子性。所以之前多个逻辑服务器读写同一玩家数据时没有什么问题,但是现在redis和mysql之间需要同步玩家的数据(例如定时将redis里的在线玩家数据刷进mysql里做持久化)。这个同步的逻辑代码放哪呢?
观察需求特性,玩家上线加载到redis做cache、定时更新持久层、玩家离线时清掉cache并更新到持久层,都是redis和mysql之间的数据交互。这些可以放到一个服务里,单进程实现,或者集成到现在的逻辑服务器里。
方便实现,做下限制。玩家登陆的逻辑服务器记为他的owner服务器,每个玩家数据的redis/mysql同步只由他owner来做。 这样问题就简化了。
这里有些做法是突然想到的,就像《暗时间》里提到的联想式的,而不是归纳演绎的。最近在看《暗时间》,好书,里边就提到边写边思考,思考时“大脑内存”有上限的,边写就能把部分思考分支换出笔记这种“硬盘”上,然后大脑专心思考其中一两个分支,想的差不多,再回过头将“笔记硬盘”上的数据换入“大脑内存”……将正在思考的东西写博客的习惯已经形成一段时间了,看了书后,更深切体会到这种好处。
如果逻辑服务器宕机,它上边的玩家就掉线了,而这台逻辑服务器是不能对这些玩家做离线数据持久化的。这种情况需要进一步思考TODO。另外之前这种玩家怎么标记为离线,需要再想一遍,也TODO了。
二、从本质出发review我们的存储架构
不要走的太远而忘了为什么出发,从本质上思考,弃掉那些不必要的思考分支,简化问题。
本质我们的架构是为实现游戏的玩法目标来做的,另一方面我们考虑开发成本、维护成本、机器成本。好的架构是权衡目标实现程度和这些成本的耗费。
目标是实现同一国家的玩家不分区分服。之前缓存和持久化都是用redis来做,开发成本和维护成本都挺低的。但是需要很多机器。现在控制机器成本,所以需要分析我们数据的特点,将冷数据放到mysql这种机器需求量少的数据库。具体到表的分析这里就不方便贴了。说下大概分类:
(1)离线玩家的冷数据,离线玩家的私人数据,不需也不能与别人交互的;
(2)离线玩家的热数据,例如名字,好友是想看到离线好友的名字的;
(3)在线玩家的一直更新的数据,例如经验值,游戏货币等;
(4)在线玩家的到强实时玩法时才更新的数据。
(1)里的数据无疑问放在mysql里。(2)里的数据还得根据情况看是否一致放在redis里,即离线的玩家这部分数据也放在redis里。(3)里的数据无疑问在线是放到redis里。(4)里的数据可以根据情况考虑下延迟加载什么的,即玩家上线时这部分数据不马上加载到redis,而是等玩家开始这个玩法时才从mysql里加载到redis里。这个需要考虑这个玩法的数据量以及是否玩家参与度高。
三、扩展
先了解mysql单表数据上限、然后mysql单库上限。这里的上限指不影响效率的上限,而不是物理上限。拿到上限数据后,做预分库分表。分库分表也要好好想想。
查了下,mysql 5.1里InnoDB引擎表空间最大容量为64TB。在查我们公司服务器配置表里硬盘,最低有100G的,最高600多G的。
初步确定mysql的sharding和partition为这样:不同物理机之间的sharding为分个大的id段,单个物理机上即单库内的如果表还是很大就做自己的partition。最终看上线怎么定,再定这个跨机sharding的id段长度,至于单机的partition,对代码来说是不需要管的,运维根据性能搞就行了。
先简单算下,每人100k,500w人一个sharding,需要大约500G空间。
四、其他架构展望
有单机内容;需要联网时才联网;弱联网时弱联网,强实时时做强实时联网。一直纠结这个会不会影响现在的存储架构,但是想了下,不大影响,变的只是链接形式,玩家数据处理还是一样的。