가상 면접 사례로 배우는 대규모 시스템 설계 기초 2권의 1장, 근접성 서비스 관련 내용에서 다음과 같은 설명을 보았습니다.
지오해시 테이블은 샤딩이 까다로우므로, 면접 시에 이야기하지 않는 것이 좋다. 샤딩 로직을 애플리케이션 계층에 구현해야 하기 때문이다.
??? 사실 잘 이해가 되지 않아요.. 지오해시 테이블은 왜 샤딩이 까다로운지, 샤딩 로직을 애플리케이션 계층에 구현해야 한다는 것이 무슨 소린지. 아 애초에, 사실 샤딩 자체를 제대로 이해하고 있지 못한 것을 깨달았습니다.
샤딩에 대한 이해로부터, 일반적인 샤딩이란 어떤건지, 그래서 왜 지오해시 테이블은 샤딩이 까다로운 건지 이해해보고 싶어졌습니다.
내가 아는 샤딩이란?
이곳저곳에서 주워 들어 이해한 바로는, 여러 데이터베이스 서버에 같은 스키마 구조를 가진, 즉 같은 테이블에 데이터를 분할해서 저장하는 방식입니다. Horizontal Partitioning 방식이라고 이해할 수 있는데, 단순히 테이블을 쪼개어 같은 데이터베이스에 저장하는 방식보다 더 나아간 방식이라고 볼 수 있을 것 같아요.
당연히 장/단점이 존재할텐데, 우선 가장 큰 장점은 트래픽을 병렬적으로 처리할 수 있다는 점일 것 같습니다. 물론 데이터베이스가 한개더라도, 애초부터 성능이 짱짱한 서버를 활용하거나 스케일업을 한다면 문제가 없을 수도 있죠.
하지만, 스케일 업은 규모 확장성에 좋은 방법이 아닙니다. 데이터가 이미 저장되어 있는 서버의 리소스를 물리적으로 확장한다는 것은 어려운 일이고, 하드웨어의 수직적 확장에는 한계가 존재합니다.
그렇기에 병렬적인 확장, 스케일-아웃이 중요해지는데, 그 때 적절히 활용될 수 있는 것이 샤딩인 것이죠.
여기서 잠깐, 레플리케이션 방식이랑은 어떤 점이 다르고, 언제 어떤 방식을 활용해야 하는걸까?
레플리케이션 방식이란 데이터베이스의 복제본을 활용하는 방식입니다. 즉, 원본 데이터 베이스 외에도 다른 데이터베이스를 추가로 복제해두고 최신화 하는 방식인 것이죠.
이런 방식을 통해, 주(Master)로 활용하던 데이터베이스가 다운되었을 때 서브(Slave)로 활용하던 데이터베이스 중 하나를 주 데이터베이스로 승격하여 높은 가용성을 확보할 수 있는 것이죠.
더 나아가, 단순히 Master 를 대체하기 위한 용도로 대기시키는게 아니라, 읽기 연산의 트래픽을 분담합니다. 일반적으로 쓰기 연산은 주 데이터베이스에만 가능하게 하고, 이를 이후에 서브 데이터베이스들에 복제하는 방식을 활용하는 것 같습니다. 이는 전략에 따라 다르며, 여러 데이터베이스에 쓰기 연산이 가능한 전략도 존재합니다. 그러나 만약 마스터 데이터 베이스가 여러개거나, 서브 데이터베이스들도 쓰기 연산이 가능하다면 동시성 문제가 발생할 수 있으니 이를 조심히 다뤄야 할 수 있을 것 같습니다. 더 다양한 전략이 궁금하다면 이 포스트를 참고하면 좋을 것 같습니다.
결론 부터 말하자면, 샤딩과 레플리케이션은 용도가 다르고, 같이 활용될 수 있기 때문에 어떤걸 활용할지 비교하는 것 자체가 잘못된 것 같습니다. (Mutual Exclusive 한게 아닙니다)
즉, 샤딩을 통해 데이터베이스를 분리하고, 이 분리된 데이터베이스들의 그룹의 레플리케이션을 만드는 것이 가능하다는 것입니다. 애초에 각각이 가지는 장점이 명확하며 다르기 때문에 이를 같이 활용하는 방법을 고려해 볼 수 있는 것이죠.
우선, 레플리케이션은 높은 가용성 (high availability), 장애 복구 능력 (disaster recovery), 읽기 연산 성능 향상 과 같은 특징을 갖고 있습니다. 주 데이터베이스가 다운되더라도 서브데이터 베이스를 활용하여 가용성을 확보할 수 있고, 극단적으로 어떤 한 지역에 자연재해가 발생하여 시스템 전체가 다운되더라도, 다른 지역에 있는 레플리케이션이 살아 있어 수월하게 장애를 복구할 수 있을 것입니다. 읽기 연산은 사본 데이터베이스를 활용한 트래픽 분산으로 설명될 수 있죠.
샤딩은 주로 large-scale 시스템에 적용됩니다. 단일 서버로 동작하는 전통적인 데이터베이스의 한계를 극복하고 데이터베이스를 수평적으로 확정하여 병렬 처리를 통한 전체적인 성능 향상을 기대할 수 있죠. 단일 데이터베이스에 몰리던 커넥션 수를 분산시켜 전체적인 처리량의 성능 향상을 기대할 수 있습니다. 레플리케이션과 달리, 쓰기 연산의 성능 향상 또한 크게 증가하겠죠.
한 줄로 다시 정리하면, 데이터베이스 레플리케이션은 데이터 중복성 (data redundancy), 고가용성 (high availability) 및 워크로드 분산에 초점을 맞추는 반면, 데이터베이스 샤딩은 데이터를 분할하여 수평적 확장성과 성능 최적화에 초점을 맞춘다고 볼 수 있습니다.
또한, 레플리케이션을 활용하여 읽기 연산의 성능을 향상 시킨다고 하더라도, 데이터 양이 어마어마하게 많아진다면 한계가 존재 합니다. 쓰기 연산이 많다면 그것도 문제죠. 그 때 샤딩을 적용하는 방법을 고려해 볼 수 있을 것 같습니다.
데이터 양이 어마어마하게 많다는건 어느정도를 말하는 걸까?
데이터 양이 많아 질 때 샤딩을 적용합니다. 근데 얼마나 많을 때를 말하는걸까요? 물론 샤딩을 위한 결정에는 데이터의 종류, 읽기 연산 / 쓰기 연산의 빈도, 데이터의 크기, 데이터베이스의 하드웨어 스펙 등 많은 요인이 작용할 것입니다. 그래도, 단일 데이터베이스에 데이터 양이 너무 많다는 것이 어느정도를 의미하는 건지 어림 잡고 싶어졌습니다.
Chat GPT-4 한테 한번 물어봤습니다. 역시나 모호하게 답하길래, 데이터 사이즈를 예시로 설명해 달라고 다시 질문했죠.
Gigabytes (GB): Smaller databases in the range of a few GBs typically don't require sharding. Most modern databases can handle this amount efficiently with proper indexing and optimization.
Terabytes (TB): When databases start to approach the terabyte range (1 TB and beyond), you might begin to experience performance issues if your hardware isn't scaled accordingly, or if the workload requires high transaction rates. It's around this point that many organizations start considering sharding, especially if they expect continued data growth.
Petabytes (PB): At this scale, sharding is almost always necessary. Databases of this size are usually split across multiple systems to manage the data effectively and maintain acceptable performance levels.
위 답변은 대충 감을 잡는 정도로만 활용해야 할 것 같습니다. 앞서 말했듯이, 샤딩을 결정할 때는 다른 다양한 요인이 작용할 수 있기 때문이죠.
엘라스틱 서치 공식 도큐먼트 중 하나에 다음과 같은 설명이 나와 있습니다.
팁: 크기가 아주 큰 샤드는 사용하지 마세요. 클러스터의 장애 복구 기능에 부정적인 영향을 미칠 수 있습니다. 샤드의 크기에 대한 제한은 없지만, 50GB의 샤드 크기는 다양한 사용 사례에 적용되는 한계로 종종 인용됩니다.
https://www.elastic.co/kr/blog/how-many-shards-should-i-have-in-my-elasticsearch-cluster
이번 포스팅에서 다루기엔 이와 관련한 이해가 부족하여, 이 부분을 나중에 한번 공부해서 다뤄보겠습니다. 샤드가 적용되어야하는 상황, 그 크기 등에 대한 이해에 도움이 될 것으로 기대합니다.
그래서 샤딩은 어떻게 적용 하는건데?
이론적으로는 어느정도 이해했습니다. 근데 그래서, 이걸 어떻게 적용해야 하는 걸까요? 내가 진행하는 프로젝트에 샤드를 적용해야 할 것 같다, 하면 뭐부터 시작해야 할까요?
어플리케이션 로직과 함께 직접 적용하기
일단, 단순무식하게 생각해 보면 어플리케이션 로직에서 이를 구현할 수 있을 것 같아 보입니다. 여러대의 DBMS 노드를 준비해 두고, 데이터를 처리하기 전 엔티티의 id 값 등으로 샤드 키를 생성하여 이를 적절한 노드로 분산시키는 방식이죠.
실제로, 우아한 기술 블로그에서 DB 분산처리를 위한 sharding 을 주제로 이와 같이 어플리케이션 로직으로 분리하는 구현 방식을 소개하였는데, 꼭 한번 참고해 보시기 바랍니다. (기술 블로그 최고)
하지만 이런 방식은 어플리케이션 로직을 직접 구현한다는 점 외에도, 데이터가 늘어남에 따라 샤딩을 추가 하는 등 DBMS 노드도 직접 관리해 주어야 하고, 데이터가 불균형하게 쌓일 경우 재정렬해주는 등 많은 부담이 존재할 것 같습니다.
클라우드 서비스 활용하기
샤딩을 적용할 수 있게 도와주는 관리형 데이터베이스 서비스는 다양하게 존재합니다. AWS 를 적절히 활용해서 샤딩을 수월하게 적용할 수 있겠죠.
다만, 여기서 제가 가지고 있던 오해를 바로잡아야 할 것 같습니다. 이 포스팅을 작성하기 시작할 당시에, "샤딩 로직을 애플리케이션 계층에 구현해야 하기 때문에 지오해시 테이블은 샤딩을 적용하기 까다롭다" 라는 문장을 보고, 아 그렇다면 샤딩 로직을 애플리케이션 계층에 구현하지 않는 방법, 즉 클라우드 서비스 등에서 알아서 해주는 방법이 있나보네? 하고 생각했었습니다. 하지만, 이 포스트 작성을 위해 샤딩에 대하여 공부해보니 이는 사실이 아니었습니다. 그런 마법같은 일은 없으며, 결국 개발자가 직접 샤딩키나 매핑 테이블을 활용하며 application tier 에서 로직을 구현하고 관련한 환경설정이나 인프라 작업을 진행해야 하죠.
클라우드 서비스는 이를 편하게 적용할 수 있게 도와주는 것입니다. 예를 들어, 레플리카를 쉽게 만들어주고, 미그레이션에 도움을 주고, 마스터 노드로 승격시켜 주는 등에 도움이 있을 것 같습니다. Sharding with Amazon Relational Database Service 를 한번 참고해 보시기 바랍니다.
Mapping 테이블과 라우팅 로직이 어플리케이션 계층에 필요하다는 것은 알았지만, 아직 구현이 머릿속에 그려지진 않습니다. 아무래도 가장 좋은 방법은 이와 관련한 실습을 진행해 보는 것 같으니, 추후에 관련한 실습 후 포스팅을 작성해 보겠습니다.
다시 처음 의문으로 돌아가서, 왜 지오해시 테이블은 샤딩이 까다로운걸까?
결국 이 문제는 샤딩키에 대한 특성과 관련된 것이지, 애플리케이션 로직과 관련된 문제가 아니었습니다. 단순히, 지오해시 값이 왜 샤딩키로 적절하지 않은지 고민하면 되는 문제인 것이죠.
그렇다면, 지오해시 값은 왜 샤딩키로 적절하지 않을까요?
우선 불균등한 데이터 분포를 떠올릴 수 있습니다. 특정 지오해시값에 해당하는 지역은 바다나 사막과 같이 관련된 데이터가 쌓일 가능성이 낮은 반면, 뉴욕과 같이 대도시는 무수히 많은 데이터가 쌓일 가능성이 높습니다. 이렇게 되면, 각 샤드에 저장되는 값이 불균등해 질 가능성이 높아지죠.
유사한 문제로 핫스팟 문제를 떠올릴 수 있는데요, 지오해시는 본질적으로 지역 위치에 기반에 값이기 때문에 특정 지오해시 관련한 트래픽이 쏠리거나 데이터 집약적인 작업을 수행하면 핫스팟 문제가 발생할 수 있습니다. 예를들어, 뉴욕과 같은 대도시의 지오해시 값이 저장된 특정한 샤드에 많은 요청이 몰려서 문제가 발생할 수 있는 것이죠.
그 외에도 경계값 문제, 확장성 이슈, 쿼리 퍼포먼스 측면에 여러가지 문제를 고민해 볼 수도 있을 것 같습니다. 다만, 이는 크게 중요한 것 같지 않아 생략하겠습니다.
마지막으로, 저자는 샤딩이 유일한 선택지일 수도 있다고 말합니다. 그런 경우 관리 비용은 증가하겠지만, 디렉터리 샤딩과 같은 방법을 고민해 볼 수도 있겠죠.
하지만, 이번 사례에서 활용되는 지오해시 값은 가짓수가 적고 용량이 크지 않습니다. 한 대의 서버에 충분히 담을 수 있어, 여러 서버로 샤딩할 기술적 필요성이 없는 것이죠. 따라서 단순히 읽기 부하를 나눌 사본 데이터베이스 서버를 두는 방법이 개발도 쉽고 관리도 간편할 것입니다. 이런 이유에서 저자는 지리 정보 색인 테이블의 규모를 확장할 때는 샤딩이 아닌, 사본 데이터베이스 활용을 추천합니다.
참고 문헌
[1] Learn When to Use Database Replica and Database Sharding for Systems Design: https://javachallengers.com/database-replica-and-sharding/
[2] Is sharding not as popular or more difficult with Relational/SQL databases? (Quora): https://www.quora.com/Is-sharding-not-as-popular-or-more-difficult-with-Relational-SQL-databases
[3] What is database sharding? (AWS): https://aws.amazon.com/what-is/database-sharding/?nc1=h_ls
[4] DB분산처리를 위한 sharding (우아한 기술 블로그): https://techblog.woowahan.com/2687/
[5] Sharding with Amazon Relational Database Service (AWS) https://aws.amazon.com/ko/blogs/database/sharding-with-amazon-relational-database-service/
[6] Shard Split using replica on AWS RDS - https://debrajmaity.medium.com/shard-split-using-replica-on-aws-rds-d7565cfcd436
'시스템 디자인' 카테고리의 다른 글
내가 만든 게시판 서비스의 사이트 접속 속도가 사용자가 늘면서 점점 느려진다. 어떻게 해야할까? (0) | 2024.04.24 |
---|