대규모 데이터 처리에 대한 내 생각
최근에 취업을 준비하며 여러 채용 공고를 확인해 보면 많은 회사들이 대용량 트래픽이나 데이터를 처리해 본 경험이 있는 사람들을 우대하고 있다.
내가 근사한 서비스를 만들어서 많은 사람들이 사용하거나, 서비스 기업에 취업하지 않고서는 그러한 경험을 한다는 게 쉽지 않은 부분이다.
직접 경험해보지는 못하지만 다른 사람들의 경험을 간접적으로나마 느껴보고 공부해보면 그나마 괜찮지 않을까 생각이 든다.
대규모 데이터를 어떻게 처리해야 될지를 고민하기에 앞서 대규모가 어느 정도인지를 파악해야 한다.
조금 부끄러운 얘기지만 이번에 수료한 부트캠프를 다니기 전까지 대규모 데이터라고 하면 수 GB ~ 수십 GB 정도 될 줄 알았다. 물론 잘 모르는 내 입장에서는 저 정도 크기의 데이터도 되게 커 보였다.
하지만 대규모 데이터라 하면은 최소 수백 GB에서 테라 바이트까지 한다고 한다.
아마도 이런 대규모에 대한 감이 없다 보니 회사에서도 우대사항으로 대규모에 따른 대응 능력을 원하는 것 같았다.
"대규모 서비스를 지탱하는 기술" 책을 보면 소량의 데이터 처리와 대규모 데이터 처리에 대한 차이를 알려준다.
내가 개인적으로 하는 프로젝트는 소량의 데이터 규모이기 때문에 쿼리를 던지면 즉각적으로 응답을 하게 된다.
하지만 테이블 수가 수천만 건 단위 혹은 데이터 크기가 수 GB에서 수백 GB까지 되면 개발자가 아무 생각 없이 쿼리를 던지면 응답을 하지 않는다고 한다.
이것만 보더라도 왜 대규모 데이터 처리가 중요하고, 기업들이 원하는지 알 것 같다. 내가 직접 경험해 볼 수 없다면 다른 사람의 경험이 녹아있는 책을 통해서 간접 경험이라도 해보자.
앞으로 정리할 내용은 "대용량 서비스를 지탱하는 기술"이라는 책을 읽고 정리한 내용이다.
책 자체는 나온 지 오래돼서 중간중간 옛날 기술에 관해서 나오지만 대용량 데이터를 처리한다는 전체적인 개념은 크게 다르지 않을 거라고 생각해서 정리를 해봤다.
대규모 데이터 처리가 어려운 이유
앞서 설명했던 대로 데이터의 규모가 클 경우에는 아무 생각 없이 쿼리를 던지면 응답하지 않는다고 하였다.
예를 들어 SELECT member_name FROM MEMBER라는 쿼리를 던진다고 생각해 보면 개인 프로젝트 같은 데이터의 규모가 작은 경우에는 빠르게 응답하겠지만 규모가 큰 경우에는 아무 응답을 하지 않는다는 것이다.
그렇다면 같은 쿼리를 던졌는데도 대규모 데이터에서 처리하기 어려운 2가지 이유를 알아보자.
1. 메모리 내에서 계산할 수 없다.
메모리에 올리지 않으면 기본적으로 디스크를 계속 읽어가면서 검색하게 되어 원하는 데이터를 좀처럼 발견할 수 없는 상태가 된다. 여기서 문제가 되는 점은 바로 디스크를 읽고 있다는 점이다.
데이터가 어느 정도 규모를 갖추게 되면 메모리 내에서 계산할 수 없게 되므로 디스크에서 특정 데이터를 검색하게 된다. 그리고 디스크는 메모리에 비해 상당히 느리기 때문에 데이터를 I/O 하는데 시간이 오래 소요된다.
2. 디스크(보조 기억장치)가 느리다.
메모리는 전기적인 부품이지만 디스크는 물리적인 부품이다.
메모리상에 데이터가 있다면 탐색할 때 물리적인 동작 없이 실제 데이터 탐색 시의 오버헤드가 거의 없으므로 빠르다.
디스크는 헤드의 이동과 원반의 회전과 같은 물리적인 동작을 수반하기 때문에 데이터 탐색 시 느리다.
어떻게 대규모 데이터를 처리할 수 있을까
앞에서 대규모 데이터를 처리하기 어려운 이유를 알아보았다. 그렇다면 어떻게 해야 대규모 데이터를 처리할 수 있을지 알아보자.
1. 단일 호스트의 성능 끌어내기
대규모 데이터를 처리하기 위해서 적용할 수 있는 방안은 여러 가지가 있다. 예를 들어 서버를 여러 대로 확장하여 대규모 데이터를 처리할 수 있겠지만 무심코 적용했다가는 오히려 안 하느니만 못한 경우가 생길 수 있다.
무심코 특정 방법을 적용하는 것은 아마도 어떠한 문제일 것이라는 추측을 했기 때문이다. 책에서 오래된 개발자 격언이라고 소개해주는 글이 있다.
추측하지 말고 계측해라
서버를 확장하거나 메모리를 늘리는 것은 단순하면서도 쉬운 해결 방법이 될 수도 있겠지만 그보다 앞서서 어떻게 하면 서버의 리소스를 최대한 사용할 수 있을지 파악해야 한다.
위의 말처럼 리소스를 얼마나 사용하는지 파악하려면 추측이 아닌 실제로 계측을 해보며 명확한 데이터를 가지고 판단을 해야 개발자가 어떤 해결 방법을 적용할 수 있을지 판단할 수 있을 것이다.
2. 병목 규명 작업
시스템 전체의 부하 상황을 확인하여 어디서 부하가 발생하는지 확인해 보자.
3. 부하가 걸리는 원인 파악
부하가 걸린다는 것은 보통 CPU나 I/O에서 발생하게 된다.
- CPU에서 부하가 발생하는 상황
CPU에 부하가 발생하는 상황은 2가지가 있다.
첫 번째로 디스크나 메모리 용량 등 그 밖의 부분에서는 병목이 되지 않아서 이상적인 상태인데 부하가 발생한다면 시스템의 전송량에 문제가 있는지 확인해야 한다.
두 번째로 프로그램이 어떠한 문제로 인해 폭주하게 되어 CPU에 필요 이상의 부하가 걸리는 상황이 있다.
CPU에서 부하가 발생하는 상황을 생각했다면 그다음으로는 직접 확인해 보며 부하를 조사해야 한다.
리눅스에서 top이나 sar 명령어를 통해 사용자 프로그램의 처리가 병목인지, 시스템 프로그램이 원인인지 파악해야 한다.
ps 명령어를 사용하여 프로세스의 상태나 CPU 이용시간 등을 보면서 원인이 되고 있는 프로세스를 조사한다.
문제가 되는 프로세스를 확인했으면 보다 상세하게 조사하기 위해 strace로 추적하여 병목 지점을 좁혀나간다.
CPU 부하를 해결하는 방법
CPU 부하를 해결하는 방법으로는 가장 간단하게 서버를 증설하는 것이다. CPU 부하는 I/O 부하와는 다르게 서버 증설이 간단하게 할 수 있다.
하지만 서버 증설을 못하는 경우가 있을 수 있는데 이럴 때는 프로그램 로직을 개선하거나 알고리즘을 개선하는 방법이 있다.
마지막으로 문제가 되는 오류를 제거하여 부하를 줄일 수 있다.
- I/O에서 부하가 발생할 시
I/O에서 부하가 발생하는 상황은 클라이언트로부터 I/O 요청이 너무 많거나 스왑이 발생하여 디스크 액세스가 발생하는 상황이 있다.
스왑(Swap)이란?
스왑(Swap)은 실제 메모리 보다 더 많은 리소스를 필요로 할 경우 디스크 공간을 일부 이용하여 부족한 메모리를 대체할 수 있는 공간을 의미한다.
스왑을 사용해서 더 많은 요청을 받을 수 있지만 하나의 디스크를 사용하는 것이지 스왑 했다고 디스크가 메모리가 되는 것은 아니기 때문에 속도는 떨어질 수밖에 없다.
스왑이 발생하고 있을 경우
스왑이 발생했다는 것은 메모리 용량보다 더 많은 자원을 소비하고 있다는 뜻이므로 ps 명령어를 통해서 어떤 프로세스에 문제가 있는지 확인해야 한다.
만약 프로그램의 오류로 인하여 메모리를 지나치게 많이 사용하고 있다면 프로그램 로직을 개선한다.
만약 별 다른 문제가 식별되지 않을 시 메모리를 증설하여 더 많은 요청을 받을 수 있게 해 주고, 메모리를 증설할 수 없는 상황이면 부하 분산을 검토하여 대응한다.
스왑이 발생하지 않고 디스크로 입출력이 빈번하게 발생하고 있는 경우
스왑이 발생하지 않고 디스크로 I/O 부하가 발생하고 있는 경우라면 캐시 메모리가 부족한 경우로 어떻게 하면 캐시 영역을 확대할 수 있을지 고민해야 한다.
프로그램 로직을 개선해서 I/O 빈도수를 먼저 개선해 보고 같은 문제가 반복될 시 메모리를 증설하여 캐시 영역을 확대시킨다.
하지만 메모리를 증설할 수 없는 상황이 발생했을 때는 데이터를 분산시키거나 캐시 서브를 도입해서 대응해야 한다.
4. OS 튜닝
대규모 데이터를 처리하기 위해서 OS 튜닝을 고려하는 것도 하나의 방법이다.
튜닝이라고 해서 기존의 성능을 몇 배씩 늘릴 수 있다고 착각할 수 있는데, 튜닝의 본래 의미는 하드웨어나 소프트웨어가 본래 지니고 있는 성능을 충분히 발휘할 수 있도록 문제가 될 만한 부분이 있다면 제거해 주는 것이다.
예를 들어 CPU를 최대한 사용해서 10초 걸리는 처리 성능을 아무리 OS 설정을 만져도 10초 이하로 줄어들지 않는다. 하지만 부하가 발생하여 처리 작업이 100초가 소요된다고 하면 충분히 OS 튜닝을 해서 개선할 수 있다.
규모 조정과 확장성
대규모 데이터를 처리하는 방법으로는 규모를 조정하는 방법도 있다.
규모를 조정하는 방법으로는 고가의 빠른 하드웨어를 사서 성능을 높이는 sacle-up 전략과 저가이면서 일반적인 성능의 하드웨어를 많이 나열해서 시스템 전체 성능을 올리는 scale-out 전략이 있다.
스케일 아웃
스케일 아웃 전략은 웹 서비스에 적합한 형태이고 비용이 저렴하다는 점과 시스템 구성에 유연성이 있다는 점이 포인트다.
스케일 아웃이 스케일 업 전략보다 선호되는 이유는 고가의 하드웨어 장비를 사용한다 해서 그것이 무조건 성능과 비례하지 않다는 것이다.
동일한 성능을 확보하기 위해서는 저가의 하드웨어를 나열해서 확보하는 편이 더 낫다는 것이다.
시스템 구성의 유연성이라는 것은 부하가 적을 때는 최소한으로 투자하고 부하가 높아짐에 따라 확장해 가기 쉽고 상당한 용도의 서버도 저렴하고 간단하게 준비할 수 있다는 것으로 여러모로 빠르게 상황 대처가 쉽다.
규모 조정의 요소
스케일 아웃 전략은 하드웨어를 횡으로 전개해서 확장성을 확보해 가게 된다. 이를 통해서 CPU 부하의 확장성을 확보하기 쉽다.
반면에 DB 서버 측면에서는 I/O 부하가 걸리게 된다.
DB는 대규모 환경에서 I/O 부하를 부담하고 있어 애초에 분산시키기 어려운 데다가 디스크 I/O가 많이 발생하면 서버가 금세 느려지는 본질적인 문제가 있다.
대규모 데이터를 처리하기 위해서 어떻게 프로그램을 개발해야 될까
최대한 메모리에서 처리를 마칠 수 있게 하기
디스크의 seek 횟수가 확장성, 성능에 크게 영향을 주기 때문에 seek 횟수를 최소화한다는 의미로 메모리를 활용해야 한다.
데이터양 증가에 강한 알고리즘 사용하기
알고리즘의 기초적인 부분을 제대로 활용하여 엄청난 계산 량을 몇 번의 계산 량으로 개선한다.
데이터 압축이나 검색 기술과 같은 테크닉을 활용하기
압축해서 데이터량을 줄일 수 있다면 읽어내는 seek 횟수도 적어지게 되므로 디스크 읽는 횟수를 최소화할 수 있다. 또한 메모리에 캐싱하기 쉬워진다.
참고 자료
'CS > 데이터베이스' 카테고리의 다른 글
데이터베이스 - 고립화 수준과 이상 현상 (1) | 2024.08.05 |
---|---|
데이터베이스 - 동시성 제어 (0) | 2024.08.05 |
데이터베이스 - 트랜잭션 (0) | 2024.08.04 |
데이터베이스 - ERD (0) | 2024.08.01 |
데이터베이스 - Key (0) | 2024.08.01 |