在redis中,我拥有一个拥有10万用户且不断增长的大型数据集。为了制作排行榜,我扫描整个数据库,为每个用户获取所有哈希值。然后我一个接一个地得到分数。后来,我在javascript中进行排序和修剪。我的问题是,做同样事情的更快的方法是什么?当前查询需要几秒钟。我的直觉是将数据存储在JS中,只运行一次查询。
getLeaderboards: function(player){
var self = this;
async.waterfall([
function(callback){
client.smembers("usr", function(err, replies){
var pvpleaders = [];
var expleaders = [];
var lastUser = false;
for(var i = 0; i < replies.length; i++){
var name = replies[i].toString();
if(i == replies.length - 1){
lastUser = true;
}
if(name.charAt(0) != "_"){
callback(err, name, pvpleaders, expleaders, lastUser);
}
}
});
},
function(name, pvpleaders, expleaders, lastUser, callback){
client.hgetall("u:" + name, function(err, reply){
if(reply){
kills = parseInt(reply.kills);
exp = parseInt(reply.exp);
remortexp = parseInt(reply.remortexp) || 0;
if(kills > 0){
//log.info(name+' '+kills);
pvpleaders.push([kills, name]);
}
if(exp + remortexp > 0){
//log.info(name+' '+exp);
expleaders.push([exp + remortexp, exp, remortexp, name]);
}
}
if(lastUser){
log.info('user user');
callback(err, pvpleaders, expleaders);
}
});
}
], function (err, pvpleaders, expleaders) {
if(err){log.info(err);}
pvpleaders.sort(function(a, b) { if (a[0] === b[0]) { return 0; } else { return (a[0] > b[0]) ? -1 : 1; } });
pvpleaders.splice(30, pvpleaders.length);
expleaders.sort(function(a, b) { if (a[0] === b[0]) { return 0; } else { return (a[0] > b[0]) ? -1 : 1; } });
expleaders.splice(30, expleaders.length);
var leaderboards = JSON.stringify({pvp: pvpleaders, exp: expleaders});
player.sendLeaderboards(leaderboards);
});
},
答案 0 :(得分:1)
如果我的理解是正确的话,基本上你的问题是如何设计一个有效的记分牌。
一个简单的解决方案是在redis中使用ZADD。它将创建一个有序集。 ZADD复杂度的时间是O(M * log(N)),你使用ZRANGE得到结果,其时间复杂度为O(log(N)+ M)。
更有效的解决方案需要您考虑更多有关数据的信息。你的数据有多大?例如,如果您的所有用户的分数都在0到10000之间?如果是这样,您可以在此处使用bucket sort并将结果缓存在redis中。插入和搜索都是O(1)(因为桶的数量是固定数量)。仅对前100名,您维护一个已排序的数据结构。通过这种方式,您可以获得功能&#34;显示前100名记分牌&#34;和&#34;搜索给定用户的排名&#34;两者都是时间复杂的。
答案 1 :(得分:0)
使用排序集数据结构 - 排行榜是它的经典用例。
将memeber的值设置为玩家ID,将得分设置为玩家的得分。然后,您可以执行有效范围(z [rev] rangebyscore命令)服务器端,并且结果已经排序。在大多数情况下,由于网络流量的节省,这将比任何客户端后处理快得多。