본문 바로가기
Book

[독서 기록] 웹 개발자를 위한 대규모 서비스를 지탱하는 기술

by Renechoi 2024. 4. 14.
 
대규모 서비스를 지탱하는 기술
대규모 서비스를 개발ㆍ운용하는 기술자를 위한 입문서! 『웹 개발자를 위한 대규모 서비스를 지탱하는 기술』은 저자가 서버 1대부터 시작하여 1,000대의 호스트를 운영하기까지 수없이 많이 겪었던 시행착오와 해결책, 먼 길을 돌고 돌아서 비로소 체득한 대규모 서비스 개발과 운용에 관한 핵심 노하우들을 전한다. OS 및 컴퓨터의 동작원리, DB 분산방법, 실전적인 알고리즘을 시스템에 적용하는 방법, 대규모 데이터를 요리하는 검색엔진의 원리와 구조, 시스템 전체를 조망하기 위한 인프라 설계지식 등을 다양한 샘플 코드와 함께 자세하게 소개하고 있다.
저자
다나카 신지, 이토 나오야
출판
제이펍
출판일
2011.02.28

 

1. 대규모 웹 서비스 개발 오리엔테이션

이 책의 근원이 되는 하테나 서비스의 대략적인 규모

  • 등록 사용자는 100만 명 이상, 1,500만 UU/월
  • 수십 억 섹세스/월
  • 피크 시 회선 트래픽 양은 430Mbps
  • 하드웨어(서버)는 500대 이상

서버 몇 대 정도의 소규모 서비스에는 없는, 대규모 서비스에만 있는 문제나 어려움에는 어떤 점들이 있을까?

  • 확장성 확보, 부하분산 필요
  • 다중성 확보
  • 효율적 운용 필요
  • 개발자 수, 개발방법의 변화
  • 대규모 데이터량에 대한 대처

2. 대규모 데이터 처리 입문

3억 5천만 레코드가 있다. 이 테이블에 갑자기 select * from relword와 같은 쿼리를 실행하면 응답이 반환되지 않는데, 그 이유는 3억 레코드 이상이 존재하기 때문이다.

 

비교적 극단적인 예이지만 그 외에도 레코드 건수가 1,500만이나 5,000만 정도는 된다.

 

데이터 크기로는 entry라는 테이블이 3GB, bookmark라는 테이블이 5.5GB, tag 테이블이 4.8GB, 그리고 HTML 텍스트 데이터도 압축해서 저장하고 있는데, 이것이 200GB를 넘고 있다.

대규모 데이터 처리의 어려운 점

대규모 데이터는 어떤점이 어려운가?

메모리 내에서 계산할 수 없다는 점이다. 메모리 내에서 계산할 수 없다는 점이 어려운 점인 이유는 메모리에 올리지 않으면 기본적으로 디스크를 계속 읽어가면서 검색하게 되어 좀처럼 발견할 수 없는 상태가 되기 때문이다.

 

데이터 건수가 많으면 그만큼 입력 데이터 건수가 늘어나므로 계산량이 많아진다는 점도 당연한 이유지만, 이 점보다도 문제가 되는 것은 '디스크를 읽고 있다'는 점이다.

메모리와 디스크의 속도차

메모리는 10^5~10^6배 이상 고속
-> 10만 ~ 100만 배.

디스크는 왜 늦을까?

메모리는 전기적인 부품이므로 물리적 구조는 탐색속도와 그다지 관계없다.

 

디스크는 동축 상에 '원반'이 쌓여 있다. 이 원반이 회전하고 있고 여기서 데이터를 읽어낸다. 즉 메모리와는 달리 회전 등의 물리적인 동작을 수반하고 있다. 이 물리적인 구조가 탐색 속도에 영향을 준다.

 

디스크에서는 헤등의 이동과 원반의 회전이라는 두 가지 물리적인 이동이 필요하지만, 역시나 오늘날의 기술로도 원반의 회전속도를 빛의 속도까지 근접시킬 수는 없다. 디스크에서는 각각 밀리초 단위, 합해서 수 밀리초나 걸린다. 메모리는 1회 탐색할 때 마이크로초면 되지만, 디스크는 수 밀리초가 걸린다는 것이다.

 

다음으로 데이터가 뿔뿔이 흩어져서 배치되어 있고 이분탐색 등 여기저기에서 찾아야 하는 알고리즘을 사용한다고 하면, 한 바퀴 회전해서 이쪽으로 이동하고 또 한 바퀴 회전해서 저쪽으로, 또다시 회전해서 이쪽으로와 같이 원반을 빙글빙글 돌려야 한다.

 

또한 경우에 따라서는 헤드도움직여야 한다. 결과적으로 상당한 시간이 걸리게 된다. 그러나 데이터가 메모리상에 있다면 탐색할 때 물리적인 동작 없이 실제 데이터 탐색 시의 오버헤드가 거의 없으므로 빠른 것이다.

 

탐색에 사용되는 것이 CPU의 캐시에 올리기 쉬운 알고리즘이나 데이터 구조라면 메모리 내용이 CPU 캐시에 올라가므로 더욱 빨라져 나노처 단위로 처리할 수 있다.

OS 레벨에서의 연구

디스크는 느리지만 OS는 이것을 어느 정도 커버하는 작용을 한다. OS는 연속된 데이터를 같은 위치에 쌓는다. 그리고 나서 데이터를 읽을 때 1 바이트씩 읽는 것이 아니라 4KB 정도를 한꺼번에 읽도록 되어 있다.

 

이렇게 해서 비슷한 데이터를 비슷한 곳에 두어 1번의 디스크 회전으로 읽는 데이터 수를 많게 한다. 그 결과로 디스크의 회전횟수를 최소화할 수 있게 된다. 이러한 작용을 해서 디스크를 가능한 한 회전시키지 않아도 되도록 하고 있다. 그렇지만 결국 회전 1회당 밀리초 단위이므로 역시 메모리와의 속도차를 피할 수 있는 것은 아니다.

전송속도, 버스의 속도차

전송속도 차이도 살펴보자. 메모리나 디스크 모두 CPU와 버스로연결되어 있다. 이 버스의 속도에서도 상당한 차이가 있다. 먼저 '탐색'과 '전송'의 차이에 유의하기 바란다. 앞서 본 것은 메모리 혹은 디스크상에 있는 임의의 데이터를 탐색할 때의 속도차이다.

 

여기서 살펴보고자 하는 것은 전송속도다. 찾은 데이터를 디스크에서 메모리로 보내거나 메모리에서 CPU로 보내는 등 컴퓨터 내부에서 전송하기 위한 속도다. 그 예로, hdparm이라는 Linux 툴을 사용하면 그 속도차를 알 수 있다. 그림에서 'Timing cached reads'는 메모리에 있는 캐시 데이터의 전송속도이므로 실질 메모리 전송속도, 'Timing buffered disk reads'는 디스크의 전송속도로 생각하기 바란다. 대략 100배 정도 차이가 나고 있다.

 

메모리와 CPU는 상당히 빠른 버스로연결되어 있으므로 7.5GB/초 정도 나오지만 디스크는 58MB/초 정도밖에 나오지 않는다.

규모조정의 요소

웹애플리케이션과 부하의 관계

웹 애플리케이션과 부하의 관계를 그림으로 살펴보자. 웹 애플리케이션의 3단 구조에는 프록시, AP 서버, DB가 있다.

AP 서버는 CPU 부하만 걸리므로 분산이 간단하다. 그 이유는 기본적으로 데이터를 분산해서 갖고 있는 것이 아니므로 동일한 호스트가 동일하게 작업을 처리하기만 하면 분산할 수 있다. 따라서 대수를 늘리기만 하면 간단히 확장해 갈 수 있다. 결국 새로운 서버를 추가하고자 한다면 원래 있던 서버와 완전히 동일한 구성을 갖는 서버, 심하게 말하면 복사본을 마런해서 추가하면 된다. 요청을 균등하게 분산하는 것은 로드밸런서(load balancer)라는 장치가 해준다. 이걸로 OK.

 

한편, I/O 부하에는 문제가 있다. DB를 추가한다고 생각해보면 바로 알겠지만 쓰기가 발생했을 때 데이터를 어떻게 동기화할 것인가라는 문제가 생긴다. 그렇다. 쓰기는 간단히 분산할 수가 없다.

DB 확장성 확보의 어려움

CPU 부하의 규모조정은 간단하다

  • 같은 구성의 서버를 늘리고 로드밸런서로 분산

I/O 부하의 규모조정은어렵다

  • DB

대규모 데이터를 다루기 위한 기초지식

대규모 데이터를 다루기 위한 급소

  1. 어떻게 하면 메모리에서 처리를 마칠 수 있을까
  • 디스크 탐색 횟수 최소화하기
  • 국소성을 활용한 분산 실현
  1. 데이터량 증가에 강한 알고리즘, 데이터 구조
  • 예: 선형검색 -> 이분검색
  1. 데이터 압축, 정보검색기술

3. OS 캐시와 분산

OS의 캐시 구조

OS의 캐시 구조를 알고 애플리케이션 작성하기

디스크와 메모리 간 속도차가 10^5~10^6배 이상 난다고 했는데, 원래 OS에는 디스크 내의 데이터에 빠르게 액세스할 수 있도록 하는 구조가 갖춰져 있다. OS는 메모리를 이용해서 디스크 액세스를 줄인다. 원리를 알고 이를 전제로 애플리케이션을 작성하면 OS에 상당부분을 맡길 수 있다.

 

그 원리가 바로 OS 캐시다. Linux의 경우는 페이지 캐시나 파일 캐시, 버퍼 캐시라고 하는 캐시 구조를 갖추고 있다.

 

OS는 가상 메모리 구조를 갖추고 있다. 가상 메모리 구조는 논리적인 선형 어드레스를 물리적인 어드레스로 변환하는 것이다.

가상 메모리 구조

가상 메모리 구조가 존재하는 가장 큰 이유는 물리적인 하드웨어를 OS에서 추상화하기 위해서다.

 

메모리의 실제 주소를 프로그램에서 실제로 사용하지 않고, OS가 비어 있는 곳을 찾고, 메모리가 다른 어드레스를 반환한다.

 

그 이유는 개별 프로세스에서는 메모리의 어느 부분을 사용하는지 관여하지 않고, '반드시 특정 번지부터 시작' 또는 '0x000부터 시작'하는 것으로 정해져있으면 다루기 쉽기 때문이다. 예를 들면 유닉스의 공유 라이브러리는 프로세스 내의 지정된 주소로 할당되도록 되어 있다. 프로세스 내에서 이 특정 어드레스는 예약되어 있다. 이때 만일 시작주소가 각기 다르다면 메모리를 확보해야 할 주소위치를 찾기가 매우 어려울 것이다.

 

여기서의 포인트는 OS라는 것은 메모리를 직접 프로세스로 넘기는 것이 아니라 일단 커널 내에서 메모리를 추상화하고 있다는 점이다.

 

디스크의 경우에도 OS가 모아서 읽어낸다고 했는데, 메모리를 확보할 때에도 그와 마찬가지 방식으로 1바이트씩 액세스하는 것이 아니라 적당히 4KB 정도를 블록으로 확보해서 프로세스에 넘긴다. 여기서 1개의 블록을 '페이지'라고 한다. OS는 프로세스에서 메모리를 요청받으면 페이지를 1개 이상, 필요한 만큼 페이지를 확보해서 프로세스에 넘기는 작업을 수행한다.

Linux의 페이지 캐시 원리

OS는 확보한 페이지를 메모리상에 계속 확보해두는 기능을 갖고 있다.

 

OS는 우선 디스크로부터 4KB 크기의 블록을 읽어낸다. 읽어낸 것은 한 번은 메모리상에 위치시켜야 한다. 왜냐하면 프로세스는 디스크에 직접 액세스할 수 ㅇ벗기 때문이다. 어디까지나 프로세스가 액세스할 수 있는 것은 (가상) 메모리다. 따라서 OS는 그 메모리 주소를 프로세스에 알려준다. 그러면 프로세스가 해당 메모리에 액세스 하게 된다.

 

데이터 읽기를 마친 프로세스가 '이번 디스크 읽기는 끝나고 데이터는 전부 처리했으므로 더 이상 불필요'하게 됐어도 해제하지 않고 남겨둔다. 그렇게 하면 다음에 다른 프로세스가 같은 디스크에 액세스할 때에는 남겨두었던 페이지를 사용할 수 있으므로 디스크를 읽으러 갈 필요가 없게 된다. 이것이 페이지 캐시다.

Linux는 페이지 단위로 디스크를 캐싱한다

예를 들어 디스크상에 4GB 정도의 매우 큰 파일이 있고 메모리가 2GB 밖에 없다고 하자.

 

2GB 중에 500MB 정도를 OS가 프로세스에 할당했다고 하자. 그러면 '이제 1.5GB 정도 여유가 있다고 할 때, 4GB 파일을 캐싱할 수 있을까?'라는 문제가 발생한다.

 

"파일 캐시"라고 생각한다면 파일 1개 단위로 캐싱하고 있다는 이미지를 주므로 4GB는 캐싱할 수 없다고 생각할 수 있지만, 실제로는 그렇지 않다.

 

OS는 읽어낸 블록 단위 만으로 캐싱할 수 있는 범위가 정해진다. 여기서는 디스크상에 배치되어 있는 4KB 블록만을 캐싱하므로 특정 파일의 일부분만, 읽어낸 부분만을 캐싱할 수 있다. 이렇게 이스크를 캐싱하는 단위가 페이지다.

 

페이지 = 가상 메모리의 최소단위

I/O 부하를 줄이는 방법

캐시를 전제로 한 I/O 줄이는 방법

살펴본 바와 같이 캐시에 의한 I/O 경감효과는 매우 크다. 캐시를 전제로 IO를 줄이기 위한 대책을 세워가는 것이 유효하다는 것을 알 수 있을 것이다. 이것이야말로 I/O 대책의 기본이다. 이 기본으로부터 도출할 수 있는 포인트를 두 가지 소개한다.

 

첫 번째 포인트는 데이터 규모에 비해 물리 메모리가 크면 전부 캐싱할 수 있으므로 이 점을 생각할 것. 다루고자 하는 데이터의 크기에 주목하자는 것이다.

 

또한 대규모 데이터 처리에는 데이터 압축이 중요하다고 했는데, 압축해서 저장해두면 디스크 내용을 전부 그대로 캐싱해둘 수 있는 경우가 많다. 예를 들어 LZ법 등 일반적인 압축 알고리즘의 경우, 압축률은 보통이더라도 텍스트 파일을 대략 절반 정도로 압축할 수 있다. 4GB의 텍스트 파일이라면 메모리 2GB인 머신으로 뒷부분 절반 정도는 거의 캐싱할 수 없었던 것이, 압축해서 저장해두면 2GB로 캐싱할 수 있는 비율이 상당히 늘어나게 된다.

 

또 하나는 경제적인 비용과의 밸런스를 고려하고자 한다는 점이다. 최근에는 메모리가 8GB~16GB 정도가 일반적인 서버 한 대의 메모리 구성이다.

국소성을 살리는 분산

국소성을 고려한 분산이란?

  • 액세스 패턴을 고려한 분산
  • 캐싱할 수 없는 부분이 사라진다

파티셔닝

파티셔닝은 한 대였던 DB 서버를 여러 대의 서버로 분할하는 방법을 말한다. 분할 방법은 여러 가지가 있지만, 간단한 것은 '테이블 단위 분할'이다.

  • entry 테이블
  • bookmark 테이블
  • tag 테이블
  • keyword 테이블

위와 같이 분할해서 각기 다른 서버로 관리하도록 하고 있다. 이것이 테이블 단위 분할에 의한 파티셔닝이다.

 

1,2,는 같이 액세스 하는 경우가 많으므로 같은 서버에 위치시키고 있다. 그밖에도 몇 종류가 동일 서버에 저장되어 있으며, 크기로는 개당 2GB 정도의 테이블이 여러 개, 대략 16GB 정도의 메모리를 탑재한 머신을 준비해두면 전부 메모리에 올릴 수 있다. tag, keyword 테이블은 각각 꽤 커서 10GB 정도 된다.

 

테이블 단위로 분할했으면 entry나 bookmark 테이블로의 요청은 1+2 서버로, tag나 keyword로의 요청은 3+4서버로 보내 처리될 수 있도록 한다.

 

다른 분할 방법으로는 '테이블 데이터 분할'이 있다. 특정 테이블 하나를 여러 개의 작든 테이블로 분할한다.

요청 패턴을 '섬'으로 분할

'용도별로 시스템을 섬으로 나누는 방법'도 있다.

 

HTTP 요청의 User-Agent나 URL 등을 보고, 예를 들어 통상의 사용자이면 섬1, 일부 API 요청이면 섬 3, Google bot이나 yahoo 등의 봇이면 섬 2 와 같은 식으로 나누는 방법이다.

4. 분산을 고려한 MySql 운용

분산할 때는 국소성을 고려하고, 데이터 구묘에 맞게 탑재 메모리를 조정하고, 메모리 증설로도 대응할 수 없을 경우에는 분산하라는 것이 지금까지 한 설명의 주된 흐름이었다. 메모리와 디스크의 속도차와 그로 인한 I/O 분산의 어려움, 그리고 이를 전제로 시스템을 어떻게 구축/운용할 것인가가 서서히 분명해지는 것 같다.

 

DB 스케일아웃 전략에 대해 자세히 살펴보도록 하자.

인덱스를 올바르게 운용하기

인덱스의 중요성

MySql의 인덱스는 기본적으로 B+트리라는 데이터 구조다. B+트리는 B트리에서 파생된 데이터 구조다. B트리는 트리를 구성하는 각 노드가 여러 개의 자식을 가질 수 있는 다분트리다. 또한 데이터 삽입이나 삭제를 반복한 경우에도 트리의 형태에 치우침이 생기지 않는 '평형 트리'이기도 하다. B트리는 하드디스크 상에 구축하기에 알맞은 데이터 구조이므로 DB에서 자주 사용된다.

 

동일한 트리지만 이분트리와 B트리는 어떤 점이 다를까? 이분트리는 노드가 반드시 하나로 정해져 있고 자식 노드가 두 개로 정해져 있지만, B트리는 m=5처럼 개수가 정해진다. B트리는 이 수를 조정함으로써 각 논드의 크기를 적당한 사이즈로 정할 수 있다. 이 점이 B 트리의 장점이다.

 

여기서 노드의 크기라는 것이 3장에서 설명한 디스크의 페이지와 매우 밀접한 관계가 있다. 노드 1개로 디스크의 1블록만큼을 할당하면, B트리로 디스크 상에 저장했을 때, 1블록, 1블록과 같이 각 노드를 딱 1블록만큼으로 해서 저장했을 것이다.

 

감이 좋은 사람은 벌써 눈치챘을 것이다. 앞에서 OS는 디스크에서 데이터를 읽을 때 블록 단위로 읽어낸다고 했다. 또한, 임의의 위치에 있는 데이터를 읽어내려면 물리적인 동작, 다시 말해 디스크 Seek이 발생하고, 여기서 밀리초 단위로 시간이 걸리며 느리다는 것도 설명했다.

트리에서 검색을 할 때는 노드에서 노드로 트리를 순회한다. B트리의 경우, 각 노드를 1블록에 모아서 저장되도록 구성할 수 있으므로 디스크 Seek 발생횟수를 노드를 찾아갈 때만으로 최소화할 수 있다. OS가 한 번에 읽어내서 메모리에 캐싱하게 되므로 같은 노드 내의 데이터는 디스크 Seek 없이 탐색할 수 있다.

 

한편, 이분트리는 특정 노드를 모아서 1블록에 저장하는 등의 작업이 어렵다. 그러므로 이분트리를 디스크 상에 저장하는 데 있어서 디스크 구조에 최적화할 수가 없다. 그 결과, 디스크 상의 이분트리를 검색하려고 하면 여기저기 블록에 분산되어 있는 데이터를 읽어야 하므로 디스크 Seek 횟수가 많아지게 된다.

 

B+트리는 각 노드 내에 자식 노드로의 포인터만 가지고 있고 포인터 이외에 데이터로서의 실제 값 등은 제일 마지막인 잎 노드에만 가지고 있는 구조다. B+트리가 DB에 데이터를 저장하는 데 좀 더 최적화된 데이터구조라는 점은 알아두도록 하자.

인덱스의 효과

그렇다면 인덱스의 효과는 실제로 어느 정도일까? 대략 정리해보면 다음과 같다.

[예] 4,000만 건 태그 테이블에서의 탐색

  • 인덱스 없음 = 선형탐색 -> O(n) -> 최대 4,000만 번 탐색
  • 인덱스 있음 = B트리로 이분탐색 -> O(log n) -> log 4000만 = 최대 25.25번

MySql의 레플리케이션 기능

Mysql에는 기본 기능으로 레플리케이션 기능이 있다. 레플리케이션이란 마스터를 정하고 마스터를 뒤따르는 서버를 정해두면, 마스터에 쓴 내용을 슬레이브가 폴링해서 동일한 내용으로 자신을 갱신하는 기능이다. 슬레이브는 마스터의 레플리카가 되는 것이다. 이렇게 해서 동일한 내용의 서버를 여러 대 마련할 수가 있다.

 

마스터/슬레이브로 레플리케이션해서 서버를 여러 대 준비하게 되면, AP 서버에서는 로드밸런서를 경유해서 슬레이브로 질의한다. 이렇게 해서 쿼리를 여러 서버로 분산할 수 있다.

 

이때 애플리케이션 구현에서 select 등 참조 쿼리만 로드밸런서로 흘러가도록 한다. 갱신 쿼리는 마스터로 직접 던진다. 갱신 쿼리를 슬레이브로 덩지게 되면 슬레이브와 마스터 간 내용을 동기화할수 없다.

 

MySql은 마스터와 슬레이브 간 내용의 불일치를 감지해서 레플리케이션을 중지해버린다. 이렇게 해서 오류로 이어진다는 것은 쉽게 상상할 수 있을 것이다. 따라서 갱신은 어디까지나 반드시 마스터에서 이뤄지도록 한다. 하테나에서는이 부분을 O/R 매퍼 내에서 제어하고 있다.

마스터/슬레이브의 특징

이 구성에서는 마스터를 분산할 수 없다는 문제가 있다. '참조계열 쿼리는 슬레이브로 분산하면 되므로 분산할 수 있지만, 갱신계열 쿼리를 분산할 수 없지 않은가?'라는 문제다. 그리고 또 한가지, 마스터의 다중화를 어떻게 할 것인가라는 문제도 당연히 발생한다.

 

참조계열 쿼리는 확장을 위해 서버를 늘리면 되는데, 다만 서버를 늘린다고는 해도 앞서 말했듯이 대수를 늘리기보다도 메모리에 맞추는 것이 중요하다.

 

한편, 마스터는 확장할 수 없다. 반드시 할 수 없는 것은 아니지만, 갱신계열 쿼리가 늘어나면 상당히 험난해진다. 그렇지만 이 부분에서는 웹 애플리케이션의 특성이 있는데, 웹 애플리케이션에서는 대략 90% 이상이 참조계열 쿼리다. 쓰기는 상대적으로 훨씬 적다.

갱신/쓰기 계열을 확장하고자 할 때

그러나 드물지만 마스터에 엄청난 쓰기작업이 발생하는 애플리케이션을 개발하는 경우가 있다.

 

이런 경우 테이블을 분할해서 테이블 크기를 작게 해준다. 그러면 분할로 인해 쓰기작업이 분산된다. 테이블 파일이 분산되면 동일 호스트 내에서 여러 디스크를 가지고 분산시킬 수도 있으며, 서로 다른 서버로 분산할 수도 있다.

 

다음으로, 처음부터 RDBMS를 사용하지 않는 방법도 생각해볼 수 있다. 하테나에서 쓰기작업이 너무 많아서 RDBMS를 사용하지 않는 실제 사례로는 오구메모의 동영상 재생횟수를 표시하고 있는 부분이다. 사용자가 동영상을 재생할 때마다 갱신이 일어난다. 여기는 쓰기작업 횟수가 많아서 RDB로는 확장할 수 없어서 key-value 스토어 방식이다.

MySQL의 스케일아웃과 파티셔닝

MySql의 기본적인 스케일아웃 전략으로는 데이터가 메모리에 올라가는 크기이면 메모리에 올리고, 올라가지 않으면 메모리를 증설하는 것이었다. 그리고 '인덱스는 제대로 걸자'였다.

 

메모리 증설이 불가능하다면 파티셔닝.

파티셔닝(테이블 분할)에 관한 보충

파티셔닝이란 테이블 A와 테이블 B를 서로 다른 서버에 놓아서 분산하는 방법이다. 파티셔닝은 국소성을 활용해서 분산할 수 있으므로 캐시가 유효하고 그래서 파티셔닝은 효과적이라는 얘기였다.

 

단, join 하고 있는 테이블 들에 대해서는 다른 서버로 나눌 수 없다.

파티셔닝의 상반관계

파티셔닝의 좋은 점은 부하가 내려가고 국소성이 늘어나서 캐시 효과가 높아진다는 점이었다. 나쁜점도 물론 있다.

  • 운용이 복잡해진다.
  • 고장률이 높아진다.

5. 대규모 데이터 처리 실전 입문

용도특화형 인덱싱

인덱스와 시스템 구성

전문 검색이나 유사문서계열 탐색, 데이터마이닝의 경우 RDBMS로는 한계가 있다.

 

배치 처리로 RDBMS에서 데이터를 추출해서 별도의 인덱스 서버와 같은 것을 만들고, 이 인덱스 서버에 웹 애플리케이션에서 RPC 등으로 액세스하는 방법을 사용한다.

RPC, 웹 API

우선 DB가 있다. DB에서 정기적으로 3시간에 1번처럼 cron 등으로 데이터를 추출해서 인덱스 서버로 넘기는 것이다. 인덱스로는 검색용 역 인덱스를 만들어준다. AP 서버에서는 인덱스를 갖고 있는 인덱스 서버에 RPC로 엑세스 한다.

RPC는 Remote Procedure Call을 의미한다. 요즘은 RPC 보다는 웹 API라고 부르곤 한다.

 

인덱스를 갖고 있는 서버에 웹 서버를 실행하고, 여기에 무언가를 검색해서 JSON을 반환하는 애플리케이션을 만들고 웹 API로 JSON에 액세스한다.

용도특화형 인덱싱

검색에서 역 인덱스가 그 전형적인 예로, 자연언어처리와 같은 처리를 미리 한 다음 인덱스를 만들어두면 RDBMS로 데이터를 전부 순회하지 않아도 순식간에 검색할 수가 있다.

반응형