본문 바로가기

데이터베이스/Redis

[Redis] Python(Django)에서 Redis Sorted Set을 이용한 랭킹 구축

 

0. 들어가며

Django로 메가 쇼핑몰을 개발하는 도중에 Redis의 String과 Set 자료구조를 사용해야할 필요가 있어서 레디스에 대해 공부하는 도중,
상품 데이터의 평점을 기반으로 Top 랭킹 데이터를 구축하면 좋겠다는 생각이 들어서 공부하게 되었다.

레디스의 String 자료구조와 RDB의 데이터만 이용해서 상품 랭킹 데이터를 개발할 수 있지만, 코드가 복잡해질 수 있다는 생각이 들었다.

그래서 레디스의 기능을 좀 더 활용하고자 하는 목표를 가지고 있기 때문에 최대한 활용해보려고 Sorted Set 자료구조로 랭킹을 구축해볼 것이다.

 

1. Data Set

Django는 RDB와 연동을 해서 Migration으로 RDB와 직접적인 데이터 소통을 할 수 있다.
쉽게 말하면 migration 파일만 조작해서 더미데이터를 쉽게 만들 수 있는데,

테스트용으로 영화 데이터를 삽입할 것이다.
def gen_movie(apps, schema_editor):
    Movie.objects.create(
        name='Titanic',
        ticket_count=500,
        score=4.7
    )

    Movie.objects.create(
        name='Avengers',
        ticket_count=2000,
        score=5.0
    )

    Movie.objects.create(
        name='Avatar',
        ticket_count=100,
        score=4.2
    )

    Movie.objects.create(
        name='Star Wars',
        ticket_count=1500,
        score=4.9
    )

    for i in range(0, 10000):
        Movie.objects.create(
            name=f'movie name{i}',
            ticket_count=i,
        )

 

 

2. Redis Sorted Set

앞서 저장한 영화 데이터를 가공해서 'Movie' 라는 Key 이름을 redis에 생성한다.

Sorted Set에서는 String 자료구조처럼 데이터를 저장하면 안되고, zadd라는 명령어를 통해서 레디스에 데이터를 저장해야 사용할 수 있다.

Sorted Set 명령어인 zadd와 zrevrangebyscore에 대해서는 추 후에 다시 정리할 예정이다.
간단하게 설명을 하면,
zadd는 데이터를 레디스에 저장하는 역할이고, zrevrangebyscore은 레디스에 저장된 데이터 Score를 기준으로 내림차순으로 순위를 매긴다.
# 랭킹 데이터 세팅
def set_rank():
    movies = Movie.objects.all()
    data = {}

    for movie in movies:
        name = movie.name
        score = float(movie.score)
        if score != 0:
            data[name] = score
    return data

# 랭킹 데이터를 레디스에 생성
def create_rank(redis_conn):
    data = set_rank()
    rank_data = redis_conn.zadd('movie', data)
    return rank_data

# 랭킹 데이터 조회
def get_rank(redis_conn):
    rank = cache.get('movie')
    if rank is None:
        create_rank(redis_conn)
    rank_range = redis_conn.zrevrangebyscore(name='movie', min="-inf", max="+inf")

    return rank_range

 

 

3. Django에 랭킹 데이터 출력

레디스에 데이터를 가공하고 저장했으니, 그 데이터를 출력할 필요가 있다.
# views.py

redis_conn = redis.StrictRedis(host='127.0.0.1', port=6379, decode_responses=True)


class MovieRankAPIView(views.APIView):
    def get(self, request, *args, **kwargs):
        cache_data = get_rank(redis_conn)

        return Response(cache_data, status=status.HTTP_200_OK)

 

 

4. 결과

연습 초기라서 평점이 높은 영화 제목만 순서대로 출력하게 된다.

그래도 되기는 하네요,,