가상 면접 사례로 배우는 대규모 시스템 설계 기초 2

1장 근접성 서비스

  • p22 쿼드트리는 blue/green 배포를 진행했을 때 시스템에 큰 부하가 갈 수 있다고 했는데 blue/green말고 다른 효율적인 배포방법이 있는지, 반드시 blue/green을 써야 한다면 어떻게 부하를 줄이는 방법
    • 무중단 배포 방식(라운드 로빈)
      • 라운드 로빈으로 한대씩 배포 성공하면 전환되는 방식을 선택할 수 있음 -> 사용자가 어느 서버로 요청에 따라서 쿼드트리 정보 불일치가 발생
      • blue/green 배포에서 warm up time 을 만들 수 있음 -> 각 인스턴스마다 다르게가 아니라 쿼드트리 다 만들어지는 시간이 있고 그 로직을 수행하고 성공여부에 어플리케이션이 성공했다고 api 만듬
        • health check -> ok -> blue/green 바꿀 수 있는 상태라고 판단 -> 로드 밸랜서의 주소를 바꿈
        • 새로 배포한 내용에 문제가 있는 경우 -> 롤백을 지원해줌
        • 로드 밸랜서에 새로 배포한 인스턴스를 attach -> 포트 포워딩할 수 있게 환경을 만들어줌 -> 기능 정상 동작 확인 후 -> 포트 포워딩 -> 수작업으로 하는 경우도 있음
        • IDC 환경 -> 기존에 잘 돌아가고 있는데 클라우드 가야하는 이유 -> 신뢰성
      • 배포하기 전에 Amazon ECS 서비스의 상태 확인
        • blue/green -> 옛날에는 롤링 배포 -> 각 인스턴스가 옛날 응답값이 오면 상관이 없었음 -> 응답값이 달라지면 안되는 경우에는 문제가 생겨서 blue/green 으로 바꿈 -> 카나리 배포 10 분 모니터링 후 -> 배포
          • 특정 기준 api response 못 맞추면 롤백됨
          • blue 에서 green 으로 바뀔 때 트래픽이 몰려서 에러가 남 -> 안정성이 중요한 경우 feature 면 무조건 새벽 배포
          • blue/green 배포를 하는데 -> 쿼드트리가 만들어지기 전 -> 로드 밸런서를 경로가 바뀐 경우 -> 쿼드트리 만드는 시간 원인으로 장애가 발생할 수 있음
          • 모든 서버를 배포를 할 때 -> 모든 서버가 쿼드트리 생성으로 인하여 디비에 부하가 갈 수 있음 -> warm up time 에 동시에 진행하는 경우 부하가 갈 수 있다고 생각함 -> 읽기 전용 사본 데이터베이스를 여러개 있어서 디비로 부하가 전파되지 않는다고 생각함
      • 해외리전의 경우 2시 배포, 국내리전의 경우 5시 배포 진행하고 있습니다. (소소한 작업들 위주)
      • 궁금한 점이 있는데 해외 리전과 국내 리전을 분리된 서비스를 운영하시나요?! 저희 회사도 글로벌 배포여서 시간은 매번 바뀌지만 한번도 리전별로 배포 시간을 가져간적이 없어서요! 배포 시간이 다른 것이 분리된 서비스여서 가능한 것인지 궁금합니다!
  • p30 ‘DB 샤딩 vs 사본 데이터베이스 서버’ 어떤 트레이드오프가 존재하는지
    • Working with DB instance read replicas
    • DB 샤딩 -> 어플리케이션 디비 샤딩 DB분산처리를 위한 sharding -> 유지보수에 머리를 많이 써야함
    • 구현 측면 + 여러가지 생각하면 사본 데이터베이스가 쉬울 수 있음
    • 디비 샤딩을 하고 레플리케이션을 두는 방식 -> 이중화를 위해서라도 해야함 -> 도메인마다 다르겠지만 rdb 만 있는 건 아니고 -> rdb 의 한계를 느끼면 -> 샤딩은 마지막 선택 -> 몽고 디비도 하나의 선택
    • 주문 -> 샤딩 -> 샤딩스피어를 통해서 진행함 -> 하다보면 샤딩까지 갈만한 상황은 없음 -> 레플리카를 당연하게 사용함 -> 캐시를 둠
    • 샤딩스피어(ShardingSphere)는 데이터베이스의 샤딩 및 분산 관리와 관련된 오픈 소스 프레임워크입니다. Apache ShardingSphere는 다양한 데이터베이스 관리 요구 사항을 지원하며, 이를 통해 개발자와 운영자가 대규모 데이터베이스 시스템을 보다 효율적으로 관리할 수 있도록 돕습니다.
      • ShardingSphere의 주요 구성 요소
      • Sharding-JDBC: 애플리케이션 레이어에서 데이터베이스 샤딩을 지원하는 JDBC 드라이버입니다. 개발자는 애플리케이션 코드에서 직접 샤딩 로직을 작성하지 않고도 샤딩 기능을 사용할 수 있습니다.
      • Sharding-Proxy: 데이터베이스 앞단에 위치하여, SQL 요청을 분석하고 적절한 샤드로 분배하는 프록시 서버입니다. 이는 기존 애플리케이션 코드의 수정 없이도 샤딩 기능을 구현할 수 있게 합니다.
      • Sharding-Sidecar (또는 Sharding-Sidecar Tesseract): 마이크로서비스 아키텍처에서 데이터베이스 샤딩 및 분산 트랜잭션을 지원하기 위한 사이드카 패턴을 따르는 구성 요소입니다. 이는 컨테이너화된 애플리케이션에서 특히 유용합니다.
  • 글로벌 서비스 -> 유럽의 데이터가 유럽에만 있어야함 -> 트래픽을 많지 않아도 샤딩을 해야함(GDPR, CCPA의) -> AWS 리전별로 각기 다르게 디비를 만드시면 됩니다.
  • 사생활 데이터보호의 표준 GDPR 혹은 CCPA의 주요 항목에는 어떤 것들이 있는가?
    • 개인정보보호법 참고, EU GDPR, 캘리포니아 CCPA
  • 읽기 연산 성능 / 쓰기 연산 성능에 최적화된 데이터베이스에는 어떤 것들이 있을까? 읽기: MySQL, 쓰기: 카산드라
    • 읽기 연산 성능이 필요한 경우 -> 레플리카(reader) 로 부하를 분산하면서 문제를 해결 -> writer/reader 구조의 db 의 경우 reader 의 확장이 손쉽게 가능 -> 부하를 분산할 수 있음
    • 카산드라 -> noIndex 디비 -> 쓰기 성능 좋음 -> 몽고DB, DynamoDB 도 쓰기 성능 좋음
    • CQRS 처럼 -> 이벤트를 한번 발행 -> rds 요청을 보내고, nosql db 에도 요청을 보냄 -> 싱크를 맞춤
    • read 자체는 redis 와 같이 읽기 성능이 좋은 데이터베이스를 사용함 -> 커맨드(rds[writer,reader])에 대한 처리가 일어나면 -> reader 의 싱크를 맞춤
    • 카프카 CDC 로 싱크 맞추기 -> DB 변경 사항을 이벤트로 발행 -> 수신하는 곳에서 처리 또는 db 처리
    • 읽기 성능 좋은 디비는 -> 메모리 디비 (redis 같은 디비)
  • 데이터베이스 규모 확장: 샤딩, 사본 데이터베이스 서버? 샤딩은 애플리케이션 레벨에서 구현?
  • 캐시를 언제 사용하면 좋을까?
    • 빠른 응답 속도가 필요할 때
    • DB 의 자원은 한정적이므로 요청을 적게 하는게 중요 -> 항상 같은 응답을 주는 경우 -> DB 로 조회하기 전에 캐시를 사용해서 응답을 주는 방식
    • 잘 안바뀌는 정보에 대해서 많은 사용자가 요청할 때
  • 캐시를 사용했을 때 좋은 결론으로 내려지기 쉽지 않은 이유
  • 쿼드트리에서 최소 개수를 보장하도록 미리 인접 노드의 목록을 가져와서 계산해두면 응답 시간이 더 빨라지지 않을까? 마찬가지로 지오해시에서 인접 노드의 목록을 미리 합쳐두면 되지 않을까? 이렇게 하지 않는 이유는 구축시간+메모리와의 트레이드 오프 때문인지 구축 시간과 응답 시간 사이의 트레이드 오프에서 구축 시간이 더 중요한 경우가 있을지
    • 요청이 오지 않는 경우에 불필요한 목록일 수도 있음
    • 예견된 상황에 요청이 많을 수 있을 때 미리 만들어두면 좋음
    • 또 하나의 요구사항과 기능구현일수도 있어보임
  • p36 daily로 캐시 업데이트를 진행하는데, 캐시에 없는 사업장 정보를 조회하는 경우가 존재하는지 캐싱된 데이터를 언제 어떠한 기준으로 새로고침 할지?
    • daily 로 캐시를 업데이트 한 이후 -> 사업자 정보가 추가/변경/삭제된 경우 -> 캐시 새로고침을 하도록 기능구현하면 해결됨(evict)
  • geospatial_index 테이블은 지오해시 + businesses_id 복합 PK를 가지고 Redis는 지오해시(key) : businesses_ids(values) 배열을 값으로 가지면 저장 형태가 다르기 때문에 데이터 베이스 값과 Redis에 저장된 값에 차이가 있을 것 같은데 이 둘의 차이를 어떻게 해결할 수 있을지?
    • 레디스에서 지오해시_% 검색하면 해결될 수 있을 것 같음
  • best practice중 하나로 지오해시에 대응되는 사업장 목록을 요청 받으면 일단 캐시를 먼저 조회한다는 내용을 보고 생각 실생활에서 네이버 지도를 이용, 종로나 강남 등의 밀집 구역에서 검색할 때 (술집이나 음식점 등의 키워드로 가정) 매번 검색 결과가 조금씩 달라질 때가 있다. 해당 키워드를 가진 수많은 사업장이 존재할 때, 목록을 캐싱해둔다고 하면 어떠한 데이터를 기준으로 캐싱을 할 수 있을지?
    • 목록을 캐싱해둔다고 했을 때 조회수순, 검색어순, 리뷰숫자순, 가까운 거리순
    • 네이버 지도에 검색하면 해당 검색어에 대해서 광고가 있다고 하면 광고 순위 순으로 목록이 반환될 수 있음
    • 특정 키워드로 검색했을 때 상단에는 입찰 -> 입찰가가 높은게 위
    • 단순 검색일 경우 -> 조회한 키워드가 아니라 가중치를 두고 의도한 데이터를 목록의 상위로 올림
  • 사업장 서비스에서 생성 및 사용되는 데이터와 LBS에서 사용하는 데이터를 동일하게 사용할까? master와 replica, CQRS 패턴으로 command 와 query를 구분하여 데이터 생성과 소비의 사이클을 분리할 수도 있을 수도 있지만, 소비 하는 쪽에서 온전하게 동일한 데이터를 사용하는게 아니라면 중간에 가공하는 서비스를 하나 두고, 준 실시간으로 싱크를 맞추어야 하는 것도 아니니, 매일 새벽에 ETL 작업으로 조회 검색용 데이터를 만들어서 사용하는 것은 어떠한가 조회용 DB로 NoSQL이나 별도의 미들웨어로 엘라스틱 서치를 사용하는 것은 어떠한가?
    • 문제에서는 하루에 한번 사업장 정보가 수정된다 -> 새벽에 ETL 을 통해서 다른 DB 를 사용하는 것도 좋은 방법 -> ETL 이 하나의 일 / NoSql, 엘라스틱 서치는 돈
  • 실제 위치 기반 사용
    • S2 를 실제로 사용하고 있음, 특정 지역에 해시값을 부여해서 처리, DB ES 를 사용하고 있음 -> RDB 로 대체를 못하는 영역 -> RDB 를 굳이 써야한다면 postgresDB 에 플러그인을 붙여서 사용함
  • ES 의 성능
    • ES 의 읽기 성능이 좋음
    • 사용자 정보를 기준으로 ES 에 대해서 위치 정보를 조회할 때
      • 성능이 안나올 때 -> 튜닝
    • ES 의 응답이 너무 많을 때
      • ES 에 필요한 정보만 응답하게끔 한다. / gzip 이나 그런 것도 cpu 자원을 소모함 -> ES 를 쓰는 이유가 강력한 검색 필터링
    • ES 에 요청이 너무 많을 때
      • ES 샤드를 나눈다거나 튜닝
  • rdb 로 기준으로 위치기반 서비스 조회할 때
    • geohash 값을 key 값으로 검색