기술 학습

대규모 트래픽을 처리하는 MySQL 샤딩

밤린 2024. 6. 13. 18:03

Problem

 

- 게임서버를 만들게 되면 서버와 DB간 1:1 매핑으로 게임 서버를 만들 수 없음

- 유저는 어느 서버든 접속할 수 있어야 하며, 유저의 정보는 DB여러개 중 어딘가에 존재함으로 게임 서버는 모든 DB로의 접속이 가능해야 함

- 이 때 예시로 서버 200대가 있고 DB가 30대가 있으며 각 서버마다 DB에 Connection pool을 300개를 맺게 해주면 단순 산수로 각 MySQL서버 마다 60,000개의 conns required 필요해짐 <- 서비스가 불가능함

 

Proxy

GameServer와 DB사이에 뭔가 새로운 계층이 필요함

 

새로운 계층(Proxy Layer)에 대한 요구사항

1. DB에 대한 Connection 관리 및 그 요구량을 완화 <- 근본적인 문제

2. 직접 구현x, MySQL 특화, Query인식 <- 투명한 미들웨어(구현의 필요성x : 직접 구현을 하게 되면 검증을 해야 하며 이 비용이 비쌈)

3. Clustering지원, Scalability, 고성능 <- 성능 및 안정성

+ 적용 실패시 쉽게 fade-out할 수 있어야 함

 

Compare

- MySQL에서 직접 제공하는 Router는 성능이 좋지 않음

- MariaDB의 MaxScale이 사용할만 하지만 가장 중요한 Connection Multiplexing을 지원하지 않음

ProxySQL ?

ProxySQL은 MySQL과 호환DB들을 위한 고성능, 고가용성, 프록시로서 MySQL 프로토콜 자체를 인식하여 동작한다

 

특징

 

- 게임 서버가 ProxySQL을 봤을 때 그냥 MySQL 서버와 동일하다

- MySQL입장에서는 백엔드는 MySQL에 쿼리를 던지는 그냥 어플리케이션임

- Front와 Back-end가 합쳐서 ProxySQL이 됨

- Multi Layer 구성이 가능하다

- 이 경우 게임 서버 입장에서 ProxySQL1번의 Front가 MySQL서버임

- DB입장에서는 ProxySQL2의 Back이 애플리케이션임

- ProxySQL1의 백엔드와 ProxySQL프론트는 동일한 관계 <- 관계가 명확해짐

- 클러스터링도 가능

 

Connection Multiplexing

MySQL DB에 대한 connection 수를 극적으로 줄여주는 핵심 기능

 

많은 수의 Front-end connection들을 효율적으로 적은 양의 Back-end connection들로 muxing

- 다중화를 통해 이를 해결한다는 의미로 여러 개의 저수준의 요청을 하나의 고수준으로 통합해준다는 의미

- connection multiplexing이 만능은 아님 (일부 시스템 쿼리나 특정 쿼리는 multiplexing이 안됨)

 

Schema 기반의 샤딩

게임 유저를 정해진 스키마로 샤딩

- 임의의 게임 유저는 각자의 data가 적재되어 있는 논리 DB로 Rule에 기반해서 접근

 

User 기반의 샤딩

DB 유저를 정해진 MySQL서버로 샤딩

- 임의의 MySQL 서버 유저는 정해진 MySQL서버로 Rule에 기반해서 샤딩

 

DB유저명 + 스키마명 = 목표 논리 DB

 

Query rules example

 

Advance Architecture

- ProxySQL은 자체적으로 MySQL replication hostgroup 정보를 관리 가능

- ProxySQL에서 제안하는 방식은 Query Pattern Matching <- 정규표현식으로 쿼리에 대한 쿼리룰을 등록

ex) select -> slave / insert, update -> master

- 서비스 중에 새로운 쿼리가 추가되면 쿼리 패턴을 수정해야 함 <= MySQL username을 이용해서 해결

 

 

Schema Sharding

- 각각의 물리 MySQL Server는 여러 논리 Schema로 구성

- 접근할 DB수가 많아질 수록 코드의 복잡도도 상승 but, proxySQL 사용시 구현 비용은 무시 가능

-  샤딩이 된 MySQL Server에서 유저 증가시 DB자체를 migreation을 통해 각 1,2,3 물리 DB가 1 ->3개로 늘어 부하가 분산됨

- 유저가 감소하게 될 시 1,2,3을 하나의 물리 서버로 migreation을 통해 비용감소

- ex) 한 대의 MySQL에 10개의 스키마를 생성하고 총 10대의 MySQL 서버로 서비스를 하면 -> 총 100개의 스키마로 샤딩 되며 서버에서 100개의 DB관리를 해야 하며 이를 ProxySQL이 처리함(이 때, 모든 유저와 스키마 사이의 매핑 정보는 RouteDB에서 관리)

- 모든 유저를 RouteDB에서 관리하게 되면 병목 형상이 발생할 수 있음

 

Final Architecture

Fading-out RouteDB

- 서버에서 고유한 ID 발급  UniqueID -> Murmur Hash 진행 f(x) -> ( UserDB index = f(UniqueID) % N (고정 상수값)

- UserDB index을 통해 RouterDB없이 자신의 DB를 알 수있음 

- N의 숫자에 따라 최악의 상황에서 최대로 늘릴 수 있는 물리DB의 수가 됨

 

 

 

 

Reference

https://www.youtube.com/watch?v=8Eb_n7JA1yA&ab_channel=NHNCloud