Linux | c&cpp | Email | github | QQ群:425043908 关注本站

itarticle.cc

您现在的位置是:网站首页 -> 数据库 文章内容

Mysql使用和优化-itarticl.cc-IT技术类文章记录&分享

发布时间: 6年前数据库 149人已围观返回

游戏有大量的数据需要存储, 最早的服务器并没有选择数据库这种技术来做存档(那时候商业数据库太贵, 开源数据库太垃圾), 不过现在的游戏 大都用各种数据库在存储玩家的数据

数据大致分为游戏数据和日志数据, 前者主要和服务器交互, 后者主要用来做挖掘或者数据分析.

关系数据库

国内的游戏大部分都在用MySQL, 也有一些公司在Postgresql, 或者一些基于MySQL/Postgresql前端的分布式数据库.

但是关系数据库的理论都差不多.

模式的选择

游戏一般使用第一范式或者第二范式, 其他的范式一般不太常用.

端游体系里面, 第一范式比较常见. 大多都会把很多个数据通过序列化的方式打包存在一个字段里面(blob). 这样做有一个好处, 就是不需要频繁的修改表结构; 但是坏处也是显而易见的, 性能非常差(以至于不能频繁更新), 只能隔一段时间落地, 数据不可见(不能做灵活的数据分析, 需要做反序列化).

因为不能频繁更新会导致一系列的设计问题, 服务器宕机怎么解决等等.

所以出现了一些第二范式的设计, 表格都是严格拆分开来的. 这样做可以实时更新数据库, 可以做灵活的在线数据分析, 缺点就是修改表结构会比较麻烦.

表格设计

尽量把每个字段都独立开来, 否则还需要序列化反序列化. 可以使用blob或者类似的字段来存序列化的内容, 但是需要控制长度, 大于768字节就需要看看设计是否合理.

序列化的字段过多, 会给存储引擎带来不必要的麻烦, 因为InnoDB会把大于768字节之外的数据存在其他页上, 更新一行数据会导致存储引擎写多次才能完成; 还有InnoDB支持事务, 所以他需要把数据先写入到BinLog里面, 会导致LOG数据非常大, 运维难以维护.

这也是推荐使用第二范式的原因.

索引设计

游戏数据库的索引设计比较简单, 因为游戏业务比较特殊, 大都是少读多写的应用. 跟互联的应用不太一样, 互联网是多读少写. 这也就意味着游戏领域里面必须要做缓存, 一般都是在逻辑服务器内有玩家数据的缓存.

表上面, 一般只需要一个主键或者联合主键即可. 比如通过玩家UID来索引(玩家表), 或者通过UID和ItemUID来索引(道具表).

用普通索引的场合比较少.

这边说一下InnoDB. InnoDB实现了行级锁, 有好处就是锁的碰撞很少, 坏处就是你可以写出来有死锁的代码. 一般来讲, 一个表如果有多个索引(主键和其他索引), 那么只能通过主键更新或者删除, 不要通过索引删除, 一旦锁碰撞时, 是有可能产生死锁.

大量数据的处理方式

游戏一旦爆款, 就会有大量的玩家来注册玩, 数据库上面就需要考虑一下, 是否能撑住这么多玩家. 技术手段也比较简单, 无非就是分库分表.

分库

分服的游戏, 一般都会分库. 每个区服用一个库, 这样天然就是隔离的. 一个区的注册玩家也不会太多, 所以基本上什么都不需要处理.

唯一需要处理的就是合区. 只需要把ID设计好, 让运维可以简单的通过union或者select into讲两个数据库合并, 就可以极大的减少合区的负担. 如果ID没有设计好, 那么合区就需要写工具去重新计算每行字段的ID, 整个合并过程是要按照数个小时计算.

分表

如果一张表数据过多(比如几百万行甚至上千万行), 那么查询和更新的时间长度都会比较长, 不太可能在几十毫秒内完成. 要完成游戏所需要的QPS有一定的难度. 这时候就需要分表.

游戏行业的分表也比较简单, 一般按照UID来分表. 国内游戏注册玩家的数量一般比较高的也就在一亿这个级别上(划分128张表也就够了).

日志数据因为有比较强的日期相关性, 所以是可以按照时间来分表, 然后超过一定时间之后可以把该表删掉.

也有一些分库分表的中间件, 例如Kingshard等, 可以在中间件这边帮你做分库分表; 如果是是单纯的分辨, MySQL 5.5以上支持内置的分表方式(名词叫分区).

分布式数据库

如果不想程序处理分库分表的话, 可以选择分布式关系数据库. 现在云服务提供商都提供这种数据库, DB前面有一个Proxy, 这个Proxy帮你做了分库分表等工作, 你就不需要关系这些东西的存在, 只需要像单库单表一样来使用, 可以极大简化超大规模数据的处理. 只是延迟会稍微高一点.

有了分布式数据库, 做那种不分区服的游戏, 要简单很多, 程序员不需要再考虑数据的跨区查询更新问题, 只需要负责上层业务编写.

关于QPS

现在的关系数据库, 都会有SSD护航, 所以QPS会比较高. 商业SSD可以支撑100WQPS以上的读写, 所以让DB支撑100WQPS的读写也慢慢成为可能.

目前云上的DB, 大都能支持数万QPS的写操作.

一般的游戏, QPS是和玩家在线数量有一定关系, 比如qps = f(online). 可以去寻找一下函数关系, 一般是线性关系. 所以可以根据玩家在线数量, 去选择合适的DB规格.

非关系数据库

比较常用的非关系数据库是redis和mongodb, redis一般是当作缓存来用.

之所以选择mongodb, 可能是最大的原因是隐式模式. 关系数据库你必须要先确定模式, 然后才能编写代码, 而MongoDB不需要, 这就决定了他可以做快速的原型开发.

另外一方面mongodb天然支持集群, 可以方便扩容, 对开发来讲是一件比较简单的事情.

MySQL/Postgresql高版本也支持json数据格式, 需要快速开发的可以尝试一下.

参考资料: 1) 高性能MySQL 2) 高可用腾讯云DB 3) 分布式腾讯云DB 4) TiDB 5) MongoDB 6) Kingshard 7) MySQL分区 8) MySQL JSON

发布时间: 6年前数据库149人已围观返回回到顶端

很赞哦! (1)

文章评论

  • 请先说点什么
    热门评论
    148人参与,0条评论

站点信息

  • 建站时间:2016-04-01
  • 文章统计:728条
  • 文章评论:82条
  • QQ群二维码:扫描二维码,互相交流