memcache クライアントを実装してみた
目的
- 主に自分の勉強です
- クライアントはいろんな言語で実装されてるけど、やっぱり自分でやってみることに意義があるよね
実装項目
以下の3つを実装する- set
- get
- stats
ソース
my_memcache.py1 # -*- coding:utf-8 -*- 2 import socket 3 import pickle 4 import base64 5 6 class MyMemcache: 7 8 def __init__(self): 9 self.__sock = socket.socket() 10 11 def __del__(self): 12 self.__sock.close() 13 14 def connect(self, host, port): 15 self.__sock.connect((host, port)) 16 17 def close(self): 18 self.__sock.close() 19 20 def set(self, key, value, exptime=0, flags=0): 21 serialized_value = base64.b64encode(pickle.dumps(value)) 22 self.__sock.send("set %s %d %s %d\r\n" % (key, flags, exptime, len(serialized_value)) ) 23 self.__sock.send("%s\r\n" % serialized_value) 24 25 result = self.__sock.recv(64) 26 27 if result == "STORED\r\n": 28 return True 29 else: 30 return False 31 32 def get(self, key): 33 self.__sock.send("get %s\r\n" % key) 34 lines = self.__sock.recv(1024).splitlines() 35 serialized_value = lines[1] 36 value = pickle.loads(base64.b64decode(serialized_value)) 37 return value 38 39 def stats(self): 40 self.__sock.send("stats\r\n") 41 lines = self.__sock.recv(1024).splitlines() 42 43 values = {} 44 45 for line in lines: 46 if line == 'END': 47 break 48 49 else: 50 [dummy, key, value] = line.split() 51 values[key] = value 52 53 return values 54
解説
set- 引数は以下の4つ
- key : 必須
- value : 必須
- exptime : 任意(デフォルトは0)
- flags : 任意(デフォルトは0)
- 整数や文字列以外に、リストや辞書などもくることを考慮し、pickle を使って value を直列化した
- 返り値が "STORED\r\n" のときに "True" を返すようにした
- それ以外は "False" としたため、若干処理が甘いかもしれない
get
- 返り値が3行の文字列なので、まず改行文字で分割した
stats
- 以下のフォーマットで返ってくる
- STAT version 1.2.8
- なので、文字列を分割して辞書に登録する
- 文字列 "END" が返ってきたら終了する
テストコード
my_memcache.py55 if __name__ == '__main__': 56 memcache = MyMemcache() 57 memcache.connect("localhost", 11211) 58 59 print "########## stats ##########" 60 print memcache.stats() 61 print "\n" 62 63 print "########## string ##########" 64 key = "string_key" 65 value = "string_value" 66 print "key :" , key 67 print "value :" , value 68 print "---------- set ----------" 69 print memcache.set(key, value) 70 print "---------- get ----------" 71 print memcache.get(key) 72 print type(memcache.get(key)) 73 print "\n" 74 75 print "########## list ##########" 76 key = "list_key" 77 value = ['a', 'b', 'c'] 78 print "key :" , key 79 print "value :" , value 80 print "---------- set ----------" 81 print memcache.set(key, value) 82 print "---------- get ----------" 83 print memcache.get(key) 84 print type(memcache.get(key)) 85 print "\n" 86 87 print "########## tuple ##########" 88 key = "tuple_key" 89 value = (1, 2, 3) 90 print "key :" , key 91 print "value :" , value 92 print "---------- set ----------" 93 print memcache.set(key, value) 94 print "---------- get ----------" 95 print memcache.get(key) 96 print type(memcache.get(key)) 97 print "\n" 98 99 print "########## dict ##########" 100 key = "dict_key" 101 value = {'a' : 1, 'b' : 2, 'c' : 3} 102 print "key :" , key 103 print "value :" , value 104 print "---------- set ----------" 105 print memcache.set(key, value) 106 print "---------- get ----------" 107 print memcache.get(key) 108 print type(memcache.get(key)) 109 print "\n" 110
実行
$ python my_memcache.py ########## stats ########## {'pid': '11509', 'total_items': '64', 'uptime': '47141', 'listen_disabled_num': '0', 'version': '1.2.8', 'limit_maxbytes': '134217728', 'rusage_user': '0.138425', 'bytes_read': '4793', 'accepting_conns': '1', 'rusage_system': '0.238628', 'cmd_get': '86', 'curr_connections': '6', 'threads': '2', 'total_connections': '35', 'cmd_set': '65', 'curr_items': '6', 'get_misses': '0', 'cmd_flush': '0', 'evictions': '0', 'bytes': '618', 'connection_structures': '7', 'bytes_written': '8006', 'time': '1272860539', 'pointer_size': '64', 'get_hits': '86'} ########## string ########## key : string_key value : string_value ---------- set ---------- True ---------- get ---------- string_value <type 'str'> ########## list ########## key : list_key value : ['a', 'b', 'c'] ---------- set ---------- True ---------- get ---------- ['a', 'b', 'c'] <type 'list'> ########## tuple ########## key : tuple_key value : (1, 2, 3) ---------- set ---------- True ---------- get ---------- (1, 2, 3) <type 'tuple'> ########## dict ########## key : dict_key value : {'a': 1, 'c': 3, 'b': 2} ---------- set ---------- True ---------- get ---------- {'a': 1, 'c': 3, 'b': 2} <type 'dict'>
- 格納した値が、ちゃんと返ってきてるよ、やったね
- リストとか辞書は、型も正しいよ、やったね