본문 바로가기메뉴 바로가기


kakao의 오픈소스 Ep2 – MRTE(MySQL Realtime Traffic Emulator)

 

“카카오의 오픈소스를 소개합니다” 두번째는 matt.lee와 동료들이 개발한 MySQL Realtime Traffic Emulator(MRTE)입니다.

MRTE는 실서비스용 MySQL 서버의 트래픽을 수집하는 MRTE-Collector와, 수집한 데이터를 테스트용 MySQL 서버에서 재현하는 MRTE-Player 두 개의 툴로 구성되어 있습니다.

카카오에서도 효율적인 MySQL 운영에 큰 도움이 되고 있는 유용한 소프트웨어입니다. 특히 MRTE-Collector는 Go로 작성되어 Go로 네트웍 프로그래밍을 하려는 개발자들에게 유용할 것입니다.

MySQL 서버를 사용하면서, 가끔씩 실 서비스용 MySQL 서버(Production mysql server)로 유입되는 쿼리들을 똑같이 흉내낼 수 없을까 하는 생각들을 많이 했습니다.

실 서비스용 MySQL 서버에서는 MySQL 시스템 변수 하나도 조정해보기 어려운 경우가 많고, 때로는 업그레이드나 통합 또는 하드웨어 테스트를 하는 경우에는 이런 도구들이 절실했죠.

이를 위해서 MRTE (MySQL Real Traffic Emulator) 도구를 생각하기 시작했는데, 조금만 고민해보니 사실 이는 그다지 어려운 일이 아니었다. 여기에서는 MRTE에 대한 간략한 아키텍쳐와 사용법을 간단히 소개하도록 하겠습니다.

MRTE는 크게 유저 트래픽을 수집하는 MRTE-Collector와 수집된 SQL을 재현하는 MRTE-Player로 구성되어 있는데, MRTE-Collector와 MRTE-Player는 Message Queue (Rabbit MQ)를 이용해서 통신하도록 설계되었습니다.

MRTE Collector와 Player 전체적인 아키텍쳐

이 도구는 크게 아래와 같은 2가지 제약 사항을 가집니다:

  1. MRTE-Collector는 네트워크 인터페이스의 패킷을 캡쳐하기 때문에, 반드시 MySQL 서버와 동일 장비에서 실행되어야 합니다.
  2. Server-side prepared statement는 외부 툴에서 SQL 문장을 덤프할 수 있는 방법이 없으므로, 현재 버전의 MRTE는 Server side prepared statement는 지원하지 못합니다.

1번 제약 사항을 위해서 MRTE-Collector는 최소한의 자원을 사용하면서도 빠르게 작동할 수 있도록 설계했으며, 이를 위해서 GO 언어를 사용해서 Native code로 컴파일해서 실행할 수 있도록 개발되었습니다.

실제 초당 35000개의 패킷을 캡쳐해서 외부의 Message Queue로 전송하는 경우에도 2~3%의 CPU만 사용하는 것으로 관측되었다. 하지만 일반적인 서비스 환경의 MySQL 서버에서 초당 몇 만정도의 쿼리를 처리하는 경우는 그다지 많지 않다는 것을 감안하면, MRTE-Collector를 MySQL 서버와 동일 장비에 실행한다는 것은 그다지 큰 제약 사항이 아닐 수도 있어 보인다. 또한 MRTE-Collector는 10~15MB 정도의 물리 메모리만 사용했었다. GO 프로그램의 특성상 Virtual memory는 700MB 정도로 꽤 점유하는 편이지만, 사실 Virtual memory 확보는 그다지 시스템의 자원 사용이나 성능에 영향을 미치지 않는다는 것이 Google의 의견입니다.

아래 그래프는 MRTE-Collector가 실행중인 MySQL 서버의 CPU 사용량인데, 잠깐 MRTE-Collector를 멈췄을 때 CPU 사용량이 얼마나 떨어지는지를 보여주고 있습니다:

MRTE의 CPU 사용량

그리고 MRTE-Collector는 tcpdumpngrep 명령과 같이 pcap 라이브러리를 이용하기 때문에 매우 안정적으로 패킷을 캡쳐할 수 있다. 실제 sysbench로 초당 35000 쿼리가 실행되는 환경에서도 MRTE-Collector 시작 및 종료(패킷 캡쳐 시작 및 종료)시에도 서비스에 특별한 성능 악 영향은 보이지 않았다. 또한 Message Queue나 MRTE-Collector가 문제를 일으켜 제대로 처리하지 못할 때에는, pcap 라이브러리는 MRTE-Collector의 처리를 기다리지 않고 수집된 패킷을 버리고 무시하기 때문에 유저의 네트워크 패킷을 블록킹하지는 않습니다.

2번 제약 사항(Server side prepared statement) 제약 사항에 대해서 조금 살펴보겠습니다. MySQL 서버에서는 2종류의 PreparedStatement를 지원하고 있습니다:

  • Client side prepred statement: 초기 MySQL 서버가 PreparedStatement를 지원하지 못하던 시절에는 Client JDBC Driver에서 PreparedStatement를 흉내낼 수 있도록(표준 준수) Client side prepared statement를 지원했었는데, 이를 Client side prepared statement라고 합니다.
  • Server side prepared statement: 이후 MySQL 서버에서 PreparedStatement를 지원하게 되면서 실제 Client side에서 PreparedStatement emulation이 아닌 타 RDBMS와 동일한 방식의 PreparedStatement 기능을 지원하기 시작했는데, 이를 Server side prepared statement하고 합니다.

초기 MySQL 서버에서는 Text protocol(Text protocol이라고 해서 문자가 전송되는 프로토콜을 의미하는 것이 아니라 SQL 문장이 그대로 전달된다는 의미에서 Text protocol이라 함)만 지원했었는데, Server side prepared statement를 위해서는 새로운 프로토콜(Binary protocol)이 도입되었습니다. 현재 MRTE-Collector에서는 Binary protocol을 사용하는 경우는 지원하지 않고 있는데, 이는 패킷 분석의 어려움이 문제가 아니라 MRTE-Collector에서 PreparedStatement의 Hash Id를 알아낼 수 있는 방법이 없기 때문에 어려움이 있습니다.만약 MySQL 서버에서 Connection별로 만들어진 PreparedStatement의 dump가 가능하다면 향후 Binary protocol도 지원이 가능할 것으로 보입니다.

하지만 다행스럽게도, JDBC Client에서 server prepared statement의 사용 여부를 명시적으로 활성화하지 않으면 기본적으로는 Client side prepared statement가 사용되고 아직 MySQL 서버에서는 PreparedStatement의 장점이 그다지 크지 않아서 대부분의 경우 Statement 또는 Client side prepared statement를 사용하고 있는 상태입니다.

MRTE 도구의 안정성과 성능 확인을 위해서 서버 4대를 아래와 같이 할당해서 테스트를 수행했습니다. 모두 2 소켓 12 코어 CPU를 사용하는 DELL 장비를 사용했습니다.

  • A : Source MySQL Server + MRTE-Collector
  • B : Rabbit Message Queue (+sysbench load generator)
  • C : Target MySQL Server
  • D : MRTE-Player

테스트는 대략 60개 정도의 Connection을 이용해서 초당 30000 QPS(22000 SELECT, 5000 UPDATE, 1600 INSERT, 1600 DELETE) 정도의 SQL을 처리하고 있었으며, MRTE-Collector와 MRTE-Player 모두 Internal queue가 평균 0~1개 정도만 쌓일 정도로 무리 없이 처리하고 있는 상태로 진행되었습니다. 아래 그래프는 테스트 도중 Source와 Target MySQL 서버의 Query activity를 보여주는 그래프입니다. (Source와 Target MySQL 서버 모두 그래프의 스파이크 현상은 MRTE와는 무관한 것임)

MRTE 환경에서의 QPS

이 테스트 환경으로 대략 3주 정도 계속 sysbench 트래픽을 Target MySQL 서버로 전송하는 테스트중에도 별다른 문제가 발생하지 않았으며, MRTE-Collector를 10분 단위로 종료했다가 재시작하는 테스트도 대략 1주일 정도 진행했었는데 특별히 문제 상황은 발생하지 않았습니다.

Rabbit MQ가 정상적으로 설치(모니터링 플러그인까지)되었다면 http://rabbtmq_host:15672/ 웹 사이트를 이용해서 MRTE-Collector와 MRTE-Player가 정상적으로 통신을 하고 있는지 그리고 각각의 모듈들이 제대로 작동하고 있는지 바로 확인이 가능합니다.

MRTE-Collector와 MRTE-Player 소스 코드는 아래 Github 사이트에서 참조해볼 수 있습니다:

이 글은 카카오 DB팀의 기술 블로그 DB Smalltalk에 포스팅한 MRTE를 이용한 MySQL Real Service 트래픽 테스트 환경 구축을 옮긴 것입니다.

matt.lee
matt.lee
Top Tag
2021
2021-new-krew
Ad Platform
Ad tech
adaptive-hash-index
adt
adtech
agile
agilecoach
ai
algorithm
Algorithm/ML
Algorithm/Ranking
almighty-data-transmitter
Analyzer
android
angular
anycast
App2App
applicative
Architecture
arena
ast
async
aurora
babel
babel7
Backend
BApp
bgp
big-data
binary
ble
blind-recruitment
block
Block Chain
blockchain
bluetooth
brian
business
Cache
cahtbot
canvasapi
Caver
cch
cd
CDR
ceph
certificate
certification
cgroup
chrome
ci
cite
client
clojure
close-wait
cloud
cloudera-manager
clustered-block
cmux
cnn
code-festival
code-review
codereview
coding
coding test
competition
Compliance
component
conference
consul
container
contents
contest
cookie
core-js@3
Corporate Digital Responsibility
couchbase
COVID-19
cpp
Data
data-engineering
DB
deep-learning
Dependency
dependency-graph
desktop
dev
dev-session
dev-track
developer
developer relations
developers
devops
digitalization
digitaltransformation
dns
docker
dr
Electron
employeecard
emscripten
eslint
extract-text
Feature List
Featured
Feedback
friendstime
front-end
frontend
functional-programming
funfunday
fzf
garbage-collection
gawibawibo
GC
github
globalpollution
go
graphdb
graphql
Ground X
growth
ha
hadoop
hate speech
hbase
hbase-manager
hbase-region-inspector
hbase-snashot
hbase-table-stat
hbase-tools
hri
id
if kakao
ifkakao
infrastructure
innodb
internship
ios
item
Java
javascript
javascript web-assembly
JCMM
JIRA
jsconf
jsconfkorea
json
k8s
kafka
kakao
kakao-Career-Boost-Program
kakao-commerce
kakao-games
kakaoarena
kakaobrain
kakaocommerce
kakaocon
kakaoenterprise
kakaok
kakaokey
kakaokrew
kakaomap
kakaopage
kakaotalk
KAS
KCDC
khaiii
Klaytn
Klip
kubernetes
l3dsr
l4
License
links
Linux
load-balancing
MAB
Machine Learning
machine-learning
map
marathon
meetup
melon
mesos
message
Messaging
microservice
Microsoft TypeScript
mm
mobil
monad
monorepo
ms-office
MSA
mtre
mysql
mysql-realtime-traffic-emulator
nand-flash
network
new
new-krew
nfc
Nickface
nomad
ocp
olive
onboarding
open
open source
opensource
openstack
OpenWork
OSS
page
parallel
PBA
performance
planning poker
Platform
polyfill
programming-contest
project-structure
pycon
python
quagga
react
reactive-programming
reactor
recap
recommendation
recommendation system
recruitment
redis
redis-keys
redis-scan
related-blind
Renderer
rest
Rome
rubics
ruby
rxjs
s2graph
scala
scalaz
seminar
Serve
server
service
sharding
shopping
socket
spark
spark-streaming
SpringBoot
ssd
Statistics/Analysis
Stomp
storage
storm
style-guide
summer internship
support
System
talk
talkchannel
tcp
tech
Techtalk
test
thread
Thread-Debugging
time-wait
tmux
Topic Modeling
typescript
Untact
update
User Story
vim
vim-github-dashboard
vim-plugin
vue
vue.js
WASM
web-cache
web-worker
webapp
webgl
WebSocket
webworkers
weekly
work
workplatform
개인화 추천
길찾기
라이선스
연관 추천
오픈소스
오픈소스검증
의존성분석
일하는방식
협업
All Tag
2021
2021-new-krew
Ad Platform
Ad tech
adaptive-hash-index
adt
adtech
agile
agilecoach
ai
algorithm
Algorithm/ML
Algorithm/Ranking
almighty-data-transmitter
Analyzer
android
angular
anycast
App2App
applicative
Architecture
arena
ast
async
aurora
babel
babel7
Backend
BApp
bgp
big-data
binary
ble
blind-recruitment
block
Block Chain
blockchain
bluetooth
brian
business
Cache
cahtbot
canvasapi
Caver
cch
cd
CDR
ceph
certificate
certification
cgroup
chrome
ci
cite
client
clojure
close-wait
cloud
cloudera-manager
clustered-block
cmux
cnn
code-festival
code-review
codereview
coding
coding test
competition
Compliance
component
conference
consul
container
contents
contest
cookie
core-js@3
Corporate Digital Responsibility
couchbase
COVID-19
cpp
Data
data-engineering
DB
deep-learning
Dependency
dependency-graph
desktop
dev
dev-session
dev-track
developer
developer relations
developers
devops
digitalization
digitaltransformation
dns
docker
dr
Electron
employeecard
emscripten
eslint
extract-text
Feature List
Featured
Feedback
friendstime
front-end
frontend
functional-programming
funfunday
fzf
garbage-collection
gawibawibo
GC
github
globalpollution
go
graphdb
graphql
Ground X
growth
ha
hadoop
hate speech
hbase
hbase-manager
hbase-region-inspector
hbase-snashot
hbase-table-stat
hbase-tools
hri
id
if kakao
ifkakao
infrastructure
innodb
internship
ios
item
Java
javascript
javascript web-assembly
JCMM
JIRA
jsconf
jsconfkorea
json
k8s
kafka
kakao
kakao-Career-Boost-Program
kakao-commerce
kakao-games
kakaoarena
kakaobrain
kakaocommerce
kakaocon
kakaoenterprise
kakaok
kakaokey
kakaokrew
kakaomap
kakaopage
kakaotalk
KAS
KCDC
khaiii
Klaytn
Klip
kubernetes
l3dsr
l4
License
links
Linux
load-balancing
MAB
Machine Learning
machine-learning
map
marathon
meetup
melon
mesos
message
Messaging
microservice
Microsoft TypeScript
mm
mobil
monad
monorepo
ms-office
MSA
mtre
mysql
mysql-realtime-traffic-emulator
nand-flash
network
new
new-krew
nfc
Nickface
nomad
ocp
olive
onboarding
open
open source
opensource
openstack
OpenWork
OSS
page
parallel
PBA
performance
planning poker
Platform
polyfill
programming-contest
project-structure
pycon
python
quagga
react
reactive-programming
reactor
recap
recommendation
recommendation system
recruitment
redis
redis-keys
redis-scan
related-blind
Renderer
rest
Rome
rubics
ruby
rxjs
s2graph
scala
scalaz
seminar
Serve
server
service
sharding
shopping
socket
spark
spark-streaming
SpringBoot
ssd
Statistics/Analysis
Stomp
storage
storm
style-guide
summer internship
support
System
talk
talkchannel
tcp
tech
Techtalk
test
thread
Thread-Debugging
time-wait
tmux
Topic Modeling
typescript
Untact
update
User Story
vim
vim-github-dashboard
vim-plugin
vue
vue.js
WASM
web-cache
web-worker
webapp
webgl
WebSocket
webworkers
weekly
work
workplatform
개인화 추천
길찾기
라이선스
연관 추천
오픈소스
오픈소스검증
의존성분석
일하는방식
협업

위로