대규모 포털이나 오픈마켓과 같은 대규모 웹사이트를 운영하기 위해서는 여러가지 시스템들이 잘 구성이 되어있어야, 무정지 서비스를 할 수가 있다.
 예전에 오픈마켓 회사에서 근무했던 경험을 바탕으로, 간단히 소개해보고자 한다. 
 
참고로, 오픈마켓과 포털의 기본적인 차이점은, 오픈마켓쪽이 얽혀 있는 트랜잭션이 많고, DB의 구조가 포털쪽에 비해서 상상할 수 없을 정도로 복잡하다. 그래서 DB를 설계할 시에 테이블을 수직적으로 분할하기 힘든 상황이 많다. 그리고, 테이블간의 관계가 복잡하여, 개발시에 조금만 설계를 잘못해도, 조인 연산으로 인해 그 파괴력이 후덜덜 할 수 있다는 점을 유의하면 될 것이다.

일단, 웹사이트의 가장 기본 형태는,

- 웹서버만 존재하는 경우 (정적인 데이터들로만 구성된 웹페이지인 경우)
- 웹서버와 DB서버로 구성된 경우(동일 하드웨어 혹은 분리된 하드웨어)일 것이다.

부하가 작은 경우엔 웬만해서 못하는 것 없이 거의 다 할 수 있을 것이다. 

좀더 부하가 커지게 되면, 다음과 같은 단계를 취할 것이다.

1. 웹서버를 증설한다.
2. DB서버를 고사양으로 바꾼다.

DB에 걸리는 부하보다 웹서버단의 가용자원이 떨어지면, 웹서버를 병력적으로 여러 대로 증설하여 효과를 볼 수 있다. 그러나 웹서버가 증가되면, 결국은 DBMS서버의 커넥션 풀 관리나 DB요청 간격이 짧아지게 되므로, DB서버의 업그레이드로 이어지게 된다.

웹서버는 병렬적으로 여러대 서버를 사용해서 동일한 효과를 얻을 수 있지만, DB서버의 경우에는 DB서버를 분할하기 위해서는 Database 구조를 변경하고, 다시 어플리케이션을 변경하는 등의 번거롭고 힘든 작업을 수행하게 되므로, 여러 서버로 DB를 분할하기 보다는 첫단계에서는 DB서버를 고사양으로 업그레이드 하게 된다.

 더욱 발전하여 위의 단계를 넘어서 사이트가 커지게 되면, 부하의 양상에 따라서, 대응하는 방법이 나누어진다.

웹서버에서 처리되는 부하가 증가하는 경우에는,

1. 정적인 페이지(js, css, html)와 이미지 파일의 도메인이 동적 요청을 처리하는 도메인에서 분리된다.

2. 그리고, 이미지 도메인에 이미지 파일 캐시를 위한 Jaguar cache server같은 이미지 캐시 서버를 적용하고, 부하 분산해서 처리할 수 있는  대용량 NAS장비를 사용한다.

3. 후에, 부하가 더욱 커지는 경우에는 CDN서비스를 사용하여 구성할 수도 있다.

4. 웹서버를 비즈니스 영역별로 도메인을 분리한다. (상품, 주문, 회원, 블로그, 뉴스 등등의 방식으로) 

그나마 웹서버의 부하만 큰 경우는 행복한 경우라고 할 수 있다. DB쪽 부하는 사이트의 확장성에 큰 문제점을 제시한다. 물론 Oracle grid 서버를 이용해서 최고사양의 서버를 몇대 묶어서 사용할 수 있지만, 오라클 DBMS 비용과 유지보수 비용은 어마어마 할 것인다.

이 단계에서부터는 사이트의 사활이 걸려 있으므로, 여러가지 동원될 수 있는 방법은 다 동원된다.
특히, 아래방법은, 입력보다는 조회의 트래픽이 다수일 때 적용하면 효과적인다.

1. Memcached와 같은 Cache 서버를 사용한다.

2. 리스팅을 위한 검색엔진을 사용한다. 보통 검색엔진은 상품이나 어떤 내용을 찾기 위해서 사용된다고 생각하지만, 그러한 검색만큼 많이 사용하는 것이 카테고리 페이지같이 리스팅을 위해서 DB처럼 많이 사용된다. 그냥 부하감소를 위한 리스팅용 DB라고 생각하면 편할 수도 있다. (참고로, 오픈소스 검색엔진으로 Apache Lucene이 있다. )

3. DB서버의 분할을 시작한다. 가령 오픈 마켓인 경우의 예를 들면, 상품, 주문, 회원 같은 정보를 담고 있는 DB를 분할하기 시작한다.

4. DB의 수직분할을 위한 DAL(Data Access Layer)을 적용한다. 가령 블로그나 그런 시스템이라면, 사용자 계정의 순서를 짤라서 특정 DB서버에 위치시키거나 할 수 있을 것이다. 오픈 마켓의 경우에는 상품을 몇번 상품번호부터 몇번 상품번호까지 1번 DB서버, 그 후로는 2번 DB서버.. 등등으로 서버를 구성하고, 어플리케이션 서버에서 DB서버에 대한 구체적인 정보없이 투명하게 데이터를 질의해서 가져오기 위한 방법을 적용하고자 할 것이다. 그러나, 오픈마켓쪽에서 DB구조가 복잡하게 얽혀 있는 경우에는 절대 적용하기 쉬운 방법이 아니다.

5. 캐시의 일종으로, 주요페이지(메인, 특정 유입페이지)를 시간별로 미리 html페이지를 만드는 방법을 생각할 수도 있다. 특히 각 사이트의 메인페이지는 유입도 많고, 보여주는 정보도 많기 때문에, Memcached같은 캐시방식보다는 차라리 미리 페이지를 만들어서 보여주는 것이 더 효율적일 수도 있다.

6. 이 방법은 내가 전 직장에서 구현한 방법인데, 부하가 높은 상품 페이지를 캐시하기 위해서,( 한 상품페이지에 Stored procedure 호출이 3,40번씩 일어나고, SP를 열어보면 엄청난 데이터의 테이블이 여럿 조인이 되어 있는 막강 파위 SP들이 꽤 있었다. ), 히트 상품 및 상위 랭크를 하는 수만개의 상품에 대해서, 조회되는 데이터를 상품 캐시파일을 만들고, 데이터 요청을 처리하는 캐시시스템을 만들었다.  DB호출과 같은 방식으로 데이터를 얻어오게 하였고, 많이 호출되는 상품 파일들은 운영체제에서 캐시를 하는 효과가 있긴 했었다. 메모리 캐시를 명시적으로 적절히 사용하면 더 좋은 시스템이 되지 않았을 까 생각이 된다.

그렇다면, 입력에 의해 부하가 심한 경우에는 어떻게 할 것인가? 이 경우가 위의 경우보다 더 어려운 경우이다.

입력 부하가 심한 사이트의 경우에는,
 1. DB설계가 제일 중요하다. 잘게 쪼개고, 사용자 영역별로 쪼개서 DB요청이 서버별로 분배되게 해야 한다. 

 2. 위의 방법만으로만으로 부족한 경우에는 Message Queue를 활용한다. 물론 Message Queue의 용도가 이런 것은 아니지만, 잘 활용하면 부하 분산에 효과가 있다. Amazon이 주문에 Message Queue를 사용한 것으로 알고 있다.
 사용자가 밀어넣는 입력 부하를 Message Queue 서버군에서 받고, 해당 내용을 배치처리로 DB에 입력하고, 입력된 데이터에 의해서 바뀌는 상황에 따라서 캐시를 업데이트 하거나 검색엔진의 동적색인을 위한 절차등을 타게 한다. 그러나, 이 방법은 실시간처리가 아니므로, 글을 작성했는데 한참 후에 보인다던가 하는 경우가 벌어질 수 있다.  

 최근에는, 사용자 부하 뿐만 아니라, 단지 DB backend job으로 처리하기 힘든 대용량 데이터를 처리하기 위해서, Hadoop과 같은 MapReduce나 분산파일시스템, 그리고 Hadoop기반의 HBase와 같은 분산DB의 활용이 일반화되고 있다.
Posted by 눈사람
,