[开发者心得] 为什么不能制作实时更新的全服排行榜?

[复制链接]
1531 |2
本帖最后由 (๑•ั็ω•็ั๑) 于 2023-7-25 11:44 编辑


一:原因
  • 延迟问题:实时更新的全服排行榜需要实时更新服务器数据,但这可能会因为网络延迟而导致显示不准确。例如,玩家A的分数可能已经发生了变化,但因为网络延迟,其他玩家看到排行榜时可能还没有更新A的最新分数。这会导致其他玩家看到不准确的的信息,影响他们的体验。
  • 服务器负载:实时更新的全服排行榜需要频繁地查询和更新服务器数据。这会增加服务器的负载,可能导致服务器过载或崩溃。
  • 公平性问题:实时更新的全服排行榜可能会引发公平性问题。例如,如果玩家可以在排行榜更新时利用时间差或其他漏洞来获得不公平的优势,这会破坏游戏的公平性原则。


二:技术实现
https://forum.ark.online/forum.php?mod=viewthread&tid=1276
这里引用大佬的帖子说明一下KV服务器对存储的限制,这在我们在实际开发中也需要遵循相应的要求。在玩家请求存储数据之前,服务端检查当前是否可以set这个key如果可以,才set,具体的做法是可以添加一个canUpdate标签,每次set数据之后将canUpdate置为false,然后延迟一定时间间隔将其设置true,每次set操作判断当前标签。核心的代码实现如下:

/** 更新数据 */
    private updateData() {
        if (this._isUpdate) return;
        this._isUpdate = true;
        DataStorage.asyncGetCustomData(GlobalRankPrefix + this._customKey + this.getTimeKey()).then((data: Info[]) => {
            let isChanged = false;
            if (data) {
                data.forEach((info) => {
                    const index = this._cacheData.findIndex((item) => item.userID === info.userID);
                    if (index === -1) {
                        this._cacheData.push(info);
                    } else if (this._cacheData[index].score < info.score) {
                        this._cacheData[index] = info;
                    }
                });
                this._cacheData.sort((a, b) => b.score - a.score);
                if (this._cacheData.length > MaxRankItemViewLength) {
                    this._cacheData.length = MaxRankItemViewLength;
                }
                const UndefinedIndex = this._cacheData.findIndex(info => !info.userID);
                if (UndefinedIndex != -1) {
                    this._cacheData.splice(UndefinedIndex, 1);
                }
                if (JSON.stringify(data) !== JSON.stringify(this._cacheData)) {
                    isChanged = true;
                }
            }
            // 没有数据就初始化默认的假数据
            else {
                isChanged = true;
                // 初始化默认数据
                this.initDefaultData();
            }
            this._dataReplicated = JSON.stringify(this._cacheData);
            if (isChanged) {
                DataStorage.asyncSetCustomData(GlobalRankPrefix + this._customKey + this.getTimeKey(), this._cacheData);
            }
        });
        setTimeout(() => {
            this._isUpdate = false;
        }, RankDataSaveTime);
    }

其中的RankDataRaveTime就是指多久更新可以set数据的时间,是自定义的常量,一般大于6秒。
回复

使用道具 举报

喵喵哭唧唧 发表于 2023-7-25 11:16:32 | 显示全部楼层
谢谢大大的分享,还有一些技术上的问题,比如存储6秒限制等等的,能否也讲一下呢,可能这个更重要
回复

使用道具 举报

(๑•ั็ω•็ั๑)楼主 发表于 2023-7-25 11:45:08 | 显示全部楼层
喵喵哭唧唧 发表于 2023-7-25 11:16
谢谢大大的分享,还有一些技术上的问题,比如存储6秒限制等等的,能否也讲一下呢,可能这个更重要 ...

谢谢大大提醒,相应内容已补充
回复

使用道具 举报

热门版块
快速回复 返回顶部 返回列表