[입 개발] Redis 에 추가될 Partial Sync 에 대해서…

Redis의 Partial Sync는 아직 완전히 구현된 기능이 아니고, 브랜치의 psync 에만 존재하고 있습니다. Redis의 Replication 부분에 대해서 분석을 하다가, 그냥 보는 김에 psync 까지 보게 되었는데, 아직 구현중이니 나중의 모습은 많이 바뀔 수도 있습니다.

먼저 psync가 왜 만들어지게되었을까요? Redis의 Replication 과정중에 master와 slave의 접속이 끊어지게 되면, replicationCron 에 의해서 master와의 연결을 체크하고, 접속이 가능하면, 현재 메모리의 내용을 모두 지우고, Sync 과정을 통해서 모든 데이터를 가져오게 됩니다. 데이터 양이 적을 때는 전혀 문제가 없지만, 용량이 몇 GB가 넘는 상황에서 이런 작업은 네트웍 소모도 많고, 시간도 오래걸리게 됩니다. 그런데 잠시 네트웍 이슈로 연결이 끊겼다가 접속해도 매번 새로 받아야 한다면, 엄청난 낭비가 발생하게 됩니다. 특히 Redis는 1:1 이 아니라 다수의 슬레이브가 붙을 수 있으므로, master의 성능 저하도 발생하게 됩니다.

 

그럼 여러분이면 이런 문제를 어떻게 해결하시겠습니까? 잠시 접속이 끊긴 정도라면, 내용이 대부분 비슷할테니, 차이나는 것만 복사하면 되지 않을까라는 생각을 가지게 되실껍니다. 넵, 이게 바로 Partial Sync 의 핵심 아이디어입니다.

 

즉, Partial Sync의 아이디어는 잠시 끊어진 접속등에 대해서는 Full Sync 과정을 거치지 말고, 뒤에 바뀐 부분만 sync해서 부담을 줄이자이게 됩니다. 이를 위해서 master 에 replication 용 임시 버퍼가 있고 여기의 offset을 sync 시에 전달 받게 됩니다. 그리고 이 버퍼 크기 안에서의 접속의 끊어짐이면, 버퍼 정도만 sync 하게 되므로, 전체적인 부하가 줄어들게 됩니다. 그럼 이 버퍼 범위 전이면 어떻게 하느냐? 그냥 Full Sync를 하게 됩니다.

 

여기에는 Redis가 일반 DB와 다르게 RDB를 읽어서 차이점을 보내기가 힘들기 때문에(RDB는 그냥 메모리 정보를 덤프한 거라, 시간이나 순서등을 파악할 수 없습니다.) 이런 방법을 이용한 것 같습니다.

 

다만, Replication 버퍼가 크지 않기 때문에, 어느 정도만 시간이 지나도 Write Heavy 환경에서는 차이가 크게 날 수 있기 때문에, 적절한 버퍼 사이즈로 조절하는게 필요할 듯 합니다.

 

실 예는 다음과 같습니다. 테스트를 해보면 아직까지는 PING 같은 replication이 되지 않는 명령에 대해서도 replication 버퍼를 차지하는 단점이 있는데, 이 부분은 차차 개선되지 않을 까 싶습니다. 아직 구현중인 기능이니까요.

 

$ telnet localhost 6379
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
psync ? -1
+FULLRESYNC 4f8d0341a0aa431260c55ec5ee7f7326dbf69430 233
$40
REDIS0006?foobarcounter?mZ???{*1
$4
PING
*1
$4
PING
*2
$6
SELECT
$1
0
*2
$4
incr
$7
counter
^C
 
$ telnet localhost 6379
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
psync 4f8d0341a0aa431260c55ec5ee7f7326dbf69430 234
+CONTINUE
*1
$4
PING
*1
$4
PING
*2
$6
SELECT
$1
0
*2
$4
incr
$7
counter
*1
$4
PING

위의 예를 보면 psync ? -1 라고 보내면 최초에는 Full sync를 하게 되면서 현재 master의 runid 와 offset 을 주게 됩니다. 이를 이용해서 master가 종료된적이 없으면 같은 runid를 가지게 되고 offset은 자신이 받았던 값을 기억하고 있다가 중단된 시점부터 해당 offset 값을 이용해서 다시 가져오게 됩니다. 두번째로 psync를 보낼 때는 응답이 +CONTINUE 라는 것을 확인하실 수 있습니다.

runid가 다르거나 offset이 현재 master가 보관하고 있는 범위가 아니면, 다시 Full Sync가 진행되게 됩니다.

psync 4f8d0341a0aa431260c55ec5ee7f7326dbf69430 234