首页 > 代码库 > 主程的晋升攻略(8):数据层的演进(上)

主程的晋升攻略(8):数据层的演进(上)

我们用一个做手游的故事来聊聊数据层不断优化提升的演进过程。

10:简单设计

有一天,老板突然说做个山寨版的糖果传奇手游,你接到任务后,分析出游戏的交互频率不大,都是点查询,用mysql能简单搞定。对游戏来说,你很少有机会用orcale这种上流货,mysql是物美价廉的选择。建个表,设好主键和索引,你轻松搞定数据库设计,惬意的泡了杯茶边喝边敲代码。

这里说的“点查询”,是指基于指定主键的查询,例如查询指定用户的信息,因为是基于指定主键,查询结果有限且较少,点查询的效率非常高。另一种叫“面查询”,是基于主键或索引的范围查询,例如查询昨天所有的订单,这种查询虽然有主键或索引,但结果数量不确定,有时处理不好时会出现严重性能问题。

游戏删档内测上线了,用户数不多,请求的响应也很及时,老板拍了拍你的肩膀。

100:数据库调优

游戏上线反响不错,精美的画面给了玩家不少惊喜,更多玩家蜂拥而入,你从监控系统上发现mysql的压力有点大,当初只是对数据库表结构做了设计,现在你开始review数据库优化了:创建表时默认的MyISAM存储引擎换成InnoDB存储引擎,修改mysql参数加大InnoDB的cache,不使用事务提交。

做了这些优化后,db性能提升明显,整个系统跑得很欢,你又惬意的去泡茶了。

1000:分库分表

你们游戏山寨得比较牛叉,用户持续增加,作为有风险意识的你,肯定不会等到系统告警了才去优化,于是你在想更大访问量时怎么办?

单台db的性能有极限,必须有扩展到多台db的能力,于是你重新修改了数据库表结构和后台代码,把主键按规则做了分库分表,目前用户增长迅猛,假定单台db存放500万用户,最终可能有上亿用户,那么可能有20台DB,于是你分了32个库,每个库里有32张表,共1024张表。

初始时这1024张表都在一台db上,当用户数增加时,分裂成2台、4台、8台、16台。涉及好分库分表策略后,db压力能通过扩容来解决,你放心了。

关于读写分离

有不少介绍mysql读写分离已提升mysql并发性能的文章,在游戏项目中用得比较少,主要是读写比例的原因。像网站那种读多写少的应用场景可以采用读写分离,而游戏的读和写差不多多,读写分离的用处不大;而且用户可能是海量的,分多台db是常事,如果分库后再搞读写分离,整个db就过于复杂了。

mysql读写分离是基于mysql主从复制功能的,游戏项目如果对数据安全有要求,一般会用mysql主从复制功能做热备。如果项目有GM或经分系统需要直接查询mysql,往往也是在slave上查询,不直接操作master,避免低效查询降低master性能影响业务。这种做法也是OLDP(On-Line Transaction Processing,联机事务处理)和OLAP(On-Line Analytical Processing,联机分析处理)分离的常见做法。

10000:缓存

有了分库分表来平滑扩容,项目安稳了较长一段时间,直到某一天,运维说db机器增长比较快,4个月就增加到了64台(master+slave),希望后台能提升单台db的性能,以应对后续的业务增长。

OK,你祭出你留的后手——memcached,麻利的操起机械键盘,咔哒咔哒的改起后台的代码,加入缓存逻辑:读的时候从memcached读,如果没有就从mysql查询并写入memcached。写的时候同时写入mysql和memcached。

好吧,你终于使用了NoSQL。NoSQL泛指非关系型数据库,是Not Only SQL(有多少人和我一样搞错的~~!)。

搞定这个问题后,成本下降了,项目收入可观,拿奖金好happy!
未完待续~

主程的晋升攻略(8):数据层的演进(上)