[DB] Sharding
Sharding : 조각내다
● 작은 접속자로 시작했던 DB가 이제는 1000, 2000명이 접속하는 서버로 성장했는데
동시 접속에 대한 처리를 하지 않아서 DB가 살려달라고 하는 중...
어떻게 해결해야 할까?
● Sharding, 대규모 데이터베이스나 네트워크 시스템을 효율적으로 관리하고 성능을 향상하기
위해 데이터를 여러 개의 작은 조각(=Shard)으로 나누어 분산 저장하는 기술
→ 데이터베이스에서는 물리적으로 쪼개는 기술.
→ 하나의 서버 데이터를 하나의 데이터베이스에서 관리하는 것이 아닌 여러 데이터베이스에서 관리
● 수평적 샤딩(Horizontal Sharding)

- DB 한 개만 있을 경우에는 id가 1, 2, 3, 4, 5... 1000 한 곳에 전부 저장되었다면
- 4개로 나누었으므로 DB1 : 1, 5, 9 ..., DB2 : 2, 6, 10..., DB3 : 3, 7, 11... DB4 : 4, 8, 12... 분산
- 혹은 범위 기반 Sharding도 가능
if (playerId >= 1 && playerId <= 1000) {
return 0;
} else if (playerId >= 1001 && playerId <= 2000) {
return 1;
}
...
- DB1 : ID 1~1000, DB2 : 1001~2000...
DB를 Sharding 하면 처리 속도 빠르고 좋겠네?
● Sharding은 물리적으로 서버를 늘리는 것이기 때문에 현실적인 비용 문제가 생길 수 있다.
● 줄어드는 상황도 올 수 있는데 4개에서 3개가 되었을 때 나누어져 있던 데이터들 어떻게 처리해야 하는가
- id & 4 일 때 1, 5, 9... / 2, 6, 10... / 3, 7, 11... / 4, 8, 12... 4씩 늘어나던 DB가 갑작스레 3개로 줄어들어서
새로운 Shard 규칙이 적용되기에 재분배가 이루어지지 않는다면 id가 충돌.
- 즉, 재분배가 이루어져야 하는데 이는 데이터 이동 비용과 시스템에 부하를 줄 수 있다.
● 트랜잭션 문제도 발생
- Transaction은 하나의 데이터베이스에서만 작동이 되도록 설계
- 분산 트랜잭션을 사용할 수 있지만 이 또한 단점이 존재
→ Transaction Manager가 존재하여 prepare, commit을 관리한다
→ 다만 DB가 최신 값으로 갱신되는 타이밍이 조금씩 다를 수밖에 없다.
→ 심지어 네트워크 장애, 데이터베이스 장애로 prepare, commit 등 처리에 필요한 메시지를
1개 이상의 DB로부터 받지 못한다면 어떻게 처리해야 하는가
→ 즉, 분산 트랜잭션은 매우 느리다
Sharding, DB를 나누는 것은 상황에 따라서!
● 무작정 DB를 조각을 내서 서버를 운영하는 것은 좋다고는 할 수 없다.
● 데이터 처리가 빠를 수는 있지만 변수 처리에 단점이 명확하다.
● Sharding 사용이 고민된다면 체크리스트를 작성하여 필요성을 확립해야 한다.
□ 데이터베이스 크기가 커서 단일 서버로 처리하기 어려운가?
□ 동시 접속자가 많아 단일 데이터베이스 서버의 커넥션 한계를 초과하는가?
□ 현재 데이터베이스 성능이 부족하여 응답 시간이 길거나 처리 속도가 느린가?
□ 복잡한 샤드 관리와 모니터링을 처리할 수 있는 기술적 능력과 자원이 충분한가?
□ 분산 트랜잭션 관리를 할 수 있는 역량이 있는가?