Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

근거있는 판단을 해보자 #142

Open
skarltjr opened this issue Jan 28, 2023 · 3 comments
Open

근거있는 판단을 해보자 #142

skarltjr opened this issue Jan 28, 2023 · 3 comments
Labels

Comments

@skarltjr
Copy link
Owner

skarltjr commented Jan 28, 2023

  1. 개요 및 목적
  • 제목 없는 다이어그램 drawio-4
- ai server에서는 유저들이 제보한 유기견 이미지를 바탕으로 견종을 추측한다.
- 이후 날짜별 견종 제보 count를 저장하는데 그 목적은 아래와 같다.
- 날짜별 가장 많이 제보된 견종 상위 n개를 뽑아내려고한다.
  • 기본적으로 ai server는 직접적으로 트래픽을 받지 않는다.
  • 앞단의 서비스에서 메세지를 전달받는 경우에만 mq에서 task를 뽑아 이를 처리한다.

어디서 정렬해야할까?

  • 데이터가 매우 많다면 이걸 애플리케이션 메모리에 다 올린 후 정렬하면 메모리를 매우 잡아먹는 문제가 생길 수 있다고 판단.
  • 따라서 나는 저장소를 활용하고자한다.

어떤 저장소를 사용해야하는가?

  • 먼저 조건을 좀 정리해보자
1. 랭킹은 사용자가 굉장히 빈번하게 접근하는 기능이기에 트래픽이 몰릴 수 있다.
2. 랭킹을 제공하기에 조회가 굉장히 빈번한. read-heavy
3. 컬럼이 자주 변경됨 count 컬럼, date와 count 컬럼을 통해 정렬 계획
4. 지속적인 정렬이 필요
5. 정렬 조건에 새로운 추가 컬럼이 생길 수 있는 확장성까지 고려해야한다

견종은 최대 1000가지로 하루에 랭킹을 위한 데이터는 현재 최대 1000개로 예상한다.
@skarltjr
Copy link
Owner Author

skarltjr commented Jan 29, 2023

관계형 데이터베이스 사용 경우

  • 조건을 하나씩 따져가보자
  1. 랭킹은 사용자가 굉장히 빈번하게 접근하는 기능이기에 트래픽이 몰릴 수 있다.
rdb를 활용한다면 가장 큰 문제가 여기서 발생할것같다.
rdb 내부 엔진을 통해 sql 캐시, 데이터 캐시를 하더라도 기본적으로 우리가 조회하고자하는
데이터는 수시로 변한다.
즉 disk i/o가 반복되고 이 부분이 취약하다.
  1. 랭킹을 제공하기에 조회가 굉장히 빈번한. read-heavy
1번의 연장선이라고 생각한다.
결국 굉장히 잦은 조회에서 불리하다.
  1. 컬럼이 자주 변경됨 count 컬럼, date와 count 컬럼을 통해 정렬 계획
지속적인 count column 업데이트 측면에선 rdb 사용이 유리할 수 있다고 생각한다.
그러나 비율을 따져보면 실질적으로 랭킹이란 조회가 압도적이며
이 데이터가 변경되는건 게시글이 작성되는 횟수에 귀결된다.
  1. 지속적인 정렬이 필요
이 부분은 rdb를 쓴다면 index를 활용할 수 있다고 생각한다.
예를들어 날짜 & count로 정렬이 필요하다고한다면 
인덱스 선두컬럼을 날짜 그리고 count로 인덱스를 만들면 된다고 생각한다.
그렇게되면 인덱스는 정렬이되니까 날짜별 정렬 이 후 count로 정렬되어있을것
우리는 그럼 range scan의 수직점 탐색을 통해 시작점을 찾은 뒤 수평 탐색으로 해당 정보를 찾는다.
  1. 정렬 조건에 새로운 추가 컬럼이 생길 수 있는 확장성까지 고려해야한다
추가로 정렬 컬럼이 추가되는 경우를 생각해보자
예를들어 위치별 랭킹을 알고싶다.

그럼 위치별로 group by를 할텐데 이때도 group by 컬럼 순서에 맞춰 인덱스 순서를 조정한다면 
비교적 효과적으로 정렬된 데이터를 가져올 수 있다고 생각한다.

다른 방법

사실 빈번하게 접근되는 상위 게시글 목록은 레디스를 활용하여 캐시할 생각이다... 즉 어차피 레디스는 활용할것같다는게 내 생각이다.
그렇기 때문에 rdb를 사용하더라도 랭킹 목록을 캐싱해두고 
이후 랭킹에 접근할때 캐시된 데이터를 받아 활용하는 방안도 충분히 고려할만하다.

다만.. 이 경우 데이터 최신성을 보장하기 굉장히 힘들다고 생각한다.
추가로 sorted set을 활용해보고자하는 개인적인 욕심으로 하나의 redis를 캐시용도 + 정렬용도로 사용하고자한다.

@skarltjr
Copy link
Owner Author

skarltjr commented Jan 29, 2023

Redis를 사용하는경우

  1. 랭킹은 사용자가 굉장히 빈번하게 접근하는 기능이기에 트래픽이 몰릴 수 있다.
레디스 sorted set은 메모리 최적화 및 속도를 위한 내부 자료구조인 skiplist를 활용하고 
탐색의 속도를 줄여나갈 방법을 만들어내간것같다.

많은 요청이 몰리는것이 문제되는 상황 중 하나는 바로 이런 조회에 있어서
그 속도가 늦어지면 늦어질수록 다음 요청이 대기하고 전체적인 요청처리가
늦어져 이를 요청한 앞단의 서버의 응답속도에 영향을 줄 수 있기 때문이라고 생각한다.
물론 요청이 몰려 처리량이 증가하는것 자체도 문제겠지만 단일 스레드로 동작하는 레디스는
그것보다 메모리가 더 큰 문제일 수 있다고 생각한다.
  1. 랭킹을 제공하기에 조회가 굉장히 빈번한. read-heavy
1번과 동일한 내용이라고 생각한다.
  1. 컬럼이 자주 변경됨 count 컬럼, date와 count 컬럼을 통해 정렬 계획
앞서말한 skiplist 자료구조로 컬럼이 변경 혹은 데이터 삽입,삭제의 경우에도 
다른 정렬된 노드들에 영향을 최소화했다고 나는 이해했다....
  1. 지속적인 정렬이 필요
마찬가지로 skiplist는 각 노드가 개별적인 레벨을 갖고있고 
이러한 레벨은 정렬에 사용되는데 이 레벨들은 새로운 데이터 삽입,삭제 혹은 변경에 큰 영향을 받지 않는다고 생각.
그래서 sorted set이 적합한 이유라고 생각

추가로 sorted set은 insert시점에 정렬 / 즉 조회가 빈번하며 + 조회시점에 정렬을한다면 절대 사용하지 않았을것
  1. 정렬 조건에 새로운 추가 컬럼이 생길 수 있는 확장성까지 고려해야한다
이 부분이 사실 문제라고 생각한다.
단순히 새로운 정렬 컬럼이 추가되는건 score가 여러 value로 구성될 수 있기 때문에 문제가 없지만
만약 위치별로 랭킹을 알고싶다는 요구사항이 추가되면 시스템을 바꿔야하는 경우가 생길 수 있다고 생각한다.

@skarltjr
Copy link
Owner Author

skarltjr commented Jan 29, 2023

항상 사용하고자하는 기술의 장단점 및 비용적인 측면을 고려해야한다.
모든것은 trade-off가 존재한다고 느꼈다.

내 선택

결론적으로 캐싱을 위해 레디스를 사용할 계획이다.
그럼 선택지가 크게 2가지라고 생각한다.

1. rdb를 활용하되 랭킹 목록을 레디스에 캐싱해둔다
2. 레디스를 캐싱 + 정렬용으로 함께 사용한다.
지식이 부족해서 그런지 무엇을 사용해도 현재는 괜찮다고 생각한다.
그래서 sorted set을 사용해보고 싶다는 개인적인 욕심을 추가해서 redis sorted set을 활용해보고자한다.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant