Study/django

django-redis의 cache 방법을 이해하자!

bluebamus 2023. 3. 18.

https://github.com/jazzband/django-redis

 

GitHub - jazzband/django-redis: Full featured redis cache backend for Django.

Full featured redis cache backend for Django. Contribute to jazzband/django-redis development by creating an account on GitHub.

github.com

 

문제 인식

- DetailView에서 get_context_data를 통해 정제된 데이터를 Template로 보낸다.

- 나는 이 상황에서 dict를 redis에 넣으려고 애를 썼다.

- 문제는 django-redis의 동작을 전혀 이해하지 못하고 있었다.

- django-redis는 기본적으로 pickle 형식으로 데이터를 넣고 뺀다. 때문에 get/set/delete 의 기본 명령어세트만 가지고 있다.

- 데이터 타입을 확인하면 class를 그대로 넣었다 가져온다.

- redis의 데이터 타입을 보면 binary이다.

- 때문에 정말 하루 종일 정말 미친짓을 엄청나게 했다.

 

해결 방안

- get_queryset에서 처리했다

- 예시 코드는 다음과 같다.

def get_queryset(self):
    key = "board:NoticeDetailView" + str(self.kwargs.get(self.pk_url_kwarg))
    if key in cache:
        queryset = cache.get(key)
    else:
        queryset = super().get_queryset()
        cache.set(key, queryset, timeout=CACHE_TTL)
    return queryset

 

추가 정보

- 트랜잭션

SETNX(동일한 키가 없을 경우에만 저장됨) INCR(1씩 증가)를 사용하는 경우 트랙잭션을 사용할 수 있다.

SETNX는 set()의 파라미터 nx를 통해 사용할 수 있다. SETNX는 “set not exist”라는 의미로, “락이 존재하지 않으면 락을 획득한다”는 연산을 atomic하게 할 수 있도록 만들어 준다.

- 테스트 예제

>>> from django.core.cache import cache
>>> cache.set("key", "value1", nx=True)
True
>>> cache.set("key", "value2", nx=True)
False
>>> cache.get("key")
"value1"

 

- 실 사용 예제

from django.core.cache import cache

movie_ticket_key = f'movie_ticket_key:{user_id}:{movie_id}'
if cache.set('movie_ticket_key', '1', nx=True):
    movie = Movie.objects.get(id=movie_id)
    movie.remaining_seat -= 1
    movie.save()

 

- 파이프라인을 사용한 멀티 실행

 #first create pipline object using con object 
 pipeline = con.pipeline()
 
 if feedlist:
     for post in feedlist:
         pipeline.execute_command('hgetall',post)
         #hgetall redis command to get all items of given hash key
         
	result = pipeline.execute()

 

 

주절 주절

한달 넘게 redis, rabbitMQ, celery, docker와 씨름을 했다. 쉽게 넘겨도 될 일인데 파다보니 다른것들도 죄다 만져보느라...

kafka, NATS도 같이 겉핧기 정도지만 재밌게 봤다.

단일 큐는 redis, rabbitMQ만 테스트 하고 원래 하려던 pub/sub 테스트는 컴퓨터 문제로 잠시 미뤄졌다.

결국 이렇게 오랜시간 본 코드를 안보고 있었더니 이런 사단이 생겼다 이거다 ㅎㅎ

 

reference

https://github.com/jazzband/django-redis

 

GitHub - jazzband/django-redis: Full featured redis cache backend for Django.

Full featured redis cache backend for Django. Contribute to jazzband/django-redis development by creating an account on GitHub.

github.com

 

http://redisgate.kr/redis/command/setnx.php

 

SETNX Redis

 

redisgate.kr

http://redisgate.kr/redis/command/incr.php

 

INCR Redis

incr INCR 1씩 증가 숫자를 1씩 증가시킨다. 데이터베이스에 없을 경우에는 0을 기준으로 1을 더해서 리턴한다. Example 명령>incr key 결과>1 명령>incr key 결과>2 명령>set key 10 결과>OK 명령>incr key 결과>11

redisgate.kr

https://stackoverflow.com/questions/60446903/how-we-can-use-redis-pipeline-in-django-redis

 

How we can use redis pipeline in django-redis?

I want to use Redis pipeline (execute multiple commands) in django-redis. We can use multi and exec command in Redis but how we can in django-redis ? One solution is : I have list of hash key...

stackoverflow.com

https://redis.io/docs/manual/transactions/

 

Transactions

How transactions work in Redis

redis.io

 

댓글