The greatest glory in living lies not in never falling, but in rising every time we fall.

—— Nelson Mandela

In-memory key-value 缓存 python 实现

20 Aug 2016

使用memcached 协议 https://github.com/memcached/memcached/blob/master/doc/protocol.txt
提供 getset 方法。
算是一个简单的memcached 实现。可以使用memcached client 进行操作。

网络:

请开启 TCP_NODELAY 。 tl;dr : 由于TCP端默认开启纳格算法. 为了能够立刻返回数据 请开启 TCP_NODELAY 原因详见.

具体实现代码:

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import socket

CACHE = {}

def main():
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    sock.bind(("127.0.0.1", 11211))
    sock.listen(1)
    print("sock listen on 127.0.0.1:11211")
    conn, _ = sock.accept()
    handle(conn)
    sock.shutdown(socket.SHUT_RDWR)
    sock.close()


def handle(conn):

    sockfile = conn.makefile(newline="", mode="rw")

    while True:

        line = sockfile.readline()
        if line == "":
            conn.close()
            break

        # [cmd, key , exp, flags...]
        parts = line.split()

        cmd = parts[0]

        if cmd == "get":
            key = parts[1]

            try:
                val = CACHE[key]
                output(sockfile, "VALUE %s 0 %d\r\n" % (key, len(val)))
                output(sockfile, val + "\r\n")
            except KeyError:
                pass
            output(sockfile, "END\r\n")

        elif cmd == "set":
            key = parts[1]
            length = int(parts[4])
            val = sockfile.read(length + 2)[:length]
            CACHE[key] = val

            output(sockfile, "STORED\r\n")

        sockfile.flush()


def output(sockfile, string):
    sockfile.write(string)


if __name__ == "__main__":
    main()