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
Python 3.x 龙卷风&x2B;为什么我的redis呼叫被阻塞了?_Python 3.x_Redis_Async Await_Tornado_Python Asyncio - Fatal编程技术网

Python 3.x 龙卷风&x2B;为什么我的redis呼叫被阻塞了?

Python 3.x 龙卷风&x2B;为什么我的redis呼叫被阻塞了?,python-3.x,redis,async-await,tornado,python-asyncio,Python 3.x,Redis,Async Await,Tornado,Python Asyncio,我尝试在Tornado和Redis的基础上构建一个具有两个API端点的简单系统: 从Redis读取值或等待该值存在的API(使用BRPOP:value=yield from Redis.BRPOP(“测试”)) 编写此值的API(使用LPUSH:redis.LPUSH(“测试”、“值”)) 所以我希望能够以任何顺序调用这些API。事实上,如果我叫2。然后1.,它按预期工作,调用1。立即返回值 问题是,如果我打1。然后2.,两个请求都阻止永不返回 同时,当请求阻塞时,我仍然可以直接在Redis中L

我尝试在Tornado和Redis的基础上构建一个具有两个API端点的简单系统:

  • 从Redis读取值或等待该值存在的API(使用
    BRPOP
    value=yield from Redis.BRPOP(“测试”)
  • 编写此值的API(使用
    LPUSH
    redis.LPUSH(“测试”、“值”)
  • 所以我希望能够以任何顺序调用这些API。事实上,如果我叫2。然后1.,它按预期工作,调用1。立即返回值

    问题是,如果我打1。然后2.,两个请求都阻止永不返回

    同时,当请求阻塞时,我仍然可以直接在Redis中
    LPUSH
    /
    BRPOP
    ,甚至可以使用相同的键。类似地,我可以在Tornado中调用其他处理程序。所以我猜这个街区既不在Redis也不在Tornado,而是在我使用aioredis的时候?也许是异步IO循环?但我不明白我错在哪里。有小费吗

    谢谢你的帮助

    这是我的密码:

    import tornado.ioloop
    import tornado.web
    from tornado import web, gen
    from tornado.options import options, define
    import aioredis
    import asyncio
    
    
    class WaitValueHandler(tornado.web.RequestHandler):
        @asyncio.coroutine
        def get(self):
            redis = self.application.redis
            value = yield from redis.brpop("test")
            self.write("I received a value: %s" % value)
    
    
    class WriteValueHandler(tornado.web.RequestHandler):
        @asyncio.coroutine
        def get(self):
            redis = self.application.redis
            res = yield from redis.lpush("test", "here is the value")
            self.write("Ok ")
    
    
    class Application(tornado.web.Application):
        def __init__(self):
            tornado.ioloop.IOLoop.configure('tornado.platform.asyncio.AsyncIOMainLoop')
    
            handlers = [
                (r"/get", WaitValueHandler),
                (r"/put", WriteValueHandler)
            ]
    
            super().__init__(handlers, debug=True)
    
        def init_with_loop(self, loop):
            self.redis = loop.run_until_complete(
                aioredis.create_redis(('localhost', 6379), loop=loop)
            )
    
    if __name__ == "__main__":
        application = Application()
        application.listen(8888)
    
        loop = asyncio.get_event_loop()
        application.init_with_loop(loop)
        loop.run_forever()
    
    好吧,我知道为什么了:

    共享模式下的阻塞操作(如blpop、brpop或长时间运行的LUA脚本)将阻塞连接,从而可能导致整个程序故障

    通过对此类操作使用独占连接,可以轻松解决此阻塞问题:

    redis = await aioredis.create_redis_pool(
        ('localhost', 6379),
        minsize=1,
        maxsize=1)
    
    async def task():
       # Exclusive mode
       with await redis as r:
           await r.set('key', 'val')
    asyncio.ensure_future(task())
    asyncio.ensure_future(task())
    # Both tasks will first acquire connection.