디스크 병목 현상에 따른 DB 성능 리포트

Overview

어느 시스템에서도 병목 현상은 어딘가에 있습니다. DBMS 또한 CPU, Memory, Disk로 구성된 하나의 시스템이기 때문에 당연히 특정 구역에서 병목현상이 발생할 수 있죠. 오늘은 Disk에서 발생하는 병목에 관해서 말씀드리겠습니다.

Memory Processing

디스크 배열(RAID)에 따른 DB 성능 비교 에서, 메모리가 충분하면 아래와 같다는 그래프를 보여드렸습니다.

InnoDB Buffer Pool : 12G
InnoDB Buffer Pool : 12G

어떤 경우든 메모리에만 연산이 가능하다면, CPU자원을 거의 활용 가능하다고 할 수 있죠. 그러나 만약 디스크 I/O가 발생하는 순간부터 CPU는 전혀 연산하지 않는 현상이 발생합니다. 바로 디스크 I/O Wait 으로 인한 시스템 병목 현상 발생입니다.

Benchmark

대용량 환경에서 MySQL 성능을 분석하기 위해 2억 데이터 Insert 테스트를 수행하였습니다. (하단 결과에서는 1.3억 데이터까지만 추출하여 그래프를 만들었습니다.)

하단은 테스트를 위해 사용한 테이블 스키마입니다. (간단한 테스트입니다.) 30개 Thread로 동시 Insert 작업을 수행하였고, 건 수에 따라 QPS및 시스템 현황을 살펴보았습니다.

##테이블 정의
CREATE TABLE `test` (
`NO` int(11) NOT NULL AUTO_INCREMENT,
`EMAIL` varchar(128) DEFAULT NULL,
`NAME` varchar(32) NOT NULL,
PRIMARY KEY (`NO`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
PARTITION BY KEY ()PARTITIONS 3;

##테이블 포멧 변경
TRUNCATE TABLE TEST;
ALTER TABLE TEST ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=4;

Benchmark Result

버퍼풀 4G 환경 하의 일반 테이블과 압축 테이블 성능 비교 및 버퍼풀 8G 환경 하에서의 성능 비교입니다.
압축 테이블의 경우 생각보다 많은 CPU 작업이 필요하게 되는데요, 메모리에 모든 데이터가 존재한다면 이 자체가 병목입니다.
하지만 데이터가 급증하여 DISK I/O이슈가 발생하면 반대로 CPU 유휴 자원을 사용하여 병목을 줄일 수 있습니다.

디스크 압축에 따른 QPS 비교
디스크 압축에 따른 QPS 비교
디스크 압축에 따른 DISK I/O 비교
디스크 압축에 따른 DISK I/O 비교

7000만 건 데이터(데이터파일 약 5G) Insert까지는 일반 테이블이 압도적인 성능을 보여줍니다.  7000만 건 이상 데이터 Insert에서는 1/4로 압축한 테이블 성능이 꾸준히 유지됩니다. 9000만 건 데이터 Insert부터 1/4 압축 테이블도 성능 저하가 발생합니다.

가장 괄목할만한 사항은 DISK I/O가 급증하는 시점부터는 CPU자원은 거의 사용하지 않는다는 점입니다.

Conclusion

디스크 병목을 풀기 위해서 더욱 빠른 디스크로 고도화하여 풀 수 있는 방법이 있습니다. 다른 방법은 어차피 사용하지 못할 CPU자원이라면, CPU자원을 일부 소모하더라도 압축 테이블로 저장하여 디스크 병목을 해결할 수 있습니다.

앞선 테스트 결과가 반드시 정답은 아닙니다. 무조건 압축 테이블만이 대안은 아닙니다. 하지만 서비스 특성에 맞게 테스트 시나리오를 작성하고 병목을 사전에 최대한 줄이는 활동이 필요합니다.

무조건 고 사양의 서버로 구성하기 보다는 조금만 데이터를 다른 시각으로 설계한다면, 동일 자원에서 최적의 퍼포먼스를 발휘할 수 있을 것입니다.

동일한 내용은 제가 “파란 개발자 블로그”에 작성한 디스크 병목 현상에 따른 DB 성능 리포트 에서도 확인할 수 있습니다.^^

디스크 배열(RAID)에 따른 DB 성능 비교

Overview

MySQL DBMS 하드웨어 구성 시 어떠한 정책으로 움직이는 것이 가장 효율적일지, 메모리/디스크 설정을 변경하여 테스트를 진행하였습니다. 디스크는 RAID 레벨을 변경하였고, innodb_buffer_pool을 조정함으로써 메모리 환경을 구성하였습니다. 서비스 특성에 따라 하드웨어 구성을 달리함으로써, 장비를 더욱더 효율적으로 사용할 수 있을 것으로 기대됩니다.^^

디스크배열(RAID)란?

RAID란 Redundant Array of Inexpensive Disks의 약자로 디스크를 여러장 묶어서, 데이터 중복성 및 성능 향상을 유도할 수 있는 기법입니다. RAID 기법은 참으로 많이 있으나, 일반적으로 실무에서는 RAID0, RAID1, RAID5, RAID10또는 RAID01을 많이 사용합니다.

더욱 상세한 내용은 하단 블로그를 참조하시면 되겠습니다.
http://blog.naver.com/jevida?Redirect=Log&logNo=140118943472

Benchmark 

테스트 환경은 다음과 같습니다.

  • CPU
    – Intel(R) Xeon(R) CPU E5630  @ 2.53GHz Quad * 2EA
  • Memory(InnoDB Buffer Pool)
    – 12G : 데이터 100%가 메모리 안에 존재 (DISK I/O 없음)
    – 8G : 데이터 80% 가 메모리 안에 존재 (DISK I/O 일부 발생)
    – 4G : 데이터 40% 미만 메모리 안에 존재 (DISK I/O 다량 발생)
  • DISK RAID
    – RAID1 : 데이터/로그 디스크 공유
    – RAID1(2) : 데이터/로그 디스크 분리
    – RAID5 : 데이터/로그 디스크 공유
    – RAID10 : 데이터/로그 디스크 공유
  • 데이터 사이즈
    – 50,000,000건 (11G)
  • 동시 접속 수
    – 1, 5, 10, 15, 20, 30, 100
  • 트랜잭션 구성
    – READ-ONLY : 14 Queries (–oltp-read-only –oltp-skip-trx)
    – READ/WRITE : 19 Queries (–oltp-test-mode=complex)

Benchmark Result

  1. Innodb_Buffer_Pool Size : 12G
    테스트 결과 모두 비슷한 성능을 보여주나 100쓰레드에서는 raid1(2) 시 일부 성능이 저하되었습니다. (iblog에서 데이터 저장 공간에 적용 시 물리적 장치 분리에 의한 성능 저하 요인으로 파악되네요.)

    InnoDB Buffer Pool : 12G
    InnoDB Buffer Pool : 12G
  2. Innodb_Buffer_Pool Size : 8G
    READ/WRITE에서는 디스크 배열에 따라 상당한 성능 차이를 보이는데, Buffer-Pool안의 데이터가 디스크로 Flush 되면서 발생하는 데서 기인한 듯 하고, RAID10이 가장 안정적인 성능을 보여줍니다.

    InnoDB Buffer Pool : 8G
    InnoDB Buffer Pool : 8G
  3. Innodb_Buffer_Pool Size : 4G
    가장 재미있는 결과입니다. 디스크 의존도가 높기 때문에 당연히 Raid-10이 가장 우수합니다. 그 다음으로는 Raid-5, Raid-1 순으로 성능을 보입니다.

    InnoDB Buffer Pool : 4G
    InnoDB Buffer Pool : 4G

Conclusion

위 결과를 바탕으로 다음과 같이 결론짓고 싶습니다.

  • 예산이 허용한다면, 다수의 디스크를 사용한 Raid-10으로 구성
  • 빈번하게 사용되는 데이터가 메모리에 80% 이상 존재한다면 Raid-1도 괜찮은 성능을 보임 (특히 Read 시)
  • 데이터 변경 작업이 많은 DB인 경우 반드시 Raid5또는 Raid10으로 구성
  • 성능 확장에는 메모리 투자가 제일 유리

메모리에 데이터가 모두 존재할 수 있다면, CPU성능에 따라 TPS 결과가 나옵니다. 4000이상 TPS가 나오는 경우 CPU idle이 거의 0% 까지 떨어지기 때문에, 여기서부터는 CPU투자에 따라 결과가 좌우되겠죠.

동일한 내용은 제가 “파란 개발자 블로그”에 작성한 DISK Raid 구성에 따른 DB 성능 비교 분석 에서도 확인할 수 있습니다.^^

감사합니다.

MySQL Replication 이해(3) – 활용

Overview

MySQL Replication 시리즈 마지막 3탄, “활용”에 관한 포스트입니다. 앞 선 시리즈 MySQL Replication 이해(1) – 개념MySQL Replication 이해(2) – 구성)에서 기본적인 개념과 구성을 다뤘다면, 이 자리에서는 실제적으로 어떤 분야에 활용할 수 있는지 설명드리겠습니다.

  1. Scale Out
  2. High Availability
  3. Data Partitioning
자, 그럼 시작해볼까요?

Scale out

MySQL Replication이 가장 많이 활용되는 분야입니다.
MySQL Replication은 READ관련 Scale out만 가능합니다. 만약 WRITE 이슈가 있다면, MySQL 레벨에서는 Scale out이 불가합니다. 특히나 Replication 운영 시 마스터 트래픽이 과도하게 발생하면, Master와 Slave 간 데이터 동기화 지연 현상이 발생합니다. “반드시 알아야할 MySQL 특징 세 가지” 내용을 읽어보시면 이해가 조금더 수훨하겠네요.^^

MySQL Replication Scale Out
MySQL Replication Scale Out

WRITE 관련 Scale out이 불가하다고 했었는데, 전혀 불가능한 것일까요? 그렇지 않아요~! 서버 구성을 적절하게 재배치한다면 WRITE 분산도 일부 가능합니다.

  • 다중 마스터 구성 (하단 High Availability 참고)
    기본적으로 MySQL에서는 다중으로 마스터를 구성할 수 없습니다. 각 슬레이브들은 오직 하나의 슬레이브만 가질 수 있습니다.
  • 피라미드형  구성 (하단 Data Partitioning 참고)
    역할에 따라서 서버를 재배치하는 방식입니다. 모든 서버가 가져야할 데이터 공유는 최상위 마스터에서 담당하고, 중간 슬레이브는 자신이 맡은 역할에 맞는 마스터 역할을 하는 것이죠.

High Availability

MySQL Replication 을 높은 가용성 구현을 위해서 사용할 수 있습니다.  아래와 같이 가상 아이피(Virtual IP)를 통해서 App서버들이 서비스를 제공하고 있다면 마스터 장비 장애 발생 시자동으로 Virtual IP가 유휴 슬레이브 장비로 Virtual IP를 넘겨서 장애를 빠르게 대비할 수 있습니다.

High Availability
High Availability

일단 슬레이브로 마스터 역할이 넘어간 시점부터는 “현재 데이터의 기준”은 “신규 마스터”이어야 합니다. 데이터가 비동기적으로 복제되는 구조이기 때문에, 장애 후 IP가 넘어가는 일시적인 시점 동안 트랜잭션 유실은 발생할 수 있다는 점 있지 마세요^^

서버 한 대 효율을 조금 더 올리고자 한다면, 아래와 같이 구성해보는 것은 어떨까요?

High Availability : Multi-Master
High Availability : Multi-Master

문제는 동일 데이터 변경에 관한 이슈인데, 이것은 Service1 과 Service2 데이터베이스를 물리적으로 분리하시면 됩니다.

Data Partitioning

분명 MySQL Replication에서 Slave는 하나의 Thread로만 SQL을 실행하기 때문에, 서버 간 동기화 지연 현상이 발생합니다. 하지만 서버 구성을 조금만 변경한다면 어느정도는 해결할 수 있습니다.

Master Scale-out
Master Scale-out

Replicate_Do_DB 혹은 Replicate_Do_Table 옵션을 사용하여, 실제로 적용할 객체들만 선별적으로 동기화하는 것입니다. 서비스 단위로 기능을 나눌 수도 있고, 역할 별로 기능을 나눌 수 있습니다.

$ vi /etc/my.cnf
replicate-do-db=common

단, 서버 확장을 고려하여, 서비스 설계 단계부터 Database  또는 테이블을 최대한 물리적으로 분리하여 설계하는 것이 가장 중요합니다.

Replicat_Do* 옵션 참조)
Replication Slave Options and Variables

Conclusion

위에서 설명드린 것은 극히 일부일 뿐 더욱 다양한 케이스에 Replication을 활용할 수 잇습니다. 예를 들어 DB Major 버전 업그레이드(ex: 5.1.x -> 5.5.x), 테이블 구조 변경, 테스트 환경 구성 등이 바로 그것들입니다. MySQL Replication은 물리적으로 저장소가 분리된 영역에 데이터를 비동기적으로 복제하는 원리만 꼭 기억하세요. ^^

위 설명에서는 추상적으로 언급 드렸으나, 추후 실제 구성 사례를 정리해서 꼭 공유 드릴께요^^