1. What is Redis Cluster

Redis Cluster는 Redis에서 제공하는 Replication 및 Sharding 기법입니다. 그림은 Redis Cluster 구성 시 구조를 나타냅니다.

  • Cluster는 Data를 여러 Node에 자동으로 분배합니다.
  • 일부 Node들이 에러가 발생하여 다른 Cluster들과 통신이 불가능해도 운영을 계속 할 수 있습니다.

Cluster Multi Master-slave

Redis Cluster는 Multi-master, Multi-slave 구조를 가지며 각 Redis는 Master 또는 Slave로 동작합니다. 각 Master는 Hash Slot이라는 Data 저장구역을 다른 Master와 나누어 소유합니다. Hash Slot은 0부터 16384까지의 주소를 가지고 있습니다. 그림은 각 Master가 Hash Slot을 3개로 균등하게 분할해서 구성한 모습입니다. Data가 이용할 Hash Slot은 Data의 Key를 Hashing한 결과값을 이용합니다. Hashing은 CRC16 및 Moduler 연산자를 이용하여 Data가 각 Hash Slot에 균등하게 배분되도록 합니다. 따라서 Data는 각 Master의 Hash Slot의 크기에 비례하여 Data를 저장하게 됩니다.

각 Master에 할당한 Hash Slot은 Redis 관리자에 의해서 동적으로 변경이 가능합니다. 따라서 동적으로 Master를 추가하거나 제거하는것도 가능합니다. 각 Master는 다수의 Slave를 가질 수 있습니다. 그림에서는 각 Master가 하나의 Slave를 갖고 있습니다. Master와 Slave사이의 Replication은 Redis Master-slave 구성과 동일하게 Async 방식으로 이루어집니다. 따라서 Slave도 동적으로 자유롭게 추가하거나 제거하는것이 가능합니다.

Master Redis가 죽을경우 죽은 Master의 Slave Redis는 gossip Protocol을 통해서 Master의 죽음을 파악한뒤 스스로 Master로 승격하여 Master를 대신합니다. 그 후 죽은 Master가 살아나서 동작하는 경우 스스로 Slave로 강등하여 동작합니다. Master와 Slave사이의 Replication은 Async 방식으로 이루어지기 때문에 Master의 죽음은 Master와 Slave 사이의 Data 정합성을 깰 수 있습니다. 깨진 Data 정합성으로 인해서 Master와 Slave 사이의 Data 충돌이 발생하는 경우 무조건 나중에 Master가 된 Data를 기준으로 정합성을 맞춥니다.

2. Cluster TCP port

Cluster를 구성하는 각 Redis는 다른 모든 Redis들과 직접 연결하여 gossip Protocol을 통해 통신합니다. gossip Protocol을 통해서 각 Redis는 redis 상태 정보를 교환합니다. Cluster Client 또한 Cluster를 구성하는 모든 Redis와 직접 연결하여 Data를 주고 받습니다.

따라서 모든 redis cluster node들은 2개의 TCP connection port가 필요합니다. 일반적으로 redis는 TCP 포트Cluster Client Port: 6379를 client를 위해 사용하며 여기에 10000을 더해Cluster bus Port:16379를 생성합니다.

Cluster Bus Port

  • 자체적인 binary protocol을 통해 node-to-node 통신을 합니다.
  • failure detection, configuration update, failover authorization등을 수행합니다.
  • 사용자들은 cluster bus와 통신할 필요가 없지만, Redis cluster가 node들과의 통신하기 위해 방화벽에 해당 포트를 등록해야 합니다.

3. Cluster Client

  1. Cluster Client는 Redis Cluster와 처음 연결될 때 Redis Cluster를 구성하는 각 Redis의 상태 정보(IP, Port, Master/Slave Mode, 할당된 Hash Slot 등)를 얻어옵니다.
  2. Cluster Client는 상태 정보를 바탕으로 Redis Cluster를 구성하는 모든 Redis와 연결을 합니다.
  3. Cluster Client는 Data의 key를 바탕으로 Data가 Read/Write 될 HashSlot을 직접 계산합니다.
  4. Cluster Client는 Hash Slot이 할당 된 Redis에게 직접 Read/Write를 수행합니다.

Hashslot의 배치가 변경된 경우

  1. Hashslot의 배치가 바뀌어 Cluster Client가 Read/Write 요청을 잘못된 Redis에게 전달합니다.
  2. 요청을 받은 Redis는 요청을 처리할 수 있는 Redis의 접속 정보 및 MOVED 명령어를 전달하여 요청을 Redirection 합니다.
  3. Cluster Client는 MOVED 명령어와 함께 온 접속 정보를 바탕으로 요청을 처리할 수 있는 Redis에게 다시 요청을 전달합니다.

예를들어 Slave Redis에게 Write 요청을 보내면 Slave Redis는 해당 요청을 처리 할 수 있는 Master Redis의 정보를 Cluster Client에게 넘겨줍니다. 일반적으로 Cluster Client는 MOVED 명령어를 받으면 Cluster로부터 Cluster 상태 정보를 다시 받아 Hashslot 및 Redis 접속 정보를 갱신합니다. 이처럼 Cluster Client는 Redis Cluster로부터 얻은 상태 정보 및 MOVED 명령어를 처리 할 수 있어야하기 때문에, 기존의 Redis Master-slave Library를 그대로 이용하면 안되고 Redis Cluster를 위한 Library를 이용해야한다.

일반적으로 Redis Cluster의 Slave Redis는 자신이 처리 할 수 있는 Read 요청을 받아도 자신의 Master에게 해당 Read 요청을 Redirection 합니다. 오직 READONLY 명령어를 통해서 Read Mode로 진입한 Client으로부터 오는 Read 요청만 Slave Redis에서 처리할 수 있습니다.

4. Cluster Proxy

필요성

위에서 언급한것 처럼 Redis Cluster의 Cluster Client는 Cluster를 구성하는 모든 Redis와 Network로 직접 연결되어 있어야 한다는 특징을 갖고 있습니다. 즉 Redis Cluster의 각 Redis는 Cluster Client를 위한 End-point를 반드시 하나이상 갖고 있어야 합니다. 이러한 특징 때문에 Cluster를 구성하는 Redis의 개수 또는 Cluster Client의 개수가 늘어날수록 Network Connection은 기하급수적으로 늘어납니다. 또한 Redis Master-slave의 Client에게 Master, Slave 2개의 End-point만을 제공하던 Network 환경에 Redis Cluster 구성을 힘들게하는 요인이 됩니다. 이러한 문제점들을 해결하기 위해서는 Cluster Proxy를 이용해야 합니다.

Cluster Proxy

Cluster Proxy는 Proxy Client에게 일정한 End-point를 제공합니다. Cluster Proxy에는 corvus, predixy 같은 Application이 있습니다. Cluster Proxy는 요청 Redirection 같은 Redis Cluster만을 위한 추가적인 동작이 필요하기 때문에 HAProxy같은 범용 Proxy를 Cluster Proxy로 이용하지 못합니다. Redis Master-slave의 HAProxy 처럼 다수의 Cluster Proxy를 L4 Load Balancer 및 VRRP를 이용하여 Cluster Proxy의 HA를 보장하도록 구성하는 것이 좋습니다.


References