이번에 회사에서 직면했던 복제지연 문제에 관한 내용을 공유하고자 글을 남깁니다.
저희 회사에서는 database replication을 통해 부하를 분산하여 성능을 높히는 방식을 사용하고 있습니다.
저희는 Master와 Slave 구조의 Active Active 이중화로
Proxy sql을 통해 SELECT는 Slave로 INSERT, UPDATE, DELETE는 Master로 SQL이 날라가게 되고 변경된 데이터가 Slave로 동기화되는 작업이 이루지게 됩니다.
이러한 부하분산을 통해 성능을 향상시켜왔습니다.
위와같은 구조에서 발생할 수 있는 문제로 가장 먼저 이야기가 나올만한 부분은 복제 지연문제입니다.
그림으로 설명드리는게 빠르겠네요
위처럼 INSERT는 Master로 날라가게 되고 SELECT는 Slave로 날라가게 됩니다. 문제는 데이터베이스간 싱크가 비동기적으로 이루어지니 사용자가 INSERT를 한 직후 SELECT를 하게되면 Slave에 데이터 동기화가 완료되지 않은 시점이라면 사용자 입장에서는 데이터를 유실한것 처럼 보여지게 됩니다.
(관련된 문제에서 발생한 Exception Slack)
저희 회사에서는 위 문제가 꾸준히 있어왔는데 위 문제를 해결하는 방법에는 다양한 방법이 있습니다. 예를 들어 자신이 쓴 내용 읽기, 단조 읽기, 일관된 순서로 읽기 등이 있습니다.
그러나 저희 회사가 위 문제를 해결하기 위해 지금까지 선택해왔던 방법은 생각보다 간단하고 무식한 방법이였는데요.
주요 비지니스를 다루는 어플리케이션은 ProxySQL이 아닌 Master만 보도록 한다.
였습니다.
위 해결방법으로 해결했었던 이유는 크게 두가지였습니다.
1. 일시적인 문제로 데이터 동기화가 이루어지면 더이상 발생하지 않는다.
2. 주요 비지니스 로직은 INSERT 후 SELECT 하더라도 문제가 없도록 하면 된다.
3. 다른 개발일정이 있기때문에 위 문제에 디버깅, 개발할 여유가 되지 않는다.
이러한 3가지 이유로 위 해결방법이 선택됐었습니다.
그렇지만 위 해결방법은 database replication을 통해 부하를 분산하여 성능을 높히는 방식과는 거리가 멀어지는 해결방법이였기 때문에 좀더 나은 해결방법이 있다면 해결하고 싶다는 욕구는 항상 가지고 있었고 이번에 개발 일정을 주어졌던 일정보다 빨리 끝낸 제가 맡아서 해보겠다 건의드렸습니다.
승인은 어렵지 않게 떨어졌고 아래 Reference들을 찾아보며 어떤 방식으로 해결하는 것이 좋을지 고민하게 됐습니다.
제가 선택한 방법은 AbstractRoutingDataSource를 통해
INSERT후 SELECT해야할만한 로직이 포함된 곳이라면 Master를 바라볼 수 있도록 구현하는 방법이였습니다. (관련글1, 관련글2)
적용하는 방법은 위글에 자세히 나와있으니 다루지는 않겠습니다.
위를 저희회사 모든 어플리케이션에 구현하고 INSERT후 SELECT해야할만한 로직이 포함된 곳이라면 어노테이션을 통해 Master를 바라볼 수 있도록 했습니다. 그러나 여전히 문제는 발생할 수 있습니다.
사용자 A가 INSERT한 데이터를 사용자 B가 거의 동시에 읽으려 시도할 경우입니다.
하지만 이와같은 케이스는 빈번하지 않을 것이라 생각했고 위 방법을 모든 어플리케이션에 적용했다 하더라도 여전히 주요 비지니스를 다루는 어플리케이션은 ProxySQL이 아닌 Master만 보도록 뒀기 때문에 end user 입장에서는 이슈를 느끼지 못할 가능성이 높았습니다.
사실 복제지연 문제는 Replication 구조를 가지고 있거나 서로 다른 DB간 데이터 복제가 이루어져야할 때 맞이할 수 밖에 없는 고질적인 문제라고 생각합니다.
항상 나중에 해결해야지 해결해야지라는 생각으로 미뤄왔지만 이번에 NAVER 컨퍼런스인 DAN24에 다녀오면서 NAVER FINANCIAL Tech에 김진한님 세션 네이버페이 결제 시스템의 성장과 변화를 듣고 아 나도 회사 돌아가면 복제지연 문제를 해결해보고 싶다
라는 생각이 들어 해결하게 됐습니다.
굉장히 좋은 세션과 발표였습니다.
위 본문 내용중 정확하지 않은 내용이 포함돼 있을 수 있습니다.
저는 2년차 백엔드 개발자로 스스로 굉장히 부족한 사람이라는 점을 인지하고 있는지라
제가 적은 정보가 정확하지 않을까 걱정하고 있습니다.
혹여 제 정보가 잘못 됐을 수 있으니 단지 참고용으로만 봐주시고 관련된 내용을 한번 직접 알아보시는 걸 추천합니다.
혹여 잘못된 내용이 있거나 말씀해주시고 싶은 부분이 있으시다면 부담없이 적어주세요!
수용하고 개선하기 위해 노력하겠습니다!
https://drunkenhw.github.io/java/select-database/
https://velog.io/@ghkvud2/AbstractRoutingDataSource-%EC%A0%81%EC%9A%A9%ED%95%98%EA%B8%B0
https://velog.io/@kimtjsdlf/%EB%B3%B5%EC%A0%9C2-%EB%B3%B5%EC%A0%9C-%EC%A7%80%EC%97%B0