Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/redis/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何使用zsets在Redis上实现用户top_Redis_Sortedset - Fatal编程技术网

如何使用zsets在Redis上实现用户top

如何使用zsets在Redis上实现用户top,redis,sortedset,Redis,Sortedset,例如,我有10000个用户在玩这个游戏。每个用户在游戏中每小时可以赢或输几次(可能是100或1000次)。 我需要显示前10名用户在过去1小时内通过积分获胜。最重要的列表应每分钟更新一次 因此,每次赢或输,我都需要存储和更新60个zsets(一小时内60分钟)。旧的zset将在到期时自动删除 另一种方法是在hset中按分钟存储用户点数(每次赢或输只能存储一个hincrby),然后每分钟使用此数据重新计算zset的值。在这种情况下,我应该每分钟取10000 hkeys,删除每个键中的旧数据(超过一

例如,我有10000个用户在玩这个游戏。每个用户在游戏中每小时可以赢或输几次(可能是100或1000次)。 我需要显示前10名用户在过去1小时内通过积分获胜。最重要的列表应每分钟更新一次

因此,每次赢或输,我都需要存储和更新60个zsets(一小时内60分钟)。旧的zset将在到期时自动删除

另一种方法是在hset中按分钟存储用户点数(每次赢或输只能存储一个hincrby),然后每分钟使用此数据重新计算zset的值。在这种情况下,我应该每分钟取10000 hkeys,删除每个键中的旧数据(超过一小时),对其他数据求和,并创建新的zset以显示

这两种情况我都不喜欢,因为用户数量可能会增加几倍,或者将来还会增加其他TOP


这能在Redis中以另一种方式实现吗?

关键在于如何定义“最后一小时”。与“最后60分钟”相比,使用“时钟小时”更简单。考虑到时钟的简单性,我将解释如何计算它

您可以将HINCRBY与负数一起使用。所以,如果我理解正确的话,您应该能够为每小时创建一个哈希,并在到期时自动删除旧的小时

当用户完成游戏时,您可以执行以下操作:

HINCR“排行榜:小时数”用户ID

这将给你在那一小时内得到或失去的分数。例如,现在要获得前10名,您需要通过HGETALL路线将其全部拉回来,并在客户端进行排序

为了利用缓存特性,您可以将生成的“top X”用户/点数值存储在每N分钟过期一次的键中(例如存储为JSON)。这样,显示排名的过程将拉动该键并在找到时显示,否则生成/存储/显示结果。此外,您还可以拥有一个计划作业,该作业计算并存储每分钟显示的结果

因为用户有可能(即使很少)有相同的净分数变化,所以我不会选择总分数为分数的排序集

要使用滚动窗口,您可以按照上面的每分钟哈希值而不是每小时哈希值(可能是排行榜:minutenumber)进行操作,在计算方面,计算您现在的分钟数,并在管道中对之前的60分钟哈希值进行HGETALL。当然,将每分钟哈希设置为60后过期,以降低使用率

这样做意味着计算键,而不是查询键


我想您也可以使用Lua脚本来完成摘要功能,但是随着客户端的增长和对它的调用的增加,在客户端上进行这些计算将具有更高的水平可伸缩性。

关键在于如何定义“最后一小时”。与“最后60分钟”相比,使用“时钟小时”更简单。考虑到时钟的简单性,我将解释如何计算它

您可以将HINCRBY与负数一起使用。所以,如果我理解正确的话,您应该能够为每小时创建一个哈希,并在到期时自动删除旧的小时

当用户完成游戏时,您可以执行以下操作:

HINCR“排行榜:小时数”用户ID

这将给你在那一小时内得到或失去的分数。例如,现在要获得前10名,您需要通过HGETALL路线将其全部拉回来,并在客户端进行排序

为了利用缓存特性,您可以将生成的“top X”用户/点数值存储在每N分钟过期一次的键中(例如存储为JSON)。这样,显示排名的过程将拉动该键并在找到时显示,否则生成/存储/显示结果。此外,您还可以拥有一个计划作业,该作业计算并存储每分钟显示的结果

因为用户有可能(即使很少)有相同的净分数变化,所以我不会选择总分数为分数的排序集

要使用滚动窗口,您可以按照上面的每分钟哈希值而不是每小时哈希值(可能是排行榜:minutenumber)进行操作,在计算方面,计算您现在的分钟数,并在管道中对之前的60分钟哈希值进行HGETALL。当然,将每分钟哈希设置为60后过期,以降低使用率

这样做意味着计算键,而不是查询键


我想您也可以使用Lua脚本来完成摘要功能,但随着客户端的增长和对它的调用的增加,在客户端上进行这些计算将具有更高的水平可扩展性。

好的,我在这里尝试提供一种与Bill提供的解决方案不同的解决方案,同时也有缺点和优点,为了提供一个替代方案。使用此解决方案,您可以获得:

  • 没有客户端排序的Top N
  • 滚动窗口
  • 然而,从内存和计算的角度来看,它有点贵

    这就是它的工作原理:

  • 您有
    topn
    键,该键由实时数据ZINCRBY填充。如果我们想象永远这样做,会发生什么,你没有任何滚动窗口,但“所有时间前N”,所以我们需要一个修复
  • 您还需要一个额外的排序集,过去~2小时内每分钟一个(只要超过1小时就可以)。因此,实际上,每次更新用户分数时,您都会对
    topn
    topn\uu
    执行ZINCRBY操作
  • 您还有一个额外的过程,可以执行以下操作:对于每个不再在当前小时内的
    topn\uu
    条目,它将从
    topn
    中减去其分数。这应该可以通过一个Zunostore调用来实现,并将其用作聚合“SUM”。删除i很重要