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

Sea*_*ess 3 redis

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

每次玩家移动时(这是一个半缓慢移动的游戏。想想每秒 1-5 帧),我用新位置更新哈希并删除旧位置键。

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

  1. 在用户上设置一些密钥以使其过期。更新每一次心跳或移动。问题是位置存储在散列中,因此如果用户密钥过期,玩家仍将在同一位置。
  2. 相同,但使用 pub/sub 监听到期并完成清理(似乎过于复杂)
  3. 将心跳存储在一个排序集中,每 X 秒运行一个进程以查找老玩家。每次心跳更新分数。
  4. 彻底改变我存储位置的方式,以便我可以使用过期..不知何故?

还有其他想法吗?

dou*_*oug 5

也许使用单独的redis 数据结构(虽然是同一个数据库)来跟踪用户活动和用户位置。

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

[我的代码片段在 python 中使用 redis-python 绑定,并改编自Flask 中的示例应用程序(python 微框架);示例应用程序和框架均由 Armin Ronacher 提供。]

from redis import Redis as redis
from time import time

r1 = redis(db=1)
Run Code Online (Sandbox Code Playgroud)

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

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)
Run Code Online (Sandbox Code Playgroud)

因此,要获得所有活跃用户,只需联合所有实时密钥(在此示例中,即 10 个密钥,一个纯任意数字),如下所示:

def active_users(listOfKeys):
    return r1.sunion(listOfKeys)
Run Code Online (Sandbox Code Playgroud)

由于 TTL,这解决了您的“清理”问题——不活动的用户不会出现在您的实时密钥中,因为它们会不断回收——即,在活动用户中,仅锁定旧的时间戳,在此示例中不存在(但可能会在到期前由 redis 写入永久存储)。无论如何,这会从您的活动 redis 数据库中清除非活动用户。