以下是在 Google App Engine 上运行的 Python Flask 应用程序的一部分:
@app.route('/blabla', methods=['GET'])
def blabla():
# memcache.add('key', None) # this "fixes" it!
memcache_client = memcache.Client()
while True:
value = memcache_client.gets('key')
if value is None: # First time
updated_value = 'Bla'
else:
updated_value = value + ', bla'
if memcache_client.cas('key', updated_value):
return updated_value
从空缓存开始,如果我们向/blabla 发出连续的 GET 请求,我希望请求返回:
Bla
Bla, bla
Bla, bla, bla
.
.
(如果由于某种原因在 .gets()
和 cas()
之间的某个时刻缓存被刷新,那么我希望序列重新启动,没问题.)
但是我们什么也没得到,因为 memcache_client.cas()
永远返回 False
,因此程序陷入了 while
-环形。显然,发生这种情况是因为 key 'key'
一开始就不存在。
我知道这一点,因为如果我取消注释 memcache.add('key', None)
,它就可以工作,因为这样 key 就存在并且 .cas()
code> 很高兴并返回 True
。但是,如果在 .add()
和 .gets()
之间有其他进程要刷新缓存,我们就会回到我们开始的地方,缺少 key ,.cas()
将无限期地返回返回 False
。所以这不是一个好的解决方案。
如果一开始就缺少 key ,为什么 .cas()
不起作用?或者至少,为什么 .cas()
不接受 initial_value=
参数,就像它的兄弟 decr() 一样。 ?这是一个错误还是一个功能?除了 Guido van Rossum 在他的 single blog post on the matter 中提到的之外,我在任何地方都找不到正确的记录。 ——提到 assert
,他使 .gets()
不返回 None
,他说:
Aside 2: The assert is kind of naive; in practice you'll have to somehow deal with counter initialization.
Dank je wel Guido——请问有人知道怎么做吗?
最佳答案
好吧,我明白了。
@app.route('/blabla', methods=['GET'])
def blabla():
memcache_client = memcache.Client()
while True:
if memcache.add('key', 'Bla'):
# That's all folks!
return 'Bla'
# add() failed => the key must already exist, we have to compare-and-set.
value = memcache_client.gets(key_name)
if value is None:
# At the time add() failed the key existed, but now gets() is returning None,
# so somebody must have deleted the cache entry in between.
# Let's start from scratch.
continue
updated_value = value + ', bla'
if memcache_client.cas(key_name, updated_value):
return updated_value
else:
continue
它比我希望的要复杂,但它有效。
最后一个else: continue
是多余的,但我写它是为了明确我们将继续尝试,直到成功。
尽管在实践中,您必须以某种方式处理多次重试后的放弃。
关于python - Google App Engine memcache.Client.cas() 因缺少 key 而不断返回 False,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41308544/