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

时间:2012-03-06 05:34:56

标签: redis

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

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

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

  1. 在用户上设置一些密钥以使其过期。更新每次心跳或移动。问题是位置存储在散列中,因此如果用户密钥到期,则播放器仍将位于同一位置。
  2. 同样,但是使用pub / sub来听取过期并完成清理(看起来过于复杂)
  3. 将心跳存储在已排序的集合中,每隔X秒运行一次进程以查找旧玩家。每次心跳都会更新得分。
  4. 彻底改变我存储位置的方式,以便我可以使用过期......不知何故?
  5. 还有其他想法吗?

1 个答案:

答案 0 :(得分:4)

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

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

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

from redis import Redis as redis
from time import time

r1 = redis(db=1)

当调用下面的函数时,它会根据当前的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)

所以要让所有活跃用户只需 联盟 所有实时密钥(在此示例中为10 键,一个纯粹的任意数字),像这样:

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

由于TTL,这解决了您的“清理”问题 - 非活动用户不会出现在您的实时密钥中,因为他们会不断回收 - 即,活跃用户只能键入不会持续存在的旧时间戳在这个例子中(但可能在到期前由redis写入永久存储)。无论如何,这会从活动的redis db中清除非活动用户。