출처 : http://redis.io/presentation/Redis_Cluster.pdf
- 모든 노드는 서비스 채널과 함께 직접 연결되어 있다.
- 기본 TCP Port는 4000번 이상, 예를들어 6379 -> 10379.
- 노드간 프로토콜은 바이너리 형태이고, bandwidth와 speed에 최적화되어 있다.
- 클라이언트는 보통 노드들과 통신하고, ascii 프로토콜은 사용하며, 마이너 추가를 한다.
- 노드들은 질의들을 위임 또는 대리인 역할을 하지 않는다.
노드끼리는 어떤 대화를 할까?
PING : 친구 괜찮니? 나는 XYZ hash slots을 위한 Master야. 설정정보는 FF89X1JK야. | PONG : 물론 괜찮아. 나는 XYZ hash slots을 위한 Master야. 설정정보는 FF89X1JK야. |
수다 : 여기 내가 연락하고 지내는 다른 노드 정보가 있어.A는 나의 Ping에 답변하였고, 내 생각에 걔 상태는 좋아. B는 가동되지 않고 있어, 내 추축으로는 문제가 있는거 같아. 그래서 나는 확인이 필요해. | 수다: 나는 너와 몇몇 불특정 노드들에 대해 공유하고 싶어.C와 D는 괜찮고, 제 시간에 응답해. 그런데 B는 나 또한 가동되고 있지 않아. 내 생각엔 다운된거 같아. |
Hash slots
마스터 그리고 슬레이브 노드들
노드들은 모두 연결되어 있고 기능적으로 동등하다, 그러나 실제로는 두가지 타입의 노드들이 있다(마스터와 슬레이브 노드들로,,,)장애복구
이번 예제에서는 모든 마스터 노드마다 두개씩의 복제품이 있다, 그래서 두개의 불특정 노드까지는 아무런 이슈 없이 다운 될 수 있다. 가동 중에 두개까지의 노드 다운은 보장한다, 하지만 최선의 방법은 클러스터가 모든 Hash slot에 대해 최소한 하나의 노드로 계속 작동하는 것이다.여기까지의 뜻은 뭐냐면?
- 모든 키는 오직 하나의 인스턴스에 존재한다. 또한 N개의 복제품은 절대 쓰는 기능을 받지 않는다. 그래서 병합이 없고, 어플리케이션상 불일치 문제 또한 없다.
- 그 대가가 네트워크 분리에 저항하지 않는 것은 Hash slot당 복제품 노드들이 다운 되는것보다 크다.(음.... 무슨뜻일까,, ㅋㅋ The price to pay is not resisting to net splits that are bigger than replicas-per-hashslot nodes down.)
- 마스터와 슬레이브 노드들은 당신이 이미 알고 있듯이 Redis Replication을 사용한다.
- 모든 물리적 서버는 보통 여러개의 노드(마스터와 슬레이브들)들을 유지하고, 클러스 관리 프로그램인 redis-trib은 마스터와 슬레이브를 할당하고 복제품들은 각각 다른 서버에 위치한다.
클라이언트 요청 - 안똑똑한 클라이언트
- Client => A : GET foo
- A => Client : -MOVED 8 192.168.5.21:6391
- Client => B : GET foo
- B => Client : "bar"
클라이언트 요청 - 똑똑한 클라이언트
- Client => A : CLUSTER HINTS
- A => Client : ... a map of hash slots -> nodes
- CLient => B : GET foo
- B => Client : "bar"
클라이언트 요청들
- 안똑똑한 단일 연결 클라이언트들은 기존 클라이언트 코드 베이스에 대해 최소한의 수정으로 작동한다.
- 똑똑한 클라이언트들은 여러 노드에 영구적으로 연결하고, hashslot -> node 정보를 캐쉬한다, 그리고 -MOVED 에러를 받았을때 테이블(캐쉬)에 반영한다.
- 이 스키마는 항상 수평적인 확장성이 있고 낮은 Latency를 바탕으로 한다. 단 클라이언트가 독똑하다면 말이다.
- 특히 클라이언트가 많은 노드들에 수많은 영구적인 연결을 하는 대규모 클러스터에서 Redis 클라이언트 객체는 꼭 공유되어야 한다.
Re-sharding(재 분할?분배?)
- 우리는 너무 많은 로드를 경험할 것이다. 신규 서버를 추가 하자.
- 노드 C는 slot 7에 "MOVING to D"라고 기록한다.
- 매 시간 C는 slot 7에 대해 요청을 받는다, 만약 그 key가 아직 C에 있다면 답변을 하고, 또한 -ASK D 라는 답변도 한다.
- -ASK는 -MOVED와 유사하지만 다르다, 이 뜻은 클라이언트가 D에게 이 질의를 다시 물어봐야 한다, 다른 질의는 상관없다. 이 뜻은 똑똑한 클라이언트가 내부 상태를 변경하면 안된다는 뜻이다.
Re-sharding(재 분할?분배?) - 데이터 이동
- Slot 7에 대한 모든 새로운 Keys는 D에서 생성되고 수정되어 질 것이다.
- C에 있는 모든 Old Keys는 redis-trib의 MIGRATE 명령어에 의해 D로 옮겨질 것이다.
- MIGRATE는 하나의 원자(shell) 명령어이다, 이것은 C에 있는 key를 D로 옮기고, D에서 잘 받았는 응답을을 받은 후, C에 있는 그 key를 삭제할 것이다. 그래서 경쟁은 불가능하다.(동시에 진행되어 먼저 삭제할리 없다는 뜻인거 같음.)
- p.s MIGRATE은 만들어진 명령어다. 즐겨라...
- Open problem : 효율적으로 hash slot N 에 있는 그 다음 keyf를 C에 물어봐라.(맞나? ^^; ask C the next key in hash slot N, efficiently.)
Re-sharding with 결함있는 노드들
- 노드들은 재분배(resharding)하는 동안에 실패 할 수 있다. 일반적으로 슬레이브 승격(?)이다.
- redis-trib 유틸리티는 시스템 관리자에 의해 실행된다. 이 유틸리티는 재분배(resharding)하는 동안 클러스터 설정을 지속적으로 검사하고, 잘못 되었다면 종료하거나 경고를 한다.
결함 허용
- 모든 노드들은 지속적으로 다른 노들에게 ping을 한다.
- 하나의 노드는 N 초 이상 접속불가능 할때, 아마도 결함이 있다고 다른 노드들에게 표시한다.
- 모든 PING과 PONG 패킷은 수다섹션(gossip section : 다른 노드들의 접속불가능 시간들과 어떤 노드에서 보내왔는지에 대한 정보)을 포함한다.
결함 허용 - 결함 노드들
- A는 마지막 PING 요청이 시간초과 됐을때, B에 결함이 있다고 추측을 한다. A는 다른 힌트 없이 어떤 조치도 취하지 않는다.
- C가 수다섹션(gosship section)을 통해 C 또한 B가 결험이 있다고, A에게 PONG을 보낸다.
- 여기서 A는 B가 접속이 되지 않는다고 표시하고 이 정보를 클러스터이 있는 다른 모든 노드들에게 알린다. 다른 모든 노드들은 B가 접속불능이라고 표시한다.
- 만약 B가 다시 정상화 되었을때, 처음으로 클러스터에 있는 아무런 노드에 PING을 날리고, 일시 멈춘 클라이언트들에게 좋은일이 아니라고, 즉시 종료를 통보합니다.
- 거대한 문제점이 발생한 후 클러스터에 복귀할 수 있는 유일한 방법은 직접 redis-trib을 이용하여 해결하는 것입니다.
Redis-trib - the Redis Cluster Manager
- 이것은 일단 당신이 N개의 빈 노드들을 시작하기 위해 새로운 클러스터를 설정하는데 사용 된다.
- 이것은 클러스터가 잘 작동할때 검사를 하기 위해 사용 됩니다. 그리고 클러스터가 계속 작동을 못할때, 단일 노드없이 Hash slots이 있는 것처럼 사용 된다.
- 이것은 클러스터에 신규 노드가 추가 될때나, 이미 존재하는 마스터 노드에 슬레이브를 추가 할때 또는 우리가 일부 hash slots을 다른 노드들로 재분배(re-sharding) 하기 위한 빈 노드들을 만들때 사용 된다.
이것보다 더 복잡하다.
- 20분짜리 발표에 맞지 않을 수 있는 상세한 정보들이 있다.
- Ping/Pong 패킷은 클러스터가 적절한 중지 후 재시작을 위한 충분한 정보를 포함한다. 그러나 시스템관리자는 CLUSTER MEET 명령어를 IP가 바꿨거나 기타 등등의 경우 노드에 확인할 때 사용한다.
- 모든 노드는 유일한 ID와 클러스터 설정 파일을 갖는다. 매시간 설정이 바뀌면 클러스터 설정 파일은 저장한다.
- 클러스터 설정 파일은 사용자에 의해 변경 될 수 없다.
- 주어진 노드 ID는 절대 바뀌지 않는다.
- 질문?