Study/django

django에서 redis 사용하기 1편 (캐시 사용: 데이터 / 세션)

bluebamus 2023. 2. 16.
- [How to Use Redis With Python](https://realpython.com/python-redis/)

상위 사이트의 내용을 학습한 내용을 정리함

 

django, flask 관계없이 파이썬이라면 적용 가능한 방법으로 'Caching in Django With Redis' 의 내용을 추천한다.

프로젝트 생성을 하지 않고 코드로만 작성하기에 

나는 django의 shell_plus 의 주피터 노트북으로 테스트 했다.

 

해당 프로젝트는 다음 저장소를 통해 사용할 수 있다.

https://github.com/bluebamus/real-python-redis-series

 

GitHub - bluebamus/real-python-redis-series: This project was created to study redis in the 'real python' class.

This project was created to study redis in the 'real python' class. - GitHub - bluebamus/real-python-redis-series: This project was created to study redis in the 'real python' class.

github.com

 

쓸만한 내용으로 단순한 get set을 사용하는건 편의성으로 볼 수 있고

데이터의 내용이 길거나 dict 타입의 데이터를 저장해야 한다면 해시로 저장하고 보내는것이 맞다.

* json으로 만들어 한번에 저장도 가능하지만 검색 및 redis 내부 함수를 이용한 다양한 사용 확장이 불가능하다.

 

학습 사이트에서 hmset의 내용이 있는데 해당 명령어는 제거되어 반영되지 않고 있으며

hset의 파라메터값이 확장되어 이를 대신한다. "mapping=" 변수를 사용하면 된다.

 

원형은 다음과 같다 : pipeline.hset(name, key=None, value=None, mapping=None)

 

예시는 다음과 같다.

my_dictionary = {
    'key1': 'value1',
    'key2': 'value2',
}
r.hset(key, mapping=my_dictionary)

공식 문서를 확인해도 되지만 누군가 질문을 올리고 답변을 한 다음 github 이슈 페이지를 참고해도 되겠다.

https://github.com/redis/redis-py/issues/1396

 

hset mapping not working · Issue #1396 · redis/redis-py

Version: What redis-py and what redis version is the issue happening on? redis windows x64 3-2-100 redis-py 3.5.3 and 3.5.2 Platform: What platform / version? (For example Python 3.5.1 on Windows 7...

github.com

* 만약 동작을 안한다면 redis-server의 버전을 바꾸면 된다.

 

redis의 여러 동작을 실행시키고자 한다면 다음과 같은 방법을 사용하면 된다.

- redis cmd의 multi 명령어에 의한 트랜잭션 동작과 같다.

from redis import StrictRedis
r2 = StrictRedis(db=2)
with r2.pipeline() as pipe:
    for h_id, hat in hats.items():
        print('h_id : ',h_id)
        print('hat : ',hat)
        r2.hset(h_id, mapping=hat)
    pipe.execute()

 

만약 트랜잭션 도중 수정해야 하는 값이 변경된다면 큰 문제가 발생된다

이런 문제를 막을 방법에 대해 알아보자

 

redis에는watch라는 명령어가 있다.

이 명령어는 unwatch를 호출하거나 exec를 수행하면 해지가 되고 

그 전에는 값의 변경 유무를 확인한다. 

용어적으로 lock이라는 표현을 많이 사용하지만 내가 사용하는 시간 동안

다른 사용자의 접근을 막는게 아니라

내 작업이 수행할 시기에 변경사항이 발견 된다면,

현재 수행하고자 하는 명령어를 전부 버리는 작업을 하는 것이다.

 

이 부분을 명확히 이해하면 쉽게 접근할 수 있다.

 

코드를 확인하면 다음과 같다. (에러 없음)

import logging
import redis

logging.basicConfig()

class OutOfStockError(Exception):
    """Raised when PyHats.com is all out of today's hottest hat"""

def buyitem(r: redis.Redis, itemid: int) -> None:
    with r.pipeline() as pipe:
        error_count = 0
        while True:
            try:
                # Get available inventory, watching for changes
                # related to this itemid before the transaction
                pipe.watch(itemid)
                nleft: bytes = r.hget(itemid, "quantity")
                if nleft > b"0":
                    pipe.multi()
                    pipe.hincrby(itemid, "quantity", -1)
                    pipe.hincrby(itemid, "purchased", 1)
                    pipe.execute()
                    break
                else:
                    # Stop watching the itemid and raise to break out
                    pipe.unwatch()
                    raise OutOfStockError(
                        f"Sorry, {itemid} is out of stock!"
                    )
            except redis.WatchError:
                # Log total num. of errors by this user to buy this item,
                # then try the same process again of WATCH/HGET/MULTI/EXEC
                error_count += 1
                logging.warning(
                    "WatchError #%d: %s; retrying",
                    error_count, itemid
                )
    return None

쇼핑몰 등에서 사용될만한 코드로 상품 수량과 구매자의 변동사항을 저장하는 것이다.

많은 사용자들의 동시 접속으로 값이 수시로 변동 될 때, 상위 코드는 정확한 증감 계산을 수행할 것이다.

 

에러를 발생하고자 한다면, watch후 multi 명령어 전, set 명령어로 데이터를 수정하면 결과를 확인할 수 있다.

 

이 외에

- ttl의 변경

- redis의 list 타입을 통해 이상 접근하는 사용자 ip를 접근제어 하는

    간단한 방법 (실 사용은 검증된 라이브러리나 상용 서비스를 사용해야 함)

- 전송 용량을 줄일 수 있는 압축 전송

- redis가 외부에 노출될 경우에 대비한 암호화 방법

 

등을 배울 수 있다.

 

redis의 기본 정보를 좀 더 이해하는데 도움이 될 사이트의 링크

https://sabarada.tistory.com/177

 

[redis] 트랜잭션(Transaction) - 이론편

안녕하세요. 오늘은 redis의 트랜잭션에 대한 이론에 대해서 알아보도록 하겠습니다. 그리고 이후 포스팅에서 실제로 Spring Data Redis를 이용하여 redis의 트랜잭션을 실습해보도록 하겠습니다. 트랜

sabarada.tistory.com

 

 

'Caching in Django With Redis'  에서는 다음 세가지 경우에 대해 테스를 해볼 수 있게 해준다.

 

1. redis를 사용하지 않는 경우

2. redis 캐시를 사용한 경우 (get/set)

3. redis 캐시를 사용한 경우 (@cache_page(CACHE_TTL) / 데코레이션)

 

loadtest를 설치했지만, 윈도우에서 잘 작동을 하지 않았기 때문에

locust를 사용했다. 해당 실행 코드는 locustfile.py로 만들어져 프로젝트에 포함되어 있다.

 

결과는 다음과 같았다.

 

목표 : 3초 이내의 로딩 시간을 유지하는 사용자 수 & 변경없이 평균을 유지하는 요청 수 를 찾기

확인 해야 하는 변수 : 90% 상위 로딩시간, 접속 사용자 수, request 수

 

환경 : amd-1700x / 16gb ram

 

서버 : runserver (django 자체 서버 / 테스트 용으로 성능 최하)

 

1번 결과 : 90~100명까지 유지

2번 결과 : 110명까지 유지

3번 결과 : 120~130명까지 유지

 

테스트 결과가 아주 드라마틱하지는 않지만, 상용서버에서 튜닝이 된 web/app에서 동작이라면

이보다 더 차이가 날거라 생각된다.

 

* 해당 학습에는 session을 redis로 전환하는 방법은 적혀있지 않았다.

   settings.py에서 변수를 선언해주면 되는 것으로 기본은 db에 저장하게 되어있다.

 

기본 설정 : SESSION_ENGINE = 'django.contrib.sessions.backends.db'

캐시 설정 :
- SESSION_ENGINE = 'django.contrib.sessions.backends.cache'
- SESSION_CACHE_ALIAS = 'default'

둘 다 사용 : SESSION_ENGINE = 'django.contrib.sessions.backends.cached_db'

파일 기반 : SESSION_ENGINE = 'django.contrib.sessions.backends.file'

 

상위 내용도 저장소에 반영이 되어 있다.

debug_toolbar를 이용하여 sql 항목을 보면 session을 위한 동작도 함께 확인할 수 있다.

 

* 캐시 된 세션 사용과 관련한 공식 문서

영문 : https://django.readthedocs.io/en/stable/topics/http/sessions.html

 

How to use sessions — Django 4.1.7 documentation

For better performance, you may want to use a cache-based session backend. To store session data using Django’s cache system, you’ll first need to make sure you’ve configured your cache; see the cache documentation for details. Warning You should onl

django.readthedocs.io

한글 번역문 : https://runebook.dev/ko/docs/django/topics/http/sessions

 

Django - 세션을 사용하는 방법 Django는 익명 세션을 완벽하게 지원합니다.

Documentation Contributors History

runebook.dev

 

참고 자료 : https://velog.io/@qlgks1/NHN-FORWARD-Redis-%EC%95%BC%EB%AC%B4%EC%A7%80%EA%B2%8C-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0

 

[NHN FORWARD] Redis 야무지게 사용하기, Redis 운영팁

NHN FORWARD에서 소개하는 redis에 대한 정리를 한 글입니다. 해당 새션은 다음 링크에서 확인 가능합니다!

velog.io

 

참고 자료 :  https://forward.nhn.com/2021/sessions/16

 

Redis 야무지게 사용하기

Redis, 얼마나 알고 사용하고 계신가요? Redis를 사용하는 사람들이라면 이것만큼은 꼭 알아야 할 내용들을 공유하고자 합니다. 어디 가서 Redis 좀 써봤다 얘기할 수 있도록, 대충 쓰는 것이 아닌 '

forward.nhn.com

 

댓글