memcacheでCriticalSectionを書いてみた
gaeアプリケーションでいくつものリクエストを受けた時、相互に排他制御できる仕組みが欲しい。
memcache.incr(), decr()はアトミック操作できる。
ということで、こいつを使って CriticalSection を書いてみた。
from google.appengine.api import memcache import datetime import time class CriticalSection(object): def __init__(self, key, namespace = None, autolock = False): self.key = key self.namespace = namespace self.locked = False if autolock: self.lock() def __del__(self): self.unlock() def lock(self): assert not self.locked # 最大リトライ 250ms * 60times = 15sec for retry in range(60): # ここでロック count = memcache.incr(key = self.key, namespace = self.namespace, initial_value = 0) if count == 1: self.locked = True return True memcache.decr(key = self.key, namespace = self.namespace) # 250ms 待つ time.sleep(0.25) return False def unlock(self): if self.locked: self.locked = False # ここでアンロック memcache.decr(key = self.key, namespace = self.namespace) def test(): print 'start: ' + str(datetime.datetime.now()) csection = CriticalSection('lock', autolock = True) print 'testing now...' + str(datetime.datetime.now()) time.sleep(5.0) print 'done.' + str(datetime.datetime.now()) test()
今回はロックされていることを検出したら、250ms 毎にポーリングする仕組みを書いた。
ロックの解除をうまく検出できるといいんだけど、知識が足りなくていい知恵が思い浮かばん。