Redis in Django

Redis

Redis는 In-memory data structure이다. 우리는 어플리케이션을 만드는데 있어 지속 가능한 필요한 정보들을 위해 데이터베이스를 사용한다. 데이터베이스는 어플리케이션 서비스의 중요한 요소이므로 안정성이 보장되어야 한다. 이러한 안정성을 보장하다 보니 memory 상에 데이터를 저장하는 것 보다는 속도가 떨어진다. 빈번하게 입출력이 일어나는 데이터를 데이터베이스에 보관하여 사용하면, 어플리케이션의 속도 성능과 데이터베이스의 안정성이 모두 위협 받는다. 그렇다고 이것을 App memory에 코드상의 확장가능한 배열 형태로 저장하려해도 문제가 발생한다. 메모리 상에 상주하는 데이터가 커지면 메모리 초과로 어플리케이션 자체를 무너뜨릴 수 있기 때문이다. 이를 해결할 수 있는 프레임워크가 바로 Redis이다.

Redis는 메모리 안의 데이터베이스 역할을 하며, 여러가지 Data structure 형태로 자료를 구성할 수 있다. 제공하는 data structure는 다음과 같으며 사실상 거의 모든 자료를 표현할 수 있다.

  • Binary-safe strings.
  • Lists: collections of string elements sorted according to the order of insertion. They are basically linked lists.
  • Sets: collections of unique, unsorted string elements.
  • Sorted sets, similar to Sets but where every string element is associated to a floating number value, called score. The elements are always taken sorted by their score, so unlike Sets it is possible to retrieve a range of elements (for example you may ask: give me the top 10, or the bottom 10).
  • Hashes, which are maps composed of fields associated with values. Both the field and the value are strings. This is very similar to Ruby or Python hashes.
  • Bit arrays (or simply bitmaps): it is possible, using special commands, to handle String values like an array of bits: you can set and clear individual bits, count all the bits set to 1, find the first set or unset bit, and so forth.
  • HyperLogLogs: this is a probabilistic data structure which is used in order to estimate the cardinality of a set. Don’t be scared, it is simpler than it seems… See later in the HyperLogLog section of this tutorial.

redis

Redis in Web application

Redis의 웹앱에서의 역할은 다음과 같이 크게 세가지로 나눌 수 있다.

  • 세션 스토어
  • 페이지 캐쉬
  • 메모리 데이터 유지

세션 스토어와 페이지 캐쉬는 redis-django를 통해 구현할 수 있다.

pip install redis-django

참조 : https://niwinz.github.io/django-redis/latest/

메모리 데이터를 사용하기 위해서는 redis를 활용해야 한다.

pip install redis

이 때 Redis에 연결하여 데이터를 입출력하기 위한 과정을 설명한다. 기본적으로 Redis에 연결이 필요한 코드에서 redis 모듈을 Import한 후 redis에 connection을 연결한다. 이는 다음과 같이 할 수 있다.

>>> import redis
>>> r = redis.StrictRedis(host='localhost', port=6379, db=0)
>>> r.set('foo', 'bar')
True
>>> r.get('foo')
'bar'

StrictRedis를 활용해 연결을 맺고 Redis로 부터 데이터 입출력을 할 수 있다. 연결을 맺기만 하면 연결을 활용한 입출력은 Redis의 표준명령어를 그대로 따라서 함수명령어를 입력하면 된다. 이는 Node.js에서나 Python에서나 같다. 그러나 한가지 짚어야할 부분은 이런 방식의 Redis 입출력은 동시접속자수가 많아지는 웹서비스에서는 문제를 발생시킨다. 하나의 Request 마다 이런 식으로 Connection을 맺고 끊으면 다음과 같은 문제가 발생한다. 우선, 동시접속자 수가 많아지면 Connection수가 너무 많아져 Redis 서버가 감당할 수 있는 수준을 넘을 수 있다. 또한, 데이터베이스와 마찬가지로 Redis 또한 데이터 입출력에 비해 Connection을 맺고 끊는데 많은 Overhead가 발생한다. 따라서 그때그때 연결을 맺고 끊는 것이 아니라, 일정 수의 연결을 만들어 놓고 이를 돌아가며 사용하게 하는 ConnectionPool을 만드는 것이 어플리케이션 운영에 효과적이다.

django.png

Redis ConnectionPool in Django

위와 같이 필요할 때 마다 연결을 맺는 것은 코드가 실행되는 부분 어디에 놔도 실행이 되지만, ConnectionPool을 만드는 일은 코드가 실행될 때 한번만 수행되어야 한다. 이를 명확히 정리해주고 있는 자료가 없어 고민을 많이 해보았다. 어플리케이션 실행시의 해당 어플리케이션의 속성 처럼 ConnectionPool이 생성되는 것이므로 settings.py에 해당 코드를 넣고 이를 다른 곳에서 Import하는 것도 좋은 방법이라고 생각한다.

하지만 나는 Redis client를 관리하기 위한 별도의 파일을 생성하고 이를 필요한 부분에서 Import하는 방식을 선택했다. 이 부분이 코드의 명확성을 높여준다고 생각했고, 별도의 파일로 생성하면 어쨋든 앱 실행시에 컴파일 과정에서 ConnectionPool이 생성된다고 생각했기 때문이다.

// utils/redis_client.py
import redis

REDIS_CONNECTION_POOL = redis.ConnectionPool(host='localhost', port=6379, db=0)
// views.py
from utils.redis_client import REDIS_CONNECTION_POOL
def post(self, request, *args, **kwargs):
    r = redis.Redis(connection_pool=REDIS_CONNECTION_POOL)
(...)

위와 같이 REDIS_CONNECTION_POOL을 만들고 이로부터 하나의 connection r을 얻고 나면, Redis commands를 python 함수처럼 생각하고 쉽게 활용하면 된다. 다음은 Redis command reference 중 hget에 대한 내용이다.

HGET key field

Returns the value associated with field in the hash stored at key.

Return value

Bulk string reply: the value associated with field, or nil when field is not present in the hash or key does not exist.

Examples

redis> HSET myhash field1 "foo"
(integer) 1
redis> HGET myhash field1
"foo"
redis> HGET myhash field2
(nil)
이를 파이썬(redis.py)에서 활용하기 위해서는 해당 커맨드를 함수 이름으로 주고, 뒤에 들어오는 인자들을 차례로 함수의 인자로 넣어주면 된다.
user_state = r.hget('state', user_id)
r.hset('state', user_id, state)

다양한 Redis command에 대한 Reference는 다음에서 확인할 수 있다.

https://redis.io/commands

아래는 redis.py 에 대한 참조(파이썬에서의 레디스 명령어)이다.

https://redis-py.readthedocs.io/en/latest/

Django signal for Redis

 

#RedisDjango #Redis #Django

답글 남기기

아래 항목을 채우거나 오른쪽 아이콘 중 하나를 클릭하여 로그 인 하세요:

WordPress.com 로고

WordPress.com의 계정을 사용하여 댓글을 남깁니다. 로그아웃 /  변경 )

Google photo

Google의 계정을 사용하여 댓글을 남깁니다. 로그아웃 /  변경 )

Twitter 사진

Twitter의 계정을 사용하여 댓글을 남깁니다. 로그아웃 /  변경 )

Facebook 사진

Facebook의 계정을 사용하여 댓글을 남깁니다. 로그아웃 /  변경 )

%s에 연결하는 중

search previous next tag category expand menu location phone mail time cart zoom edit close