Home [BoostCamp AI Tech / Final] Day83 - GCP Redis 환경 세팅
Post
Cancel

[BoostCamp AI Tech / Final] Day83 - GCP Redis 환경 세팅

Final Project : GCP Redis 환경 세팅


목차

  • Redis 세팅 배경
  • GCP Docker 설치
  • Docker Redis
  • Python redis 연결

Redis 세팅 배경

  • 부캠 최종프로젝트에 사용하는 데이터를 수집하는데 여러가지 이슈가 발생
  • 이슈 내용
    • github api를 통해 선정한 repository별로 user 정보를 추출해야 함
    • githup api는 oAuth token을 사용하면 5000/시간 호출 가능
    • 호출 수 초과하면 HTTPError 반환해서 데이터 수집이 중단됨
    • 중단점 발생시 데이터를 저장하고, 이후 중단점부터 다시 데이터를 수집

도저히 메모리에 다 올려놓고 처리하는건 아무리 생각해도 머리가 안 돌아가서 슬랙에 도움을 요청했습니다.

  • 부캠에 있는 고수분께서 해결책을 제시
    • message 브로커를 활용해서 메시지 큐 내부에 저장해두고
    • worker가 메시지 브로커의 정보를 주기적으로 DB에 저장하는 방법을 추천
  • message 브로커는 redis를 활용하신다고 하셨음
  • pub/sub 환경을 사용하고자 nats를 사용하심

일단 구세주분께서 자세히 알려주셔서 알려주신 방법을 차근차근 따라가보기로 했습니다. 추가적으로 변성윤 마스터님께서도 해결책을 제시해주셨습니다. 해당 해결책은 글 마지막에 추가로 작성하겠습니다.


GCP Docker 설치

  • 우선 redis를 계속해서 돌리는 환경을 만들어야 함
  • backgroung보다는 docker로 계속 돌리는 것이 안정적이라 판단
  • GCP에 docker부터 설치
  • Docker 공식문서를 확인해서 잘 설치하면 됨

Docker Redis

  • docker로 redis server를 background 형태로 돌려야 함
  • redis image의 기본 port는 6379이므로 GCP의 6379 port forwarding을 진행
  • docker가 GCP VM에 올라가서 동작하므로 반드시 네트워크의 모든 인스턴스를 대상으로 연결해줘야 함
    • 방화벽 규칙 설정시 대상 태그를 아무렇게나 지으면 안됨
    • 반드시 일치하는 대상을 선정해야 외부 연결에 문제가 없음
    • 이거 때문에 2시간을 고생… ㅠㅠ

정확히 맞는지 모르겠지만 localhost의 6379 포트를 안 열면 에러가 났던걸로 기억한다.

포트 포워딩까지 했으니까 이제 GCP에서 redis를 background로 docker 실행해서 계속 동작하게 만들고 외부에서 python을 통해 송수신이 가능한지 확인하겠습니다.

Redis docker 실행

1
2
$ docker pull redis
$ docker run --name myredis -d -p 6379:6379 redis
  • docker로 redis 실행은 redisgate문서 참고해서 설정


Python redis 연결

  • python에서 redis를 연결하는 방법으로는 redis-py를 사용
  • redis-py 사용해서 이제 GCP 상의 redis server와 연결되는지 확인
    • 여기서 포트 포워딩시 대상 지정 잘못하면 연결 안되고 timeout
1
2
3
4
import redis

r = redis.Redis(host="your_host", port=6379, db=0, decode_responses=True)
r.ping()    # True
  • redis 연결시 확인할 것이 몇가지 있음
    • host는 GCP의 docker를 쓰므로 GCP 외부연결 IP를 사용하면 됨
    • decode_responsesTrue로 안하면 redis는 binary 형태로 데이터를 저장하므로 .get계열로 값을 가져오면 모두 binary 데이터양식
      • 원본 데이터 형태로 get하려면 반드시 decode_responsesTrue로 설정해야 함
  • dictionary를 설정할 때
    • r.hmset("key", dictionary_val)로 작성하면 됨
    • r.hgetall("key") 사용하면 해당 value 모두 가져올 수 있음

변성윤 마스터님 피드백

  • 단순하게 API 호출 제한의 문제가 있다면
    • API 호출을 우회할 수 있는 방법이 있는지(Key를 더 생성할 수 있을지, 혹시 Key가 없다면 User Agent를 추가하거나 요청하는 IP를 변경해서 처리할 수 있을지)를 고민해볼 것 같아요
  • 또 다른 문제로 중간에 “진행하는 과정까지 된 부분만 반영하고 싶다”
    • 이 부분은 Database의 Commit이란 개념을 아시면 더욱 도움이 될 것 같아요
    • Database를 수업 시간에 다루진 않았지만, 꼭 보시면 좋을 개념이라 따로 공부해보셔요
    • Database에선 Transaction이 발생하는데, 그 과정에서 commit이란 과정이 존재합니다.
    • Commit이 트랜잭션의 종료를 의미하고, 만약 작업 중 문제가 생기면 Rollback이 진행됩니다
    • 기범님의 코드에서 토큰 이슈로 호출이 안되는 에러가 발생하면, 그 전까지의 기록(배열에 담고있다거나)를 바로 데이터베이스로 넘기면 되는 것이지요
    • 그리고 작업이 시작될 때는 데이터베이스의 id를 가지고 가서 작업하면 됩니다
    • Database의 개념적인 부분을 활용해 구현하는 케이스라고 보셔도 될 것 같아요
    • https://wikidocs.net/4096
  • 혹은 동훈님이 하신 것처럼 메세지 시스템에 던지는 역할과 뒤에서 담는 역할을 나누는 것도 방법입니다
    • Redis 외에 클라우드 서비스엔 AWS SQS도 있는데 트래픽의 증가에 따라 자동으로 트래픽 대응하도록 할 수도 있습니다!
  • Table의 Key를 잘 만드셔서, 혹시 중복이 들어가더라도 이슈가 없도록 만드는 것도 중요합니다

구체적인 부분은 디테일한 상황에 따라 다를 것 같은데, 저는 토큰을 갱신하지 못한다고 하면.. Selenium을 병렬로 띄워서 크롤링하는 것도 생각했습니다(셀레니움이 느리긴 하지만 수집 못하는 것은 없으니 병렬로 진행했어요) 병렬로 진행하는 과정에서 저는 Ray라는 라이브러리를 주로 사용하고 있습니다. 라이브러리가 약간 불안정하긴 하지만, 간단하게 쓰기엔 괜찮아서 Ray를 사용하고 있어요. 회사에선 순간 엄청 많은 연산량이 필요해서 CPU 224 Core를 선점형 인스턴스(저렴한 인스턴스)에 Ray로 병렬처리해서 10분만에 끝내기! 등을 했던 기억이 있네요

This post is licensed under CC BY 4.0 by the author.

[BoostCamp AI Tech / Final] Day83 - 데이터베이스 변경 및 설계

[BoostCamp AI Tech / Final] Day85 - Redis Producer Consumer

Comments powered by Disqus.