一尘不染

如何清理Redis中不活跃的玩家?

redis

我正在制作一个使用Redis存储游戏状态的游戏。它可以很好地跟踪位置和玩家,但是我没有清除闲置玩家的好方法。

每次玩家移动时(这是一种半慢速移动的游戏。以每秒1-5帧的速度思考),我将使用新位置更新哈希值并删除旧的位置键。

跟踪活跃玩家的最佳方法是什么?我想到了以下

  1. 为用户设置一些密钥以使其过期。更新每个心跳或动作。问题在于位置存储在哈希中,因此如果用户密钥过期,则播放器仍将位于同一位置。
  2. 相同,但是使用pub / sub来监听到期并完成清理(似乎过于复杂)
  3. 将心跳存储在已排序的集合中,每隔X秒运行一次流程以查找旧玩家。每次心跳更新分数。
  4. 彻底改变我存储位置的方式,以便可以使用过期。

还有其他想法吗?


阅读 410

收藏
2020-06-20

共1个答案

一尘不染

也许使用 单独的 redis数据结构(尽管使用相同的数据库)来跟踪用户活动和用户位置。

例如,使用 redis集 分别跟踪当前在线的用户:

[我的代码段是在Python中使用redis-python绑定,并改编自Flask(python micro-
framework)中的示例应用;示例应用程序和框架均由Armin
Ronacher撰写。]

from redis import Redis as redis
from time import time

r1 = redis(db=1)

当调用下面的函数时,它将基于当前的UNIX时间(以分钟为单位)创建密钥,然后将用户添加到具有该密钥的集合中。我想您会希望将到期时间设置为10分钟,所以在任何给定时间,您都有10个有效键(每分钟1个)。

def record_online(player_id):
    current_time = int(time.time())
    expires = now + 600     # 10 minutes TTL
    k1 = "playersOnline:{0}".format(now//60)
    r1.sadd(k1, player_id)
    r1.expire(k1, expires)

因此,要使所有活动用户只需 合并 所有活动键(在此示例中,即为10个键,一个纯粹的任意数字),如下所示:

def active_users(listOfKeys):
    return r1.sunion(listOfKeys)

这通过TTL解决了您的“清理”问题-
闲置的用户不会出现在您的活动键中,因为它们不断循环使用-即,在活动的用户中,它们仅使用旧时间戳记,在此示例中不存在(但也许会在到期前通过redis写入永久性存储)。无论如何,这将从活动的redis数据库中清除不活动的用户。

2020-06-20