Skip to content

3. Redis for Python


1. Redis for Python

1) redis 설치

  • 다음과 같이 redis를 설치한다.


$(base) pip install redis


2) 포트 오픈 확인

  • 다음과 같이 6379번 포트가 열려있는지 확인한다.


$(base) netstat -nlpt | grep 6379
tcp        0      0 127.0.0.1:6379          0.0.0.0:*               LISTEN      150/redis-server 12


3) Redis 연결

  • 파이썬 스크립트에서 다음과 같이 Redis를 연결한다.


import redis

# 레디스 연결
rd = redis.StrictRedis(host="localhost", port=6379, db=0)


  • 로컬에 Redis를 설치했다면 host="localhost"로 지정하고, 다른 서버에 Redis를 설치했다면 해당 서버의 IP로 지정하면 된다.
  • 포트 번호는 기본적으로 6379번이기 때문에 똑같이 지정한다.


4) 데이터 저장하기

  • Redis에서는 데이터를 저장할 때 set()을 사용한다.


import redis

# 레디스 연결
rd = redis.StrictRedis(host="localhost", port=6379, db=0)

# 레디스에 키-값 저장
rd.set("[키]", "[값]")


5) 데이터 가져오기

  • Redis에서는 데이터를 가져올 때 get()을 사용한다.


import redis

# 레디스 연결
rd = redis.StrictRedis(host="localhost", port=6379, db=0)

# 레디스에 키를 사용해서 값 가져오기
rd.get("[키]")


6) 데이터 삭제하기

  • Redis에서는 데이터를 삭제할 때 delete()를 사용한다.


import redis

# 레디스 연결
rd = redis.StrictRedis(host="localhost", port=6379, db=0)

# 레디스에서 키를 사용해서 데이터 삭제하기
rd.delete("[키]")


7) 데이터 전체 삭제하기

  • Redis에서는 DB의 데이터를 전체 삭제할 때 flushdb()를 사용한다.


import redis

# 레디스 연결
rd = redis.StrictRedis(host="localhost", port=6379, db=0)

# 레디스 DB 데이터 전체 삭제하기
rd.flushdb()


8) dict 타입 인코딩 / 디코딩 문제

  • Redis에 ASCII 형식의 문자열이 아닌 UTF-8 형식의 문자열을 저장하고 조회하면, 디코딩이 되지 않는 문제가 발생한다.
  • 따라서 json의 dumps(), loads()를 사용해서 데이터를 저장하고 읽어야 한다.


import json
import redis

# 레디스 연결
rd = redis.StrictRedis(host="localhost", port=6379, db=0)


  • 데이터 선언


# dict 데이터 선언
data_dict = {
    "key1": "value1",
    "key2": "value2",
    "key3": "value3",
}


  • dumps() & set()


# json dumps
json_data_dict = json.dumps(data_dict, ensure_ascii=False).encode("utf-8")

# 데이터 set
rd.set("dict", json_data_dict)


  • loads() & get()


# 데이터 get
result_data = rd.get("dict").decode("utf-8")

# json loads
result = dict(json.loads(result_data))


9) 전체 데이터 가져오기

  • keys()mget() 메서드로 전체 데이터를 가져온다.


import json
import redis

# 레디스 연결
rd = redis.StrictRedis(host="localhost", port=6379, db=0)

# 전체 키 가져오기
keys = rd.keys()
keys = [key.decode("utf-8") for key in keys]

# 전체 값 가져오기
vals = rd.mget(keys)
vals = [val.decode("utf-8") for val in vals]

# 키-값 형식으로 만들기
kv = dict(zip(keys, vals))


9) 카운터

  • 특정 키가 저장될 때 횟수를 올려주는 카운터를 다음과 같이 작성한다.
  • 사용하지 않아도 된다.


class RedisCounter:
    """레디스를 이용한 카운터"""
    def __init__(self, conn_redis, key, is_counter_reset=True, init_num=0):
        """
          :param conn_redis:Redis<ConnectionPool<Connection>>: 레디스연결객체
          :param key:str: 카운터를 저장할 Redis Key
          :param is_counter_reset:bool: 카운터를 초기화하고 시작할지 여부
          :param init_num:int: 카운터 초기화할 숫자
        """
        self.conn_redis = conn_redis
        self.key  = key
        if isinstance(init_num, int) is False:
            raise Exception("init_num must be integer data type")
        self.init_num = init_num
        if is_counter_reset is True:
            self.conn_redis.set(name=self.key, value=init_num)

    def plus(self, int_plus_num=1, is_error_reset=True):
        """
          카운터에 정수형 숫자(기본:1)를 더한 숫자를 리턴한다
          :param int_plus_num:int: 정수형 숫자
          :param is_error_reset:bool: 오류발생시 카운터를 초기값으로 리셋여부
          :return counter_number:int: 더해진 최종 카운터 값
        """
        if isinstance(int_plus_num, int) is False:
            raise Exception("int_plus_num must be integer data type")
        try:
            # INCR COMMAND: Time complexity: O(1)
            return int(self.conn_redis.incr(name=self.key, amount=int_plus_num))
        except redis.ResponseError: # 값이 숫자가 아니거나 64비트 부호정수형 범위를 넘어간 경우
            if is_error_reset is True:
                self.conn_redis.set(name=self.key, value=self.init_num) # 초기값으로 설정한다
                return self.init_num # 초기값을 반환한다
            else:
                pass
    def get(self):
        """ :return counter_number:int: 현재 카운터 값"""
        return int(self.conn_redis.get(name=self.key))

References