[입 개발] Redis Sentinel을 이용하면서 겪게 되는 문제 하나와 해결책

해당 포스트는 NIPA의 클라우드 지원센터의 도움으로 작성되었습니다.

Redis Sentinel을 이용하다보면, 흔한 상황은 아니지만, 문제가 생기는 상황이 있습니다. 어떤 상황이냐 하면, “모든 Redis 노드가 장애가 나고, 다시 한 대가 살아났을 때, 최초 Master가 아니면, Master 로 전환되지 않는 문제” 입니다.

즉 다음과 같이 Redis Master/Slave 각각 한대와 Sentinel 이 한대 있다고 가정하겠습니다.(여기서 Sentinel 과 Slave의 개수는 상관없습니다.)

sentinel1

그런데 여기서 Master가 장애나면 당연히 Slave가 Master로 승격이 되게 됩니다. 당연히 기대한 동작입니다.

sentinel2

sentinel3

자 이제 사고로 마지막 노드까지 장애가 나면 전혀 서비스 할 수 있는 서버가 없어지게 됩니다.

sentinel4

여기서 두 가지 가정이 있습니다.

  • 최초의 master 가 살아난다.
  • 마지막의 master 가 다시 살아난다.

첫번째 경우에는 전혀 문제가 없습니다. 즉 정상적으로 master가 인식이 됩니다.

sentinel5

그런데 두번째 케이스 원래 최후의 master나 다른 slave가 살아나네 되면… sentinel은 해당
노드 자체를 인식하지 못하게 되고, 계속 해당 노드는 Slave로 남아있습니다. 당연히 master가 되기를 바라고 있는데 말이죠.

sentinel6

그렇다면 왜 그런걸까요? 어떤 문제가 있는건가요?

사실, 실제로 Redis 두 대가 모두 죽어있을 때도 Sentinel 은 해당 두 노드에 대한 연결을 모두 가지고 있고 이를 지속적으로 체크하게 됩니다. 해당 작업은 sentinelHandleDictOfRedisInstances 에서 이루어집니다.

그런데 후자의 경우, Redis 노드가 다시 살아나면서!!!, 이전의 설정을 읽어드립니다. 즉, 자신이 slave라고 인식을 하게 되고, Sentinel 이 INFO 명령을 줬을 때, 자신이 slave 라고 전달하게 됩니다. 이 때, Sentinel은 slave가 연결되었을 때, master를 인식하고자 하고, 현재의 연결 정보를 날리고, Master 에 대한 연결만 가지게 됩니다. 정상적인 상황에서는 Master에 질의해서 Slave들의 정보를 가져올 수 있기 때문입니다.(sentinelRefreshInstanceInfo)

    /* ---------------------------- Acting half -----------------------------
     * Some things will not happen if sentinel.tilt is true, but some will
     * still be processed. */

    /* When what we believe is our master, turned into a slave, the wiser
     * thing we can do is to follow the events and redirect to the new
     * master, always. */
    if ((ri->flags & SRI_MASTER) && role == SRI_SLAVE && ri->slave_master_host)
    {
        sentinelEvent(REDIS_WARNING,"+redirect-to-master",ri,
            "%s %s %d %s %d",
            ri->name, ri->addr->ip, ri->addr->port,
            ri->slave_master_host, ri->slave_master_port);
        sentinelResetMasterAndChangeAddress(ri,ri->slave_master_host,
                                               ri->slave_master_port);
        return; /* Don't process anything after this event. */
    }

즉 Sentinel은 위의 작업 때문에 최초의 master에 대한 정보만 가지고, 계속 이전 아직 살아나지 않은 노드만 체크하게 되는겁니다. 그래서 정상적인 master가 살아날때는 문제가 없이 인식이 되는거죠.

사실 서버의 관리상 한대가 죽더라도 이에 대한 관리를 즉각 해야하기 때문에, 이런 일이 발생하는 일이 많지는 않지만, 서버가 급격히 죽을 경우는 문제가 될수도 있습니다.

그럼 이에 대한 해결책이 있는가? 라는 질문을 받게 된다면… 크게 두 가지 방법이 있습니다.
전자는 완벽한 해결책은 아니고, 장애가 난 마지막 master 노드가 살아났을 때에 대한 해결책입니다. redis에는 config rewrite 라는 새로운 명령이 들어가 있고, master 변환이 생길때마다 해당 명령을 던져주면 master로 동작하게 됩니다.

config rewrite

그러나 이것은 모든 경우에 대한 해결책은 아닙니다. 그렇다면, 어떻게 해결을 해야 하는가? 라는 질문이 생깁니다. 후자는 sentinel을 수정하는 방법입니다. 이건 다음 번에…(실제로 해당 수정을 통해서 위의 경우에 sentinel이 master로 인식이 되도록 하게 했습니다.) 그럼 60초 후에(?) 뵙겠습니다.