当前位置: 首页 > news >正文

游戏大规模数据存储与数据量增加之后扩容的思考

从事这么多年的服务端架构设计与开发,最明确的感觉就是,不管做什么架构设计,数据存储及数据量增之后的扩展都是首要解决的问题。对于公司来说,最重要的核心资产就是玩家的数据,好的架构必须是能满足随着用户量越来越多,数据的存储能进行平滑的扩展。

我们都知道,一台数据库的数据存储是有局限的,想要存储众多的数据,必须选择的就是分库(分表先不谈,因为分表是在一个数据库内操作的,比较方便实现)。将数据存储在多个不同的数据源服务上面,虽然解决了数据存储问题,但是使用的时候就会相对麻烦些,因为你得知道你需要的数据到底存储在哪台数据库上面。

既然前提已经确定数据是分开存储的,那么剩下要解决的就是服务怎么样将数据存储到对应的数据库里面,以及使用的时候怎么样查询到数据了。在说这两个问题时,我们必须设定一个应用场景,如果没有应用场景,讨论一个四海皆可的框架,跟耍流氓没什么区别,只不过不同的场景需要变通一下,核心宗旨是类似的。

对于游戏场景来说,一种是提前规定好游戏的玩法就是分服制的,不同服之间的玩家数据是隔离独立的,最简单的一种方式是一台服务对应一个区服,再对应一个数据库就行了,达到服务上限时,再开新服即可,复杂一点的可以多台服务对应一个区,多台服务可以使用redis共享内存,每台服务的功能是一样的,就是水平扩展了一下,但是数据库是同一个,这样相对于一个服务的话,单服支持的同时在线人数会多一些。这种框架设计相对比较简单些,数据的存储及使用没有过多的额外规则,扩展分区时也不用迁移数据,只不过游戏的玩法上受服务及数据存储上限的一些限制,后期还需要根据需要合服。

另外一种设计是不分服的框架,对于玩家来说,大家都在同一个世界里面,即平时我们所说的世界服,所有玩家的数据不是隔离独立的,都可以产生交互,这种游戏同时在线的玩家越多越有乐趣,在玩法设计上也越有空间。这种设计复杂性更高些,这相当于一个可以无限扩展的存储,其主要难点还是要解决如何分布式存角色数据,以及使用数据时如何定位数据在哪个数据库中。比如下面这个图所示:
在这里插入图片描述

  1. 数据库是共享的,各个服都会连接每个数据库
  2. 角色分部在各个数据库中
    先说数据存储的数据,数据存储是从0到1的过程,原来没有这条数据,现在要存储这条数据,那这条数据应该通过怎么样的规则,存储到哪个数据库里面呢?
    1. 假如角色A由网关路由到了角色服1,角色服1有所有的数据库连接,如果按照固定的数据库数量计算,可能通过计算角色A的ID的hash值,然后根据数据库数量求余,得到一个数据源,存储到此数据库中,登陆时查询角色数据时,也按相同的算法定位到相同的数据库,也能查询到数据,但是又一个问题来了,如果将来要扩展数据库,增加了数据库,再根据hash与数据库数量求余就不一定还是原来的数据库了。只能对原来数据库的数据,按新的数据库数量重新hash求余,重新分配数据存储的数据库
    2. 如果不想迁移数据,一个方法是基于上述1的方式中,当确定某个角色存储到某个数据库之后,找一个新表,记录一下角色ID存储在数据库(给数据库制定一个唯一编号),用户再登陆时,查询的时候,先查询角色ID对应的数据库编号,然后再去这个数据库查角色的所有数据,相当于创建一个角色与数据库关联的索引表,这样又引出来另外一个问题,如果数据量比较多。比如10亿条数据,这个索引表就又非常大了。
    3. 要解决索引表大的问题,可以单独对这个索引表进行分库分表,比如角色ID生成时可以按照一定的规则,比如时间: 2025100910-8923342,前半部分精确到小时,后半部分是为了保持唯一性,那么就可以根据日期进行分库分表了。
    4. 可以看出,上面的方案都是以角色ID来处理的,但是在用户第一次进入游戏时角色ID还不存在,而且当用户登陆的时候,输入的并不是角色ID,而是一个账号,比如手机号,邮箱或自定义的账号名。这些都是无规则的数据,不能像角色ID那样以固定的格式进行分库分表。这里才是真正意义上的从0到1开始突破了,解决了这个问题,所有的问题就都串起来了。

如何存储登陆的账号
对于游戏用户来说,账号注册也是只产生一个表,它跟角色ID的索引表类似,但是它没有索引表的时间规律,这就比较麻烦了。

方案一,提前预估数据量,准备好存储完这些数据所需要的数据库数量。比如我们预估数据有100亿,那就提前准备好20个数据,一个数据库存5亿条数据,根据账号名的hash值与数据库数量求余,查询的时候也是同样的算法,这样就可以解决存取一致的问题。但是前提是要预估准确些,多了还好,如果预估少了,将来数据达到存储瓶颈时,再扩展就需要迁移数据了。

方案二,存的时候使用hash求余定位法,查的时候去所有的数据库中查询。这个方法的好处是不用提前准备那么多的数据库,可以动态扩展数据库,也不用迁移数据。因为这个表是单表,没有关联表,把账号设置为唯一索引,查询的速度也非常快,单独做一个登陆服务的集群,每次用户登陆的时候都遍历所有的数据库查询这条数据,如果存在就中止,或开几个线程同时去查询,哪个先返回了数据,就给前端先返回数据。再加上缓存机制,活跃的用户一定时间内只会查询一次,这样查询速度会更快。

为了说明整个系统的完整性,登陆账号的存储先用方案二:
在这里插入图片描述
用户登陆时,先在登陆服找到用户登陆之后的数据,账号创建了几个角色也记录在账号表里面,这样用户可以选择一个角色ID,去查角色索引表,获取到角色数据存储在哪个数据库里面。
在这里插入图片描述
对于活跃用户,可以额外再加上缓存机构,这样可以减少查询数据库的次数。

http://www.dtcms.com/a/465974.html

相关文章:

  • 电脑上做网站的软件网站建设中的服务器搭建方式
  • 「机器学习笔记9」回归分析:从理论到实践的全面指南
  • 如何起手做网站项目提高索引量的方法
  • JDBC初识
  • 用已存在的虚拟环境建立一个新项目(配置解释器)
  • 湖南省住房和城乡建设厅门户网站seo排名优化软件价格
  • Linux 系统启动过程详解
  • 死信队列vs延迟队列
  • 给实体店老板做的网站怎么网站排名seo
  • 商务网站建设毕业设计成都网站建设公司排行
  • 基于体素密度的几何重要性剔除(Voxel Density Culling)
  • 卷积神经网络详解
  • Redission
  • 前端框架深度解析:Vue 从入门到实战,掌握渐进式开发核心
  • 从暴力到滑动窗口全解析——力扣8. 字符串转换整数 (atoi)
  • 迅为RK3562开发板Android 系统动态替换开机logo的实现-替换logo
  • 基于Springboot + vue3实现的校园闲置物品交易平台
  • 学校网站 制作wordpress图片时间
  • MySQL分区分表实现方法详解
  • 缠论工具czsc快速使用入门(二)
  • Android 14 Input 事件派发机制深度剖析
  • 苏州做网站外包的公司有哪些许昌做网站团队
  • android 屏幕适配
  • ESP32开发:从Wi-Fi连接到MQTT通信
  • Linux工作队列workqueue的实现
  • 模板建站和开发网站区别wordpress 页面瀑布流
  • [C# starter-kit] 身份验证与授权 Identity JWT
  • C#通讯关键类的API
  • 网站开发说明书天元建设集团有限公司申请破产了吗
  • 分布式单例模式在微服务架构中的关键作用与实践