Redis实例示例

4 投票
1 回答
3853 浏览
提问于 2025-04-18 01:27

我在阅读《Redis in Action》这本书时,看到了一个例子,现在我在想这个例子是否正确。这个例子里有以下的Python代码:

def purchase_item(conn, buyerid, itemid, sellerid, lprice):
buyer = "users:%s"%buyerid
seller = "users:%s"%sellerid
item = "%s.%s"%(itemid, sellerid)
inventory = "inventory:%s"%buyerid
end = time.time() + 10
pipe = conn.pipeline()


while time.time() < end:
    try:
        pipe.watch("market:", buyer)                #A
        price = pipe.zscore("market:", item)        #B
        funds = int(pipe.hget(buyer, "funds"))      #B
        if price != lprice or price > funds:        #B
            pipe.unwatch()                          #B
            return None


        pipe.multi()                                #C
        pipe.hincrby(seller, "funds", int(price))   #C
        pipe.hincrby(buyer, "funds", int(-price))   #C
        pipe.sadd(inventory, itemid)                #C
        pipe.zrem("market:", item)                  #C
        pipe.execute()                              #C
        return True
    except redis.exceptions.WatchError:             #D
        pass                                        #D


return False

从这个例子中可以看到,它使用了管道技术。根据我的理解,命令在调用pipe.execute()之前是不会被执行的。在这个例子中,你可以看到#B有一个if语句,但这里的价格值是返回了吗?还是说在调用conn.pipeline()时,代码的执行 somehow 被缓冲了?

1 个回答

9

我猜你是在使用 redis-py 这个库。当你调用 pipe.watch() 时,管道会立即进入一种叫做 执行 的模式。这样你就可以用普通的 Python 代码来检查后续命令的返回值。你可以通过使用 pipe.multi() 再次将管道放入 缓冲 模式,这正是代码所做的事情。最后的 pipe.execute() 只是用来执行你代码中标记为 "#C" 的命令。所有这些内容在 redis-py 的文档 中都有解释。总结一下:

pipe.watch(...) # <--- executed immediately
pipe.zscore(...) # <--- executed immediately
.....
pipe.multi() # <--- put pipeline back in *buffered* mode
pipe.incr(..) # <--- buffered command 1
pipe.incr(..) # <--- buffered command 2
pipe.execute() # <--- execute buffered commands 1 and 2

撰写回答