转载请注明出处,欢迎大家批评指正

1、数据服务器详细设计

数据服务器在设计上采用三个层次的数据同步,实现玩家数据的高速获取和修改。

数据层次上分为:内存数据,redis数据,mysql数据

设计目的:首先保证数据的可靠,防止数据丢失,保证数据完整。然后实现数据的高速访问,减少由玩家数量增加对数据服务器性能造成的影响。最后实现运维数据的入库,以及数据持久化。

在这个基础上数据服务器不再是一个单一服务器,它涉及到与其他服务器之间的交互。

数据服务器的核心在于redis数据层面。通过redis加快玩家数据的快速拉取。

内存数据是直接与逻辑服务器进行交互的,因此内存数据划分到逻辑服务器进行管理,redis数据划分为数据服务器管理,mysql数据是对redis数据库的备份和同步。

主要流程,数据服务器启动时先从mysql数据库加载所有的活跃玩家相关数据到redis数据库中,逻辑服务器与数据服务器之间的交互都是通过国过redis数据进行操作。Redis数据库回写到mysql可以通过回写进程实现。

            图 1 数据服务器数据扭转流程图

1.1 数据服务器主进程

数据服务器主进程核心是对redis的操作,通过redis数据库实现数据的高速存储。因此,数据服务器的核心是保证在玩家数量大较大的情况下对玩家数据的增删改都能维持在一定的时间效率内。

针对于redis数据库本身,可以考虑实现redis的主从库搭建,保证redis的数据库的备份和效率。

数据服务器主进程的构成:

1、mysql数据同步到redis数据库中。

2、逻辑服务器和数据服务器的网络库

3、玩家账户修改缓存

4、Redis数据库的回写至mysql

5、逻辑数据库的请求处理

6、内存数据库的组织结构

1.2 数据回存服务

数据服务器接收到逻辑服务器的请求后,就数据库操作请求进行操作的队列缓冲,形成操作队列。操作队列同时提供了redis数据库的及时写入和mysql数据库的异步写入。

1.3 数据服务器提供接口

对于逻辑服务器,数据服务器应为其开放以下接口:

1、数据拉取接口,拉取对应玩家的所有数据,将数据保存到内存数据中

2、修改玩家数据接口,提供玩家的部分或全部信息修改命令

2 数据服务器模块功能

首先redis是一种key-value的内存数据库,以key和value的方式来存储数据实现高速的访问和操作。其次mysql是一种关系型数据库,存储的是结构化的数据。这种差异决定了在数据入库redis的时候需要做相应的处理。

2.1 数据入库redis

通过redis的key-value来存储数据库中的表名以及表的索引和hashkey,来实现构造二维的数据表。

针对于每张表,key结构 [表名]:[id值]

要求所有的数据库表的第一个字段为id,或者所有的表都为主键,并且不能重复,这样保证了所有的key都不重复

图 2 数据入库redis后表现结构

入库流程方法一:

先将redis清空,再将mysql所有的额数据逐条入库到redis。逐条入库的好处是可以对玩家进行其他的操作处理,缺点是启动服务器速度慢。

方法二:

先将redis数据库清空,再将mysql读取处理的数据缓存成redis识别的事务,一次性进行redis入库。

2.2 排序

实现高效的排序功能,可以使用redis的zset进行拍寻队列构建,对于玩家等级或经验改变时,对redis数据库进行修改,当需要或获取排序时直接获取zset集合类已经拍好的顺序就可以实现高效的排序功能

2.3 redis数据回存mysql

对redis数据库的操作需要回存到mysql数据库中。

方案一:采用多线程异步,通过多线程异步实现mysql修改回存同步。在数据服务器多开一个线程进行回存。

优点:设计结构相对简单,不涉及到进程间通信,但需要多线程开发支持

方案二:采用多进程方式,回存由专门的进程进行,没有操作消息redis数据库默认转发进程转发。

优点:简单的单线程即可满足需求,但需要进程间通讯。

2.4 网络交互模块及序列化

服务器之间的网络传输由统一的网络模块进行。序列化功能采用protobuf的序列化功能。

3 具体实现

数据服务器设计到大多都是表和redis数据操作,这些操作具有相似性。这样的繁杂的操作不利于手动修改和书写代码。

因此在此处合理的运用生成器就会减少很大一部分工作量,通过生成器快速生成C++代码,并且灵活的应对数据库结构的更改。

3.1 生成物和生成器

生成器使用了C#语言快速编写访问数据库结构,并生成类代码。

生成物可以设计成各种语言的操作文件,目前生成C++文件。

3.2 Mysql数据回写进程

数据回写进程又一个回写消息队列和一个回写器组成,回写消息队列缓存所有要进行回写操作,再有回写器进行回写。多线程回写消息队列操作加锁。

3.3 玩家登陆信息查询

玩家登陆时将拉取玩家数据到内存中。这个流程现在redis数据库中查询玩家数据,如果存在,返回给逻辑服务器玩家数据,如果redis数据库中不存在玩家数据,将再次在mysql中进行查询,如果存在返回给逻辑服务器,如果不存在返回查询失败。具体流程看下图

    

                图 3 玩家数据查询流程

在修改玩家数据时,需要同步三层数据。数据首先是在内存中进行修改,然后发起修改命令给数据服务器,数据服务器将修改命令分别压入redis数据库命令队列和mysql命令队列。再有两个线程异步对命令队列中的命令执行,完成数据回写。

图 4 数据回写命令执行流程

3.4 玩家活跃程度划分 

为了提高数据的访问速度和效率,将玩家进行活跃度分级。正在游戏玩家数据加载到内存,快速访问。活跃玩家加载到redis数据库,实现快速拉取。不活跃玩家存放mysql,需要时访问查询。

优点:根据数据的访问频度对数据进行分级,使得高频数据快速访问,节约了内存空间。

缺点:不活跃玩家登陆时间相对较长,但不影响游戏效率。登陆后,玩家又再次进入活跃玩家存储方案。

基于内存,redis,mysql的高速游戏数据服务器设计架构的更多相关文章

  1. 基于内存,redis,mysql的高速游戏数据服务器设计架构 ZT

    zt  http://www.cnblogs.com/captainl1993/p/4788236.html 1.数据服务器详细设计 数据服务器在设计上采用三个层次的数据同步,实现玩家数据的高速获取和 ...

  2. Python 基于Python从mysql表读取千万数据实践

    基于Python 从mysql表读取千万数据实践   by:授客 QQ:1033553122 场景:   有以下两个表,两者都有一个表字段,名为waybill_no,我们需要从tl_waybill_b ...

  3. 数据迁移实战:基于Kettle的Mysql到DB2的数据迁移

    From:https://my.oschina.net/simpleton/blog/525675 一.什么是ETL ETL,是英文 Extract-Transform-Load 的缩写,用来描述将数 ...

  4. 基于ETL技术的数字化校园共享数据中心设计

    摘要:数据的抽取.转换与加载(ETL)是数据整合的核心过程.在分析高校信息化建设现状基础上,以建立数字化校园.整合数据资源.实现数据共享为目标,提出以ETL为基础建立共享数据中心实现数据整合的方案.介 ...

  5. 《SPARK/TACHYON:基于内存的分布式存储系统》-史鸣飞(英特尔亚太研发有限公司大数据软件部工程师)

    史鸣飞:大家好,我是叫史鸣飞,来自英特尔公司,接下来我向大家介绍一下Tachyon.我事先想了解一下大家有没有听说过Tachyon,或者是对Tachyon有没有一些了解?对Spark呢? 首先做一个介 ...

  6. 基于Redis+MySQL+MongoDB存储架构应用

    摘  要: Redis+MySQL+MongoDB技术架构实现了本项目中大数据存储和实时云计算的需求.使用MongoDB切片的水平动态添加,可在不中断平台业务系统的同时保障扩容后的查询速度和云计算效能 ...

  7. Redis+Mysql模式和内存+硬盘模式的异同

    http://www.open-open.com/lib/view/open1346029825942.html 学习任何新知识,都是一个循序渐进的过程,从刚开始的懵懂无知,到简单熟悉,然后突然的彻悟 ...

  8. 数据库应用之--Redis+mysql实现大量数据的读写,以及高并发

    一.开发背景 在项目开发过程中中遇到了以下三个需求: 1. 多个用户同时上传数据: 2. 数据库需要支持同时读写: 3. 1分钟内存储上万条数据: 根据对Mysql的测试情况,遇到以下问题: 1. 最 ...

  9. Centos8 部署 ElasticSearch 集群并搭建 ELK,基于Logstash同步MySQL数据到ElasticSearch

    Centos8安装Docker 1.更新一下yum [root@VM-24-9-centos ~]# yum -y update 2.安装containerd.io # centos8默认使用podm ...

随机推荐

  1. 【leetcode❤python】 155. Min Stack

    #-*- coding: UTF-8 -*- class MinStack(object):    def __init__(self):        """      ...

  2. srand()以及rand()函数用法

    srand()就是给rand()提供种子seed 如果srand每次输入的数值是一样的,那么每次运行产生的随机数也是一样的, srand(n) for(10) rand()也就是说,以一个固定的数值作 ...

  3. redis 常用配置

    参数说明 redis.conf 配置项说明如下: 1. Redis默认不是以守护进程的方式运行,可以通过该配置项修改,使用yes启用守护进程 daemonize no 2. 当Redis以守护进程方式 ...

  4. mySQL数据库Sql语句执行效率检查--Explain命令

    mysql性能的检查和调优方法 Explain命令在解决数据库性能上是第一推荐使用命令,大部分的性能问题可以通过此命令来简单的解决,Explain可以用来查看SQL语句的执行效 果,可以帮助选择更好的 ...

  5. [poj1182]食物链(并查集+补集)

    食物链 Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 64841   Accepted: 19077 Description ...

  6. java Collections.sort()实现List排序自定义方法

    方法一: package testSimple; import java.util.ArrayList; import java.util.Collections; import java.util. ...

  7. struct结构体(剽窃别人的)

    结构是使用 struct 关键字定义的,与类相似,都表示可以包含数据成员和函数成员的数据结构. 一般情况下,我们很少使用结构,而且很多人也并不建议使用结构,但作为.NET Framework 一般型別 ...

  8. javascript学习内容--object.style.display="value" value值为“”none“隐藏”或 "block"显示

    <head> var mychar=document.getElementById("con"); function hidden(){ mychar.style.di ...

  9. contiki-process结构体

    struct process { struct process *next; #if PROCESS_CONF_NO_PROCESS_NAMES #define PROCESS_NAME_STRING ...

  10. checkbox点击后出现div

    HTML: <div class="msg_editUrl_function"> <label class="labelChecked" fo ...