FunData — 电竞大数据系统架构演进

本文介绍FunData电竞数据平台的架构演进过程,分析旧系统在架构上的缺点及如何通过新技术解决。系统包括Master与Slave模块,处理DOTA2游戏数据,面临TB到PB级数据存储与实时分析挑战。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

电竞出现在人们视野中的频率越来越高了,此次选取FunData作为电竞数据平台,v1.0 beta版本主要提供由Valve公司出品的顶级MOBA类游戏DOTA2相关数据接口(详情:open.varena.com)。

本文将介绍FunData的架构演进中的设计思路及其涉及的相关技术,包括大数据流处理方案、结构化存储转非结构化存储方案和数据API服务设计等。

电竞数据的丰富性从受众角度来看,可分为赛事、战队和玩家数据;从游戏角度来看,维度可由英雄、战斗、道具以及技能等组成;电竞数据的实时性包括赛前两支战队的历史交战记录、赛中的实时比分、胜率预测、赛后比赛分析和英雄对比等。

因此多维度的数据支持,TB到PB级别的海量数据存储与实时分析都对底层系统的架构设计有着更高的要求,亦带来了更严峻的挑战。

 架构

系统主要有两个模块:Master与Slave。

Master模块功能如下:

 

  • 定时调用Steam接口获取比赛ID与基础信息

  • 通过In-Memory的消息队列分发比赛分析任务到Slave节点

  • 记录比赛分析进度,并探测各Slave节点状态

 

Slave模块功能如下:

 

  • 监听队列消息并获取任务(任务主要为录像分析,录像分析参考github项目clarity(https://github.com/skadistats/clarity)与manta(https://github.com/dotabuff/manta))

  • 分析数据入库

系统上线初期运行相对稳定,各维度的数据都可快速拉取。然而随着数据量的增多,数据与系统的可维护性问题却日益突出。

 

  1. 新增数据字段需要重新构建DB索引,数据表行数过亿构建时间太长且造成长时间锁表。

  2. 系统耦合度高,不易于维护,Master节点的更新重启后,Slave无重连机制需要全部重启;同时In-Memory消息队列有丢消息的风险。

  3. 系统可扩展性低,Slave节点扩容时需要频繁的制作虚拟机镜像,配置无统一管理,维护成本高。

  4. DB为主从模式且存储空间有限,导致数据API层需要定制逻辑来分库读取数据做聚合分析。

  5. 节点粒度大,Slave可能承载的多个分析任务,故障时影响面大。

在本篇的技术分享中,我们介绍了FunData数据平台架构演进的过程,分析了旧系统在架构上的缺点,以及在新系统中通过什么技术和架构手段来解决。FunData自4月10日上线以来,已有300多位技术开发者申请了API-KEY。我们也在着力于新数据点的快速迭代开发,如联赛统计数据,比赛实时数据等。 

转载于:https://www.cnblogs.com/z12568/p/10663954.html

#include <stdio.h> #include <stdint.h> #include "main.h" #include "PhyAll.h" #include "FunAll.h" volatile unsigned long ulSysTickCnt; unsigned long ulSysTimeMax; unsigned long ulLastVal; #define SYS_TIME_100US 14400 //144*100 #define SYS_TIME_500US 72000 //144*500 static unsigned char ucTimer1,ucTimer3; //ucTimer2, unsigned short usTimer4; static unsigned long ulSysTickIRQOffCnt=0; static void SystemTickInit(void); /** * @brief Main program. */ int main(void) { // unsigned short i; NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4); //NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x5000); SystemTickInit(); /* Configure the system clock */ __enable_irq(); /*if(FLASH_GetReadOutProtectionSTS()==RESET){ //»¹Ã»¿ªÆô¶Á±£»¤Ôò¿ªÆô // FLASH_ClockInit(); FLASH_Unlock(); FLASH_ReadOutProtectionL1(ENABLE); //¿ªÆôL1¼¶¶Á±£»¤ FLASH_Lock(); }*/ /* Initialize all configured peripherals */ PhyGpio_Init(); Phy_CanInit(); FunData_ParaInit(); ObjCan1_Init(); ObjCan2_Init(); ExtCan_ParaInit(); PhyIWDG_Init(IWDG_PRESCALER_DIV4,3000); //´ó¸Å160MSÒç³ö while(1) { if(Sys_Time0MS1Check()==TRUE) { //0.1msÖ´Ðеĺ¯Êý ObjCan1_RxDeal(); ObjCan2_RxDeal(); ucTimer1++; if(ucTimer1>=20)//2msÖ´ÐÐ { ucTimer1 = 0; PhyGpio_ReadInput(); PhyGpio_WriteOutput(); ObjCan1_Main(); ObjCan2_Main(); FunData_DoDeal(); FunData_LedDeal(); FunData_EidDeal(); } ucTimer3++; if(ucTimer3>=100) //10ms { ucTimer3 = 0; PhyIWDG_Feed(); } } } } static void SystemTickInit(void) { ulSysTimeMax = SystemCoreClock / 1000U; //tickÖжÏÖÜÆÚ1ms SysTick->LOAD = (uint32_t) (ulSysTimeMax - 1UL); /* set reload register */ NVIC_SetPriority(SysTick_IRQn, 0); SysTick->VAL = 0UL; /* Load the SysTick Counter Value */ SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | //ʹÓÃϵͳʱÖÓHCLK SysTick_CTRL_TICKINT_Msk | SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */ } BOOL Sys_Time0MS5Check(void) { unsigned long ulSysTime; unsigned long ulDeltaTime; ulSysTime = SysTick->VAL; if (ulSysTime <= ulLastVal) { ulDeltaTime = ulLastVal - ulSysTime; } else { ulDeltaTime = ulLastVal + ulSysTimeMax - ulSysTime; } if (ulDeltaTime >= SYS_TIME_500US) { if (ulLastVal >= SYS_TIME_500US) { ulLastVal -= SYS_TIME_500US; } else { ulLastVal = ulLastVal + ulSysTimeMax - SYS_TIME_500US; } return TRUE; } return FALSE; } BOOL Sys_Time0MS1Check(void) { unsigned long ulSysTime; unsigned long ulDeltaTime; ulSysTime = SysTick->VAL; if (ulSysTime <= ulLastVal) { ulDeltaTime = ulLastVal - ulSysTime; } else { ulDeltaTime = ulLastVal + ulSysTimeMax - ulSysTime; } if (ulDeltaTime >= SYS_TIME_100US) { if (ulLastVal >= SYS_TIME_100US) { ulLastVal -= SYS_TIME_100US; } else { ulLastVal = ulLastVal + ulSysTimeMax - SYS_TIME_100US; } return TRUE; } return FALSE; } void HAL_SuspendTick(void) { ulSysTickIRQOffCnt++; /* Disable SysTick Interrupt */ CLEAR_BIT(SysTick->CTRL, SysTick_CTRL_TICKINT_Msk); } void HAL_ResumeTick(void) { if(ulSysTickIRQOffCnt) { ulSysTickIRQOffCnt--; } if(0==ulSysTickIRQOffCnt) { /* Enable SysTick Interrupt */ SET_BIT(SysTick->CTRL, SysTick_CTRL_TICKINT_Msk); } }
06-13
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值