Google App Engine SDK 1.5.3 で memcache cas (Compare and Set) 操作ができるようにななりました。今更ですが。 GvR のブログでも丁寧に解説されています。
で、どんなときに使おうっかなぁと思うわけです。データが揮発してよい、クライアント間のデータ共有の遅延を遅らせたい、整合性は保つ、みたいなときに意味があるのでしょうか。クライアントが自身のID を渡してサービスを呼び出し、最後に呼び出して一定時間以内のクライアント数を数える、みたいな機能とか。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
""" | |
- /init to initialize service | |
- /update?uid=XXX to tell service XXX is active | |
- /count to get how many clients are active within last TIME_LIMIT sec. | |
""" | |
KEY = 'users' | |
TIME_LIMIT = 10 | |
MAX_RETRIES = 3 | |
import time | |
from google.appengine.ext import webapp | |
from google.appengine.ext.webapp import util | |
from google.appengine.api import memcache | |
from django.utils import simplejson as json | |
class InitalizeHandler(webapp.RedirectHandler): | |
def get(self): | |
memcache.set(KEY, "{}") | |
self.response.out.write("OK") | |
class UpdateHandler(webapp.RequestHandler): | |
def get(self): | |
uid = self.request.get('uid') | |
client = memcache.Client() | |
for i in range(MAX_RETRIES): | |
users = json.loads(client.gets(KEY)) | |
users[uid] = time.time() | |
if client.cas(KEY, json.dumps(users)): | |
self.response.out.write('OK') | |
return | |
else: | |
self.response.out.write('FAILED') | |
class CountHandler(webapp.RequestHandler): | |
def get(self): | |
users = json.loads(memcache.get(KEY) or "{}") | |
count = len([uid for uid,timestamp in users.items() | |
if time.time() < timestamp + TIME_LIMIT]) | |
self.response.out.write('count: %d' % count) | |
def main(): | |
application = webapp.WSGIApplication([('/init', InitalizeHandler), | |
('/update', UpdateHandler), | |
('/count', CountHandler)], | |
debug=True) | |
util.run_wsgi_app(application) | |
if __name__ == '__main__': | |
main() |
と、思ったんですが、cas のリトライに失敗したときにどうしましょうっかねぇ。どっか、別のエラーの回数を incr() しといて、エラー率とアクセス数を関連付けるとかでしょうか。むずい。
2011-09-11 22:43 追記: シャーディングで、ひとつのキーに集中しないようにする、というのは大前提で。
2011-09-11 22:43 追記: シャーディングで、ひとつのキーに集中しないようにする、というのは大前提で。