2014년 6월 10일 화요일

Memcached 복제 (1)

개요

모든 응용 프로그램은 영구적으로 저장되어야 하는 데이터를 가지게 마련이며,
이런 데이터들은 MySQL 서버와 같은 RDBMS나 NoSQL류의 DBMS에 저장되고 있다.
하지만 웹 기반의 응용 프로그램에서는 매우 빈번하게 데이터를 DBMS로부터 가져와서 가공하고 그 결과를 클라이언트로 전송해야 하는 요건을 가지고 있는데,
이렇게 많은 요청들을 매번 DBMS에서 가져간다는 것은 상당히 부담스러운 작업중 하나이다.
MySQL과 같은 RDBMS에서는 레코드 하나를 가져가기 위해서도 내부적으로 많은 복잡한 과정들을 거쳐야 하며,
때로는 메모리에 상주되지 않은 데이터를 위해서 고 비용의 디스크 읽기를 거쳐야 할 수도 있다. 
이는 HBase나 Cassandra와 같은 NoSQL류의 데이터베이스에서도 마찬가지이다. 때로는 NoSQL류의 데이터베이스는 데이터 읽기 작업이 RDBMS보다 훨씬 고비용인 경우가 많다.

그래서 이렇게 자주 사용되는 데이터는 빠르게 접근할 수 있도록 Memcached나 Redis와 같은 메모리 기반의 캐시 솔루션을 도입해서 구현하는 것이 매우 일반적인 형태이다.
Memcached와 Redis 모두 많은 개발자들로부터 관심을 받고 있는 캐시 솔루션이지만, 여전히 이 솔루션들은 각자의 단점들을 가지고 있다.

(이 글은 Memcached와 Redis중 어떤 솔루션이 더 나은지를 비교하는 것이 목적이 아니므로, 관심 대상이 아닌 Redis에 대한 언급은 생략하도록 하겠다.)
각 단점중에서 Memcached가 가진 단점 중 대표적인 것은 Memcached의 데이터가 복제되지 않는다는 것이다. (물론 그 이외에도 많은 단점들이 있을 것이다.)
최근에는 많은 회사들이 Memcached 서버의 데이터 복제나 여러 Memcached 서버간의 데이터 동기화에 대한 요건을 가지고 있으며, 페이스북의 경우에는 MySQL 서버의 바이너리 로그를 분석해서 Memcached로 변경 내용을 Relay해주는 기능들을 구현해서 사용중이기도 하다.
카카오에서도 Memcached의 이런 단점을 보완하기 위한 방법을 고려하던중, Memcached 플러그인이 내장된 MySQL 5.6 버전이 릴리즈되었다.

MySQL 5.6  Memcached 플러그인

우선 본격적인 이야기에 앞서서, MySQL 5.6의 Memcached 플러그인에 대한 기본적인 내용을 조금 살펴보도록 하자.
MySQL 5.6에 내장된 Memcached 플러그인은 아래와 같이 3가지 캐시 모드로 작동할 수 있다.

  1. Innodb-only
  2. Caching
  3. Cache-only


애초에 MySQL Memcached 플러그인은 InnoDB의 NoSQL 인터페이스로 도입된 솔루션인 관계로, InnoDB 스토리지 엔진과 매우 밀접하게 연결되어 있다.

  • 첫 번째 Innodb-only 모드에서는 Memcached 플러그인이 자체적인 캐시 메모리 공간을 가지지 않고, InnoDB 스토리지 엔진에 Memcached 프로토콜을 이용해서 데이터를 저장하고 읽어가기 위한 방법을 제공하는 것이다.즉 Memcached 프로토콜을 이용해서 SET/DELETE 그리고 GET 오퍼레이션이 실행되면, MySQL Memcached 플러그인은 그 명령을 InnoDB 스토리지 엔진으로 그대로 전달해서 실제 내부적으로는 InnoDB 테이블의 데이터를 변경하거나 조회해서 클라이언트로 반환하게 되는 것이다.



  • 두 번째 Caching 모드에서는 InnoDB 버퍼 풀과는 별도로 MySQL Memcached 플러그인이 자체적인 캐시 메모리 공간을 가지는 방식이다. 이 모드에서는 데이터를 ADD/SET/DELETE 오퍼레이션이 수행되면, MySQL Memcached 플러그인의 캐시 메모리 공간에 데이터를 변경함과 동시에 변경 내용을 InnoDB 테이블에도 같이 적용하게 된다.물론 Memcached 플러그인에 적용된 변경 사항이 InnoDB 테이블에 즉시 적용될지 또는 모아서 배치 형태로 처리될지는 MySQL 서버의 옵션을 통해서 조절할 수 있다.그리고 GET 오퍼레이션이 수행되면, Memcached 플러그인의 캐시 메모리에 존재하는 데이터라면 Memcached 플러그인 레벨에서 처리가 완료되고 그렇지 않다면 Memcached 플러그인이 InnoDB 테이블을 조회해서 클라이언트로 반환하게 된다.이 캐시 모드는 마치 MySQL 서버와 Memcached 서버를 하나로 묶어둔 것처럼 작동하는 방식이다.



  • 세 번째 Cache-only 모드는 MySQL Memcached 플러그인이 주 역할을 수행하며 InnoDB 스토리지 엔진은 전혀 처리에 관여하지 않게 된다.물론 Memcached의 캐시 메모리 공간에만 데이터가 기록되기 때문에 MySQL 서버가 재시작되면 캐시 메모리의 데이터는 모두 사라지게 될 것이다.


첫 번째와 두 번째 캐시 모드에서는 모두 Memcached 플러그인을 통해서 최종적으로는 InnoDB 스토리지 엔진으로 데이터가 전달되기 때문에 Memcached 플러그인을 통해서 유입된 데이터라 하더라도 바이너리 로그에 기록되어서 슬레이브 MySQL 서버로 전달된다.
하지만 순수한 Memcached 서버와 같은 방식으로 작동하는 세 번째 모드는 Memcached를 통한 데이터 유입이 InnoDB 스토리지 엔진으로 전달되지 않기 때문에 바이너리 로그에 기록되지 않는다.
MySQL Memcached 플러그인이 제공하는 3가지 캐시 모드중에서 첫번째와 두번째는가 각각의 목적과 용도에 맞게 훌륭하게 사용될 수 있을 것으로 보지만, 사실 3번째 Cache-only 모드는 왠지 MySQL 서버에서 필요로 할 기능처럼은 보이지 않는다. 
그런데 여기에서 제일 쓸모가 없을 것으로 보이는 세 번째 캐시 모드에서 Memcached 서버의 데이터 복제에 대한 가능성을 찾을 수 있었다.

만약 MySQL Memcached 플러그인의 Cache-only 모드에서, Memcached 플러그인을 통해서 유입된 데이터가 InnoDB 스토리지 엔진으로는 전달되지 않지만 바이너리 로그에는 기록된다면 어떻게 될까 ?

이 기능이 보완된다면, MySQL 서버를 이용해서 Memcached 서버의 데이터 복제나 동기화가 구현되는 것이다.
결국 이는 MySQL 서버의 복제 기능을 Memcached 서버에 결합하는 효과를 얻을 수 있게 되는 것이다.

물론, 바이너리 로그 기록 하나만 수정해서 모든 것이 해결되는 것은 아닐 것이다. 언급하지 않은 작은 문제들과 제약 사항들이 도사리고 있을 것이다.
하지만 MySQL 서버의 안정적인 복제 방식을 Memcached 서버에 도입할 수 있게 된다면 더 없이 좋은 솔루션이 될 것이다. 그것도 많은 시간을 투자하지 않고서 ...

(2편에서 계속 ...)

댓글 없음:

댓글 쓰기