【问题标题】:Change PubSub subscription with redis-py使用 redis-py 更改 PubSub 订阅
【发布时间】:2012-05-01 05:56:50
【问题描述】:

我有一个实时 web 应用程序,其中客户端从多个 Redis PubSub 频道接收更新,这些频道使用 gevent-socketio 和 redis-py 构建。

我正在查看 django-tictactoe 示例中的 views.py, l.26。 当客户端为频道发送订阅消息时,它会生成一个新的 greenlet。然后,greenlet 订阅 Redis PubSub 频道并阻塞,直到收到消息。

class GameNamespace(BaseNamespace):
    def listener(self, chan):
            red = redis.StrictRedis(REDIS_HOST)
            red = red.pubsub()
            red.subscribe(chan)

            print 'subscribed on chan ', chan

            while True:
                for i in red.listen():
                    self.send({'message': i}, json=True)

    def recv_message(self, message):
        action, pk = message.split(':')

        if action == 'subscribe':
            Greenlet.spawn(self.listener, pk)

据我了解,如果不生成新的 Greenlets 或取消订阅,就无法添加订阅。

您将如何以有效的方式处理频繁的订阅和取消订阅?

更新:我正在构建的是一个理论上无限的 2D 地图上的 HTML5 实时 MMO 游戏。由于地图的大小,无法将整个地图的状态发送到浏览器。因此,地图被划分为在玩家拖动地图时动态加载的图块(想想谷歌地图)。

每当拖动地图时,客户端/浏览器都会订阅刚刚变为可见的图块的更新,并在短暂延迟后取消订阅不可见图块的更新。每个玩家每秒可能会更改订阅一次,因此频繁是相对的。

客户的数量(希望)会很大。从理论上讲,所有玩家都可以查看地图的同一部分,这使得SUBSCRIBEUNSUBSCRIBE 非常昂贵,因为它们是“O(N) where N is the number of clients already subscribed to a channel”。实际上,它会均匀分布在世界各地,所以这应该不是问题。

但是,我的主要问题是 Python Redis PubSub 实现在监听时阻塞。一旦我在上面的示例中调用 red.listen(),我就无法再更改订阅,直到收到消息到达。上面的示例代码启动了一个新的 Greenlet,每个订阅都有一个到 Redis 的新连接,这可能是个坏主意。

【问题讨论】:

    标签: python redis socket.io publish-subscribe gevent


    【解决方案1】:

    您没有说明订阅之间的分区原理/要求是什么,即哪些信息流经订阅必须与其他订阅分开,因此很难明确回答。我会做一些假设......

    如果您有少量或固定数量的客户端管理多个订阅,最好通过单个长期订阅多路复用多个不同的事件,并由该 Redis 客户端对最终的事件消费者进行多路复用。从 Redis 的角度来看,这种方法可能比为每个消费者重复设置和取消订阅更高效。

    这样的方案需要发布者提供一些额外的智能,以便他们可以为每条消息选择正确的队列,但这有时很容易实现,例如通过散列客户端 ID 模 N,其中 N 是发布/订阅队列的数量。

    我希望这与您所问的有关...

    【讨论】:

    • 感谢您的回答!它仅与我的问题部分相关,但您的建议将来可能会很有价值。现在,我不太关心 Redis 的性能,而是关心 Python Redis 客户端的正确使用。我试图澄清我的问题。
    • 啊,我明白了。我将 Redis 与 C#/Booksleeve 一起使用(由 SO 自己的 @MarkGravell 编写,赞),所以我对 Python 库不太了解。但我怀疑它的阻塞设计暗示大多数人不会像你描述的那样使用它,当这种情况发生在我身上时,我的蜘蛛侠感觉就会消失,也许我应该以不同的方式看待这个问题。在这种情况下,我想知道让每个客户端使用单个非 Redis 连接到代理/管理服务来管理用户的视图/订阅是否会更好,这样您就可以轻松尝试不同的策略,即使在运行时。
    猜你喜欢
    • 1970-01-01
    • 2016-03-13
    • 2021-02-07
    • 2020-02-01
    • 2013-08-09
    • 1970-01-01
    • 1970-01-01
    • 2016-07-04
    • 1970-01-01
    相关资源
    最近更新 更多