你可以推荐一个在Azure Cloud 上存储游戏分数的替代解决方案吗?我正在寻找 managed , cheap to run 和 easily scalable up and down 存储选项 .
输入数据: { "player": 1, "score": 10 }
(分数可能已经计算,无需总结 . )
应该有一个选项来进行两种类型的查询:
1.获得球员在记分牌中的位置 .
2.获得位置X和Y之间的位置(玩家和得分) .
应用程序无法在写入时间内告诉记分板中玩家的位置 - 后端数据库解决方案应提供该信息,或者数据布局应允许快速计算所有玩家之间的位置 . 非实时准确性是可以接受的 .
当前的后端技术选择:Azure Web App(.NET Core),存储(表,Blob,队列) .
使用SQL服务器显然该怎么做,但 I would like to avoid 将SQL服务器带到了技术堆栈 . 由于多个Web服务器,保留在内存中也不是一种选择 .
您是否知道如何使用任何其他Azure服务存储和检索此类数据? DocumentDB,Data Lake,还有其他吗?
3 回答
计算列表中位置的问题是,当您的数据可以分布在多个服务器上时,很难进行排名(以及一般的窗口操作) . 随着数据的增长,这将成为一项昂贵的操作,并且不能很好地扩展 .
Data Lake支持窗口函数,包括RANK() and DENSE_RANK() . 您需要使用一些有代表性的数据对此进行良好测试,以了解性能如何 .
另一种选择是以特定间隔预先计算排名,并将整个记分板“缓存”到表存储中;如果对用户有延迟是可以接受的(例如,你可以说排名每小时刷新一次)
然后你可以有一个预定的WebJob:
读取得分高于阈值的所有得分记录,按得分排序
为玩家等级创建一个新表格,例如
player-scores-170401-124200
为整体排名创建一个新表格,例如
scoreboard-170401-124200
将排名记分板批量写入新表
通过这种方式,您可以在
PartitionKey=player
上查询player-scores
以获得单个排名,并使用不等式过滤器查询scoreboard
以获取位置窗口 .查询(这是您可能应该优化的操作)变得非常便宜和简单,因为它是每条信息的单个事务 .
运行计算也不是想要密切关注的 . 假设n分数记录:
您可以批量阅读100.交易〜= n / 100
您可以批量写入100个相同的分区 . 交易〜= 2n / 100
您可以选择保留历史排名,或在单个事务中删除整个表
所以你的1M记录的总交易是:
1000000*3/100 = 30,000 per run
每天工作一天(720k交易),每天花费大约2-3美分(当然不包括存储成本) . 在我的书中运行起来很便宜:-)
如果您使用表格,那么您的第一个查询很容易,您可以使用玩家ID(玩家的唯一标识符,无论您选择哪个)作为您的分区键,并且得分可以是同一实体的属性 . 如果您想要阅读(您的查询1),您只需使用唯一的玩家ID进行点查询并获得分数 .
你的第二个查询有点棘手 . 您可能希望避免下载整个表,并在客户端进行内存排序,这是客户端和表服务世界最差的组合 .
因此,需要在此处选择不同的分区键以针对第二个查询进行优化 . 您可以做的一件事是创建一个范围的桶并获得该范围的唯一哈希值 . IE浏览器 . 如果你正在编写一个位置为19的玩家并且你将你的铲斗大小选为50,那么这将是你的第一个位置在1到50之间的玩家 . 在将位置19的玩家写入桌面之前,你的立面(或适配器等)您调用它)客户端中的代码层会检测到这是第一个存储桶,为该存储桶生成一个哈希值,并将该播放器写入表中,并将生成的哈希值作为分区密钥和实际播放器唯一ID作为其行键和其余属性 .
您为存储桶生成的哈希可能只是桶的下限和上限的哈希等 . 请确保使用加密哈希而不是Object.GethashCode,因为它可能返回不同的哈希完全相同的对象的值,不应该用于他的目的 .
当你想要获得范围X和Y之间的所有玩家时,你需要查询你知道哪些覆盖该范围而不是整个表的分区 . 并且您可以使用确切的分区键(表示存储桶的哈希值)来查询分区,因此它会很有效 .
当您插入播放器时,您需要为第一个查询创建2个实体1,为第二个查询创建第二个实体,并插入两者 . 此过程也称为非规范化数据,以针对不同的查询需求进行优化 . 希望这有助于理解如何使用Azure表优化这一点 .
Azure表存储有利于存储纯数据,而且价格低廉且易于扩展 . 但它对复杂查询没有好处 . 如果满足您的需求,您可以选择Table Storage来节省一些资金 . 价格范围从每千兆字节4.5到12美分 .
Azure DocumentDB是一个分布式文档数据库 . 它比Azure Table Storage更强大,但也更昂贵 . 价格:每千兆每月25美分 .
Azure Data Lake Store是针对大数据分析工作负载的优化存储,我们经常将其用于批处理,交互式,流分析和机器学习数据,如日志文件,物联网数据,点击流,大型数据集
如果可以满足您的需求,最好选择Azure表存储 . 根据您的描述,我建议您使用Azure表存储并使用不同的分区键优化查询 . 有关如何设计可扩展和高性能的表,下面的链接供您参考 .
Azure Storage Table Design Guide: Designing Scalable and Performant Tables
如果我们想获得位置(排名),存储数据的最佳方式是使用得分作为分区键 . 如果我们只知道当前玩家的id,我们需要在查询位置之前获得当前玩家的得分 . 要根据玩家ID查询玩家,最好通过将玩家ID设置为分区键,在Azure表存储中存储另一个游戏数据副本 .
使用分数作为分区键适用于此场景 .
总之,我建议你存储两个不同的游戏数据副本 . 一个是使用得分作为分区键,另一个是使用玩家ID作为分区键 .
查询的结果数据是按分区键排序 . 因此结果计数是您的玩家的位置(排名) .
例如,在将分数设置为分区键后,您可以使用小于分数(例如10)的分区键来查询实体范围,实体count是分数为10的玩家的位置 .