복제(replication)을 공부하면서 결국 가장 중요한 것은 각 노드 간의 동기화 문제를 잘 해소하는 것이 가장 중요하다고 생각이 든다. 리더 기반 복제를 이용함에 따라 쓰기 작업에 대한 혼선은 어느 정도 해결할 수 있지만 모든 노드에 대해 읽기 작업이 가능하기 때문에, 읽기 일관성과 성능 중에서 적절한 트레이드 오프가 이루어지는 것이 가장 큰 과제이다.
읽기 일관성이 보장되지 않는 경우는 언제인가?
현대 애플리케이션에서는 성능 문제로 비동기 혹은 반동기 형태의 복제를 사용하고 있다. 이에 따라 각 팔로워 노드에게 최신본이 전파되기까지의 시간이 발생하고, 이 사이에 사용자가 읽기 작업을 시도하게 되었을 때
경우에 따라 서로 다른 결과를 조회할 수 있다는 점에서 발생하게 된다.
하지만, 이러한 불일치의 경우에는 일시적인 상태에 불과하다. 결국 데이터베이스에 쓰기 작업을 멈추고 잠시 동안 기다리게 되면 팔로워는 언젠가 리더를 따라잡아 일치하게 된다. 이를 최종적 일관성(eventually consistency)라고 한다.
보다 구체적으로 어떤 케이스들이 있을까? 아래에 몇 가지 예시를 살펴보자
case 1 : 쓰기 후 읽기 일관성
일반적으로 사용자가 게시물을 작성한 경우, 작성한 게시물로 리디렉션 되는 등 이어지는 읽기 작업이 동반되는 경우가 대다수이다. 하지만 비동기식 복제에서는 후속 읽기 작업이 아직 동기화되지 않은 팔로워 노드에서 이루어지는 경우 자신이 작성한 게시글을 확인할 수 없다.
이러한 문제를 방지하기 위해 쓰기 후 일관성을 보장할 수 있다.
이는 사용자가 페이지를 재로딩했을 때, 자신이 제출한 모든 갱신을 볼 수 있음을 보장하는 것이다. 그 외의 다른 사용자에 대해서는 보장하지 않는다.
해결책?
- 쓰기 작업을 한 사용자에 한해, 리더에서 읽기 작업을 강제하는 방법이 있다.
하지만 거의 모든 사용자가 쓰기 작업에 참여하는 경우, 자칫 복제의 이점을 잃을 수 있다.
- 마지막 갱신 시점을 찾아서 마지막 갱신 후 1분 동안 리더에서 모든 읽기를 수행하도록 한다.
- 팔로워에서의 복제 지연 모니터링을 통해 극복할 수 있다.
case 2 : 단조 읽기
사용자의 `시간이 거꾸로 흐르는 현상` 이라고 비유하는 표현이 딱 적합한 것 같다!
즉 사용자가 연속적인 읽기 작업을 시도했을 때, 먼저 최신본의 노드에서 읽고 이후 이전 버전의 노드에서 처리가 되는 경우를 생각해보면 된다.
기존에 최신본에서는 조회되었던 데이터가 이후에 사라지는 현상이다.
해결책?
- 각 사용자에 대한 읽기를 항상 동일한 복제 서버에서 수행되도록 보장
- 각 읽기 작업이 수행되는 노드를 결정할 때, 랜덤보다는 사용자 ID 해시 기반으로 선택하는 방법도 있을 것 같다!
우선 해당 내용에 대해서 굉장히 재미있는 해결책이라는 생각이 들었다! 확실히 해시를 사용하면 각 사용자에 대해 unique한 식별자 역할이 가능할 것이기 때문이다!
이를 두고 논의해 본 결과 특정 자바 버전에 따라 Hash 값이 달라질 수 있는 문제가 있을 것이라고 판단하였다.
자바의 hash 알고리즘이 Java 8버전을 기점으로 이전보다 훨씬 단순한 형태로 변했기 때문이다.
그 이유는, 우선 Java 8을 기점으로 해시 자료구조 내 일정량의 데이터가 축적된 경우 Tree구조(red-black tree)를 통해 해시 충돌에 대한 성능 문제를 어느 정도 극복 가능해졌기 때문이라는 점도 참고하면 좋을 것 같다.
'CS > Database' 카테고리의 다른 글
[DB] 트랜잭션의 격리성과 동시성에 대해(feat. 트랜잭션의 격리 수준) (5) | 2024.07.23 |
---|---|
Replication - 리더 기반 복제에 대해 (0) | 2024.06.10 |
[MYSQL] float, double 저장 시, 소수점이 깨지는 문제 (0) | 2023.09.05 |