기본 콘텐츠로 건너뛰기

책에서는 안 알려주는 대규모 트래픽을 위한 설계





대규모 트래픽을 커버하는 첫 페이지 만드는 법.. 

보통 DB를 연결할 때 대규모 설계는 어떻게 하시나요? 
잘 만들었다는 전제 하에 동접 3000명 이하는 
어떤 DBMS를 사용해도 문제 없이 돌아갑니다. 
여기서 이미 터졌다면 이 콘텐츠를 보기 전에 DB의 기초부터 보셔야 합니다. 
아.. 개발 코드가 터졌다구요? 그럼 개발자를 때리셔야지요.. 

만약 3000명을 넘겼다면?

이제 Write/Read를 분리해서 
1 CRUD + n개의 READ Replica를 만들겠죠? 
보통 Read Replica는 5개가 최대라고 보시면 됩니다. 
누가 연구한 자료가 있었는데... 
6번째 레플리카를 만든느 순간 마스터가 되는 서버의 효율 저하 때문에 
5번째에서 6번쨰로 올릴때의 성능이 급격히 줄어든다는 연구 결과가 있습니다. 
때문에 Azure에서도 replica설정할 때 5대까지 밖에 설정 못하게 되어 있지요. 

유저의 행동 패턴에 따라 다르긴 하지만, 
1 CRUD + 5 Read Replica의 경우 동접 15000명 정도는 커버 합니다. 

즉, 동접 15000명 에서 다시 터져서 저를 부르는 경우가 많지요.. 

이 때부터는 
회원 DB, 게시판DB, 서비스DB, 과금 DB 등등 으로 성격, 서로의 연관도에 따라 나누기 시작합니다. 
물리적으로 DB가 나눠지면 Join을 못하거나 Linked Table또는 LinkDB등의 연결자를 이용해서 JOIN이 되기도 합니다. 
그에 따라 성능 차이가 생기지만 가장 중요한 포인트는 
서로 다른 물리적 테이블의 JOIN은 인덱스를 타지 않는다! 
라는 것입니다. 즉, JOIN할 테이블들을 최소한으로 만든 뒤에 JOIN을 걸지 않으면 NoSQL처럼 느려터져 죽습니다. 
양이 많은 DB에서 양이 적은 테이블을 가져와서 JOIN을 해야겠지요.. 

이렇게 해서 동접 10만명까지 커버를 했다 칩시다. 
여기서 일반적인 동접의 기준도 서비스마다 다릅니다. 
웹 서비스는 20분 이내에 한 번이라도 클릭한 유저를 동접에 카운트 하지만, 
온라인 게임등은 소켓을 열어놓고 있기 때문에 
순간 동접을 그자리에서 카운트 합니다. 
그리고 서비스에 따라 다르지만 보통 100만 액티브 유저가 있으면 최대 동접은 10만인 경우가 많습니다. 

자, 동접 10만이 넘어가서 위태위태 합니다. 
그 다음부터는 어떻게 해야 유저를 커버할 수 있을까요? 

바로 가장 많이 몰리는 탑 페이지를 분산시켜야지요.. 

탑 페이지가 분산되더라도 결국 DB는 똑같이 읽지 않느냐? 
하시겠죠?

맞습니다. 분산이 아니라 여기서 부터는 캐싱을 해야 합니다. 

앞쪽에 CDN 사이트 캐시나 역 프록시를 이용하는 등의 캐싱하는 방법도 있지만, 
전통 적인 방법이 가장 강력합니다. 

탑 페이지에서 모든 유저에게 공통적인 게시판, 이벤트 등등의 데이터는 백그라운드에서 1분 마다 HTML화 시키고, 
계정 별 변경되는 정보만 DB화를 해서 가져오면, 
이미 위의 최적화 위에 이걸 하게 되므로, 동접 약 100만 까지는 커버 할 수 있습니다. 
즉 유저가 직접 바라보는 것은 단순화된 HTML이지 DB는 최소한의 정보만 바라보게 되거든요.. 

그럼 100만이 넘으면?

여기서 부터 Sharding이 필요한데요.. 
이건 제가 한 것이 아니고 카카오팀이 애니팡 2000만명 커버할 때 사용했던 방법인데 듣고서 감탄했습니다. 
그 동안 제대로 된 샤딩만을 생각했는데, 
제대로 샤딩 알고리즘으로 최적화를 하게 되면, 비용과 알고리즘에 따른 복잡성 때문에 오히려 인프라 관리가 어려워 지는데, 

게임 서비스의 특성상 빠른 유저 이탈 등에 맞추어 샤딩을 아주 단순화를 시켰더라구요.. 
그냥 서버 한대에 모든 기능을 때려 넣고 유저를 3만명으로 맞춥니다. 유저 3만명은 한 대에 들어갈 최대 동접 3천명일 때의 이야기 입니다. 서비스에 따라 맞추셔야지요.. 
그리고 그 서버 자체를 늘리고 유저번호는 30001~60000까지는 서버 2, .. 이렇게 3만명씩 잘라 넣습니다.  
그렇게 단순화를 하고 나니 요즘같은 클라우드 시대에는 차라리 작은 스펙의 VM을 수평적으로 확장하고 데이터를 샤딩한 다음에 서비스가 길어지면서 유저가 빠져나가는 패턴을 보고 통합을 하는 방식을 쓰면 
최고의 효율은 아니지만 가성비가 뛰어난 설계에서 개발, 운영이 편리한 샤딩이 되더라구요.
서로 다른 서버간의 유저의 소통은 중계 서버를 만들어서 그 중계서버가 중계를 하지요.. 
물론 샤딩 기법은 서비스의 특성마다 다르지만.. 단순화가 최고란 이야기를 하는 것입니다. 

그 이후부터는 저도 샤딩의 고정관념을 벗어나서 
이 방식을 개량한 단순샤딩을 많이 쓰고 있습니다. 

원래 샤딩은 엄청나게 쌓이는 로그 같은 데이터를 쪼개서 성능 저하가 생기지 않으면서 대규모 데이터를 처리하도록 만든 것이지만, 역시 너무 고정관념만 가지고는 참신한 아이디어를 이길 수 없다는 것을 알았습니다. 

이 이후는 몇천만 유저가 들어와서 견뎌내는 시스템을 저렴하게 만들 수 있게 되었지요.. 
예전에는 동접에 비례해서 비용이 늘었는데 말입니다. 

그리고, 대규모 처리를 할 때 
굳이 ALB나 ELB를 쓰시는 분이 계십니다. 

Azure의 Front Door나 AWS의 Route 53, BIGIP의 F5 및 CDNetworks에서 사용하는 GLB는 모두 DNS기반의 로드밸런서 입니다. 

DNS기반의 LB와 L4/L7기반의 LB시리즈는 결정적인 차이가 있습니다. 

장비에 서비스용 트래픽이 오느냐 아니면 방향만 가리키고 트래픽은 안받느냐 입니다. 
즉, L4/L7기반의 장비인 ELB, ALB등등은 장비에 트래픽이 오기 때문에 대규모 서비스에는 그 트래픽에 비례한 장비 비용이 발생합니다. 때문에 부하에 따른 가격 상승폭이 크지요.. 

하지만 Route53같은 DNS기반의 부하분산은 서버의 위치만 알려주고 실제 트래픽은 서버의 트래픽으로 직접 가기 때문에 부하분산장치가 저가형 리소스로도 충분해지기 때문에 비용이 적게 발생합니다. 수억회의 리퀘스트에도 단돈 몇 달러로 처리가 되지요. 

제가 한국인의 기업 수십곳에 Route53을 쓰세요 하고 말했는데, 
개발자 들이 한 명도 납득 못하고 그냥 ELB나 ALB를 쓰시더라구요.. 

결정적인 차이는 있습니다. 
Route 53은 세션 관리가 안되기 때문에 별도 세션관리용 서버가 필요합니다. 
하지만 ELB나 ALB역시 세션을 자기서버에서 관리한다면 Sticky가 되기 때문에 부하분산이 원활하게 되지 않지요. 
때문에 결국 Route53에서도 쓰이는 Redis같은 메모리 저장장치가 필요하게 되지요..

ELB를 쓰면 단지 초기에 개발만 편합니다. 

이 단지 초기에 개발만 편하기 때문에 
제가 말한 대규모를 위한 설계에는 콧방귀를 뀌고 알아먹을 생각을 안하지요. 

제가 이건 몇만 정도면 터지겠네요.. 
하고 빠져 나오면.. 

대 부분 그 정도에 터지면서 제게 어떻게 알았냐고 말씀하시는데.. 
그러니까.. 하루이틀 장사 해봤냐구요.. 무슨 무당이 근거 없는 예언한 줄 아시나봐요.. 

이렇게 대규모 처리를 시스템에서 코드까지 봐가면서 해보다보니, 
남들이 못보는 부분이 보일 뿐인데.. 

좀 제 말을 들어주시는 한국분이 많아졌으면 좋겠다 싶은 생각에 제자랑을 또 하게 됬습니다. 


giip :: Control all Robots and Devices! Free inter-RPA orchestration tool! https://giipasp.azurewebsites.net/

댓글

이 블로그의 인기 게시물

Alter table 에서 modify 와 change 의 차이 :: SQL Server

두 개의 차이를 모르는 경우가 많아서 정리합니다.  modify는 필드의 속성값을 바꿀때 사용하구요.. change는 필드명을 바꿀떄 사용합니다.  alter table tbbs modify bNote varchar(2000) NULL; alter table tbbs change bNoteOrg bNoteNew varchar(2000) NULL; change에는 원래 필드와 바꾸고 싶은 필드명을 넣어서 필드명을 바꾸는 것이죠~ 더 많은 SQL Server 팁을 보려면  https://github.com/LowyShin/KnowledgeBase/tree/master/wiki/SQL-Server giip :: Control all Robots and Devices! Free inter-RPA orchestration tool! https://giipasp.azurewebsites.net/

BI의 궁극판! Apache Drill을 써보자!

사실 Apache Drill 은 BI(Business Intelligence)라고 부르는 것 보다는 단순 데이터 연결 엔진이다. https://drill.apache.org/ 하지만 내가 왜 극찬을 하느냐면.. DBA로서 항상 문제가 되어왔던게, 이기종 데이터의 변환이나 처리였다. 포맷을 맞추는데 엄청난 시간이 걸리고, 데이터 임포트 실패가 무수하게 나고.. 한 번 잘못 데이터를 추출하면 다시 조정, 변환, 추출하는데 시간이 많이 걸린다. 그런데! Apache Drill은 그냥 RDB를 CSV랑 연결해서 조인해서 통계를 낼 수 있다. 그것도 표준 SQL을 사용하여! 예를 들어, CSV의 세 번째 컬럼이 price 이고, 물건의 판매이력을 PG사에서 CSV로 출력 받았다. 우리 DB와의 검증을 위해서는 수동으로 Import를 한 뒤에 포맷이 안맞아 잘리는 데이터가 있다면 다시 맞춰주고, 재 임포트를 수십 번, 그리고 나서 겨우 들어간 데이터를 조인하여 빠진 데이터를 분간한다. 숫자가 적다면 개발자가 개발로 처리할 수도 있지만, 건수가 하루에 300만건 짜리라면.. 한 달 온 파일은 9천만 건이다. 프로그램으로 고작 처리하는 것이 초당 500건. 거의 20만초, 에러 없이 약 56시간.. 에러가 생기면 다시 56시간.. ㅠㅡㅠ 이런게 현실이기 때문에 쿼리 말고는 방법이 없다. apache drill 의 진면목을 보자! 이번에는 좀 범용 적인 MySQL DB와 붙여 보자. . 난 이번에는 Mac에서 작업을 했기 때문에 그냥 다운 받아서 풀었음.. https://drill.apache.org/download/ 여기서 자기 OS에 맞는 버전을 받아서 설치하시길.. 압축을 풀고 나면 MySQL 커넥터를 붙여야 한다. https://dev.mysql.com/downloads/connector/j/5.1.html 여기서 다운로드 이런 커넥터 들을 붙일 때마다 콘피그를 수정해 줘야 하지만, 몇 번만...