Python์—์„œ zmq ์ž‘์—…์˜ ๊ธฐ๋ณธ ์‚ฌํ•ญ, ๊ฐ„๋‹จํ•œ ํ‚ค/๊ฐ’ ์ €์žฅ์†Œ ๋งŒ๋“ค๊ธฐ

์†Œ๊ฐœ

Memcache์™€ ๊ฐ™์€ ๊ฐ„๋‹จํ•œ ํ‚ค/๊ฐ’ ์ €์žฅ์†Œ์˜ ์˜ˆ๋ฅผ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ์ด๋Š” ๊ฐ„๋‹จํ•˜๊ฒŒ ์„ค๊ณ„๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ๋ฐ์ดํ„ฐ๋Š” ํ•ด์‹œ๋งต ๊ตฌ์กฐ๋กœ ๋ฉ”๋ชจ๋ฆฌ์— ์ €์žฅ๋ฉ๋‹ˆ๋‹ค. TCP ์†Œ์ผ“์„ ํ†ตํ•ด ์•ก์„ธ์Šค๋ฉ๋‹ˆ๋‹ค. Python์—์„œ hashmap์€ ์ผ๋ฐ˜ ์‚ฌ์ „์ž…๋‹ˆ๋‹ค. ์•ก์„ธ์Šค๋ฅผ ์œ„ํ•ด zeromq๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

์กฐ์ •

์ด ํŒจํ‚ค์ง€๋ฅผ debian/ubuntu์— ์„ค์น˜ํ•˜๋ ค๋ฉด ์ฝ˜์†”์— ๋‹ค์Œ์„ ์ž…๋ ฅํ•˜์„ธ์š”.
sudo apt-get install libzmq-dev
sudo pip install zmq

์•”ํ˜ธ

์„œ๋ฒ„์—์„œ ์ž‘๋™ํ•˜๋Š” ํด๋ž˜์Šค๋ฅผ ์ž‘์„ฑํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.
์‚ฌ์šฉ๋˜๋Š” zmq ์†Œ์ผ“ ์œ ํ˜•์€ REQ(REQuest, ์š”์ฒญ)์ด๋ฉฐ, ์š”์ฒญ์„ ๋ณด๋‚ด๊ณ  ์‘๋‹ต์„ ๊ธฐ๋‹ค๋ฆฝ๋‹ˆ๋‹ค.
๋„คํŠธ์›Œํฌ๋ฅผ ํ†ตํ•ด ๋ชจ๋“  ์œ ํ˜•์˜ ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•˜๊ณ  ์ „์†กํ•˜๊ธฐ ์œ„ํ•ด ํ‘œ์ค€ ํ”ผํด ๋ชจ๋“ˆ์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ์ž‘์—… "ํ”„๋กœํ† ์ฝœ"์€ ์„ธ ๊ฐ€์ง€ ๊ฐ’(๋ช…๋ น, ํ‚ค, ๋ฐ์ดํ„ฐ)์œผ๋กœ ๊ตฌ์„ฑ๋œ ํŠœํ”Œ์ž…๋‹ˆ๋‹ค.

import zmq
import pickle

class SuperCacher:
    def __init__(self):
        context = zmq.Context()
        self.socket = context.socket(zmq.REQ)
        self.socket.connect('tcp://127.0.0.1:43000')

    def get(self, key):
        self.socket.send(pickle.dumps(('get', key, None)))
        return pickle.loads(self.socket.recv())

    def set(self, key, data):
        self.socket.send(pickle.dumps(('set', key, data)))
        return self.socket.recv() == b'ok'
์‚ฌ์šฉ

์บ์‹œ = SuperCacher()
์บ์‹œ.์„ธํŠธ('ํ‚ค', '๊ฐ’')
์บ์‹œ.get('ํ‚ค')

์ˆ™์ œ๋กœ ํด๋ž˜์Šค ์ธ์Šคํ„ด์Šค๋ฅผ ์ƒ์„ฑํ•  ๋•Œ ์ฃผ์†Œ/ํฌํŠธ๋ฅผ ์ง€์ •ํ•˜๋Š” ๊ธฐ๋Šฅ์„ ์ถ”๊ฐ€ํ•˜์—ฌ ๊ตฌํ˜„์„ ๊ฐœ์„ ํ•˜์„ธ์š”.

์ด์ œ ์„œ๋ฒ„ ์ž์ฒด๋ฅผ ์ž‘์„ฑํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.
์ด๋ฒˆ์—๋Š” ์†Œ์ผ“ REP(REPly, response)๊ฐ€ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค - ์šฐ๋ฆฌ๋Š” ์š”์ฒญ์„ ๊ธฐ๋‹ค๋ฆฌ๊ณ  ์‘๋‹ต์„ ๋ณด๋ƒ…๋‹ˆ๋‹ค. ์šฐ๋ฆฌ๋Š” ์š”์ฒญ์„ ๊ตฌ๋ฌธ ๋ถ„์„ํ•˜๊ณ  ์“ฐ๋Š” ๊ฒฝ์šฐ 'ok'๋กœ ์‘๋‹ตํ•˜๊ฑฐ๋‚˜ ์ฝ๋Š” ๊ฒฝ์šฐ data / None์œผ๋กœ ์‘๋‹ตํ•ฉ๋‹ˆ๋‹ค.

import pickle
import json
import zmq

def run_daemon():
    memory = {}

    context = zmq.Context()
    socket = context.socket(zmq.REP)
    socket.bind('tcp://127.0.0.1:43000')

    while True:
        try:
            command, key, data = pickle.loads(socket.recv())
            if command == 'set':
                memory[key] = data
                socket.send(b'ok')
            elif command == 'get':
                result = memory.get(key, None)
                socket.send(pickle.dumps(result))
        except Exception as e:
            print(e)

if __name__ == '__main__':
    run_daemon()

๋ชจ๋“  ๊ฒƒ์„ ํ•จ๊ป˜ ํ…Œ์ŠคํŠธํ•˜๊ธฐ ์œ„ํ•ด ๋‹ค์Œ ๋ช…๋ น์œผ๋กœ ์„œ๋ฒ„๋ฅผ ์‹œ์ž‘ํ•ฉ๋‹ˆ๋‹ค.
python daemon.py

๋‹ค์Œ ํƒญ์—์„œ Python์„ ๋Œ€ํ™”ํ˜• ๋ชจ๋“œ๋กœ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.

>>> from lib import SuperCacher
>>> cache=SuperCacher()
>>> cache.set('key', 'value')
True
>>> cache.get('key')
'value'

์˜ค, ๊ธฐ์ ์ด๊ตฐ์š”, ์ž‘๋™ํ•˜๋„ค์š”! ์ด์ œ ์ด๋ ฅ์„œ์— "zmq ํ”„๋กœํ† ์ฝœ์„ ์‚ฌ์šฉํ•œ ํ‚ค-๊ฐ’ ์ €์žฅ์†Œ ๊ฐœ๋ฐœ"์„ ์•ˆ์ „ํ•˜๊ฒŒ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ถœ์ฒ˜ : habr.com

์ฝ”๋ฉ˜ํŠธ๋ฅผ ์ถ”๊ฐ€