>데이터 베이스 >Redis >클러스터란 무엇입니까? Redis에 클러스터가 필요한 이유는 무엇입니까?

클러스터란 무엇입니까? Redis에 클러스터가 필요한 이유는 무엇입니까?

青灯夜游
青灯夜游앞으로
2021-09-24 19:55:423230검색

클러스터란 무엇인가요? Redis에 클러스터가 필요한 이유는 무엇입니까? 이 기사에서는 클러스터 클러스터에 대해 자세히 알아보고 클러스터 클러스터가 지원할 수 있는 데이터 양에 대해 설명하겠습니다. 도움이 되기를 바랍니다.

클러스터란 무엇입니까? Redis에 클러스터가 필요한 이유는 무엇입니까?

이 문서에서는 노드, 슬롯 할당, 명령 실행, 재샤딩, 조정, 장애 조치 및 메시지와 같은 클러스터의 다양한 측면에 대한 심층적인 해체를 제공합니다. [관련 추천: Redis 동영상 튜토리얼]

Redis 集群原理总览

클러스터가 무엇인지 익히는 것이 목적입니다. 클러스터 샤딩 원칙, 클라이언트 포지셔닝 데이터 원칙, 장애 조치, 마스터 선택, 클러스터를 사용할 시나리오, 클러스터 배포 방법... [toc]

클러스터가 필요한 이유

65 형제: Ma 형제님, 말씀하신 대로 Sentinel Cluster를 사용하여 자동 장애 조치를 실현했기 때문에 마침내 여자친구와 행복할 수 있었고 Redis 가동 중지 시간도 두렵지 않습니다. .밤늦게 다운됐어요.

하지만 최근에 심각한 문제에 직면했습니다. Redis는 20GB의 메모리를 차지하는 800만 개의 키-값 쌍을 저장해야 합니다.

배포를 위해 32G 메모리 호스트를 사용했는데 Redis 응답이 가끔 매우 느렸습니다. INFO 명령을 사용하여 최신 포크에 시간이 걸렸는지 확인했는데(가장 최근 포크에는 시간이 걸렸습니다) 특히 높았습니다.

주로 Redis RDB 지속성 메커니즘으로 인해 발생합니다. Redis는 RDB 지속성 작업을 완료하기 위해 하위 프로세스를 포크합니다. 포크 실행에 걸리는 시간은 Redis 데이터의 양과 긍정적인 관련이 있습니다.

그리고 Fork가 실행되면 메인 스레드가 차단됩니다. 데이터 양이 많기 때문에 메인 스레드가 너무 오랫동안 차단되므로 Redis 응답이 느린 것으로 보입니다.

65 형: 사업 규모가 확장되면서 데이터의 양이 점점 늘어나고 있어요. 마스터-슬레이브 아키텍처를 업그레이드할 때 단일 인스턴스의 하드웨어를 확장하기 어렵고, 많은 양의 데이터를 저장하면 응답 속도가 느려지는 문제를 해결할 방법이 있습니까?

대량의 데이터를 저장하기 위해 대용량 메모리 호스트를 사용하는 것 외에도 슬라이싱 클러스터를 사용할 수도 있습니다. "모두가 추가하는 것이 불꽃을 더 밝게 만든다"라는 속담처럼, 하나의 기계가 모든 데이터를 저장할 수 없다면 여러 기계가 이를 공유해야 합니다.

Redis Cluster 클러스터를 사용하면 대용량 데이터 저장으로 인한 다양한 속도 저하 문제를 주로 해결하고 수평 확장도 용이하게 합니다.

두 가지 솔루션은 Redis 데이터 증가에 대한 두 가지 확장 솔루션인 수직 확장(scale up)과 수평 확장(scale out)에 해당합니다.

  1. 수직 확장: 메모리 용량, 디스크 용량 증가, 더욱 강력한 CPU 사용 등 단일 Redis의 하드웨어 구성을 업그레이드합니다.
  2. 수평적 확장: Redis 인스턴스 수를 수평적으로 늘리고, 각 노드가 데이터의 일부를 담당합니다.

예를 들어 24GB의 메모리와 150GB의 디스크를 갖춘 서버 리소스가 필요한 경우 다음 두 가지 옵션이 있습니다.

클러스터란 무엇입니까? Redis에 클러스터가 필요한 이유는 무엇입니까?

수백만 또는 수천만 명의 사용자를 상대할 때 수평으로 확장 가능한 Redis 슬라이싱 클러스터 아주 좋은 선택이 될 것입니다.

65 형제: 이 두 가지 옵션의 장점과 단점이 무엇인가요?

  • 수직 확장 배포는 간단하지만, 데이터 양이 많고 지속성을 확보하기 위해 RDB를 사용하는 경우 차단 및 응답 속도 저하가 발생합니다. 게다가 하드웨어와 비용의 한계로 인해 1T 메모리로 확장하는 등 메모리 확장 비용도 너무 높다.
  • 수평 확장은 단일 인스턴스의 하드웨어 및 비용 제한에 대한 걱정 없이 확장을 용이하게 합니다. 그러나 클러스터를 분할하면 여러 인스턴스의 분산 관리 문제가 발생하므로 데이터를 여러 인스턴스에 합리적으로 배포하는 동시에 클라이언트가 인스턴스의 데이터에 올바르게 액세스할 수 있도록 하는 방법을 해결해야 합니다.
  • 클러스터란? Redis 클러스터는 분산형 데이터베이스 솔루션입니다. 클러스터는 샤딩("분할 정복 사고")을 통해 데이터를 관리하고 복제 및 장애 조치 기능을 제공합니다.

데이터는 16384개의 슬롯으로 나누어져 있으며, 각 노드는 슬롯의 일부를 담당합니다. 슬롯 정보는 각 노드에 저장됩니다.

그림과 같이 클러스터는 3개의 Redis 노드로 구성되어 있으며 각 노드는 전체 클러스터의 데이터 중 일부를 담당합니다.

세 개의 노드가 서로 연결되어 P2P 클러스터를 형성합니다. Gossip 프로토콜을 통해 서로 클러스터 정보를 교환합니다. 마지막으로 각 노드는 다른 노드의 슬롯 할당을 저장합니다. Gossip协议相互交互集群信息,最后每个节点都保存着其他节点的 slots 分配情况。

开篇寄语

技术不是万能的,程序员也不是最厉害的,一定要搞清楚,不要觉得「老子天下第一」。一旦有了这个意识,可能会耽误我们的成长。

技术是为了解决问题的,如果说一个技术不能解决问题,那这个技术就一文不值。

不要去炫技,没有意义。

集群安装

点击 -> 《Redis 6.X Cluster 集群搭建》查看

一个 Redis 集群通常由多个节点(node)组成,在刚开始的时候,每个节点都是相互独立的,它们都处于一个只包含自己的集群当中,要组建一个真正可工作的集群,我们必须将各个独立的节点连接起来,构成一个包含多个节点的集群。

连接各个节点的工作可以通过 CLUSTER MEET 命令完成:CLUSTER MEET <ip> <port></port></ip>

向一个节点 node 发送 CLUSTER MEET

오프닝 메시지

CLUSTER MEET기술은 전능하지 않고, 프로그래머는 가장 강력한 것이 아닙니다. 확실히 이해하고 '내가 세계 최고'라고 생각하지 마세요. . 우리가 이러한 인식을 갖게 되면 성장이 지연될 수 있습니다.

기술은 문제를 해결하는 것입니다. 기술이 문제를 해결할 수 없다면 이 기술은 가치가 없습니다.

실력을 과시하지 마세요. 의미가 없습니다.

클러스터 설치클릭 -> "Redis 6.X 클러스터 클러스터 구성" 보기

Redis 클러스터는 일반적으로 여러 노드로 구성됩니다. 처음에는 각 노드가 서로 독립적이며 자신만 포함하는 클러스터에 있습니다. 실제로 작동하는 클러스터를 형성하려면 독립 노드를 연결하여 여러 노드 클러스터를 포함하는 클러스터를 형성해야 합니다.

다양한 노드를 연결하는 작업은 CLUSTER MEET 명령( CLUSTER MEET <ip> <port></port></ip>)을 통해 완료할 수 있습니다.

CLUSTER MEET 명령을 노드에 전송하면 노드가 ip 및 포트로 지정된 노드와 핸드셰이크할 수 있습니다. 핸드셰이크가 성공하면 노드는 지정된 IP와 포트를 전송합니다. 현재 노드가 있는 클러스터에 노드가 추가됩니다.

노드가 다음과 같이 말한 것과 같습니다. "안녕하세요, ip = xx, 포트 = xx인 형제님, "코드 바이트" 기술 그룹에 가입하시겠습니까? 클러스터에 가입하면 다음과 같이 성장할 수 있는 방법을 찾을 수 있습니다. 위대한 스승님 팔로우" "Ma Ge Byte" 공개 계정이 "그룹에 가입하세요"라고 답했습니다. 형제라면 저와 함께 가세요! "

Redis Cluster

구축의 자세한 단계를 보려면 기사 왼쪽 하단의 "

원문 읽기

"를 클릭하거나 -> "
    Redis 6.X Cluster Cluster Building
  • "을 클릭하여 확인하세요. . Redis Cluster에 대한 자세한 내용은

    redis.io/topics/clus…

  • Cluster 구현 원리

  • 65를 참조하세요. Brother: 데이터를 슬라이싱한 후 데이터를 서로 다른 인스턴스에 배포해야 합니다. 데이터와 인스턴스?

Redis 3.0부터 슬라이싱 클러스터를 구현하기 위한 공식 Redis Cluster 솔루션이 제공되었습니다. 이 솔루션은 데이터와 인스턴스의 규칙을 구현합니다. Redis 클러스터 솔루션은 해시 슬롯(다음에는 슬롯이라고 부르겠습니다)을 사용하여 데이터와 인스턴스 간의 매핑 관계를 처리합니다.

"코드 바이트"를 따라 클러스터 구현 원칙의 탐구 여정에 들어가세요...

데이터를 여러 부분으로 나누어 서로 다른 인스턴스에 저장하세요

🎜클러스터의 전체 데이터베이스는 16384개의 슬롯(슬롯)으로 나누어져 있으며, 데이터베이스의 각 키는 16384개 슬롯 중 하나에 속하며 클러스터의 각 노드는 0개에서 최대 16384개 슬롯을 처리할 수 있습니다. 🎜🎜키 및 해시 슬롯 매핑 프로세스는 두 가지 주요 단계로 나눌 수 있습니다. 🎜🎜🎜🎜키-값 쌍의 키에 따라 CRC16 알고리즘을 사용하여 16비트 값을 계산합니다. -bit 값 16384 모듈로를 실행하고 키에 해당하는 해시 슬롯을 나타내는 0에서 16383 사이의 숫자를 얻습니다. 🎜🎜🎜🎜Cluster를 사용하면 키 문자열에 태그 표시를 삽입하여 태그가 있는 슬롯과 동일한 슬롯에 키를 강제로 걸 수 있습니다. 🎜🎜해시 슬롯과 Redis 인스턴스 매핑🎜🎜🎜65 Brother: 해시 슬롯은 Redis 인스턴스에 어떻게 매핑되나요? 🎜

클러스터 배포 샘플에서 클러스터 생성을 통해 생성된 Redis는 클러스터 인스턴스에 16384개의 해시 슬롯을 자동으로 균등하게 배포합니다(예: N 노드 및 각 노드의 해시 슬롯 슬롯 수 = 16384). /N. cluster create 创建,Redis 会自动将 16384 个 哈希槽平均分布在集群实例上,比如 N 个节点,每个节点上的哈希槽数 = 16384 / N 个。

除此之外,可以通过 CLUSTER MEET 命令将 7000、7001、7002 三个节点连在一个集群,但是集群目前依然处于下线状态,因为三个实例都没有处理任何哈希槽。

可以使用 cluster addslots 命令,指定每个实例上的哈希槽个数。

65 哥:为啥要手动制定呢?

能者多劳嘛,加入集群中的 Redis 实例配置不一样,如果承担一样的压力,对于垃圾机器来说就太难了,让牛逼的机器多支持一点。

三个实例的集群,通过下面的指令为每个实例分配哈希槽:实例 1负责 0 ~ 5460 哈希槽,实例 2 负责 5461~10922 哈希槽,实例 3 负责 10923 ~ 16383 哈希槽。

redis-cli -h 172.16.19.1 –p 6379 cluster addslots 0,5460
redis-cli -h 172.16.19.2 –p 6379 cluster addslots 5461,10922
redis-cli -h 172.16.19.3 –p 6379 cluster addslots 10923,16383

键值对数据、哈希槽、Redis 实例之间的映射关系如下:

클러스터란 무엇입니까? Redis에 클러스터가 필요한 이유는 무엇입니까?

Redis 键值对的 key 「码哥字节」「牛逼」经过 CRC16 计算后再对哈希槽总个数 16394 取模,模数结果分别映射到实例 1 与实例 2 上。

切记,当 16384 个槽都分配完全,Redis 集群才能正常工作

复制与故障转移

65 哥:Redis 集群如何实现高可用呢?Master 与 Slave 还是读写分离么?

Master 用于处理槽,Slave 节点则通过《Redis 主从架构数据同步》方式同步主节点数据。

当 Master 下线,Slave 代替主节点继续处理请求。主从节点之间并没有读写分离, Slave 只用作 Master 宕机的高可用备份。

Redis Cluster 可以为每个主节点设置若干个从节点,单主节点故障时,集群会自动将其中某个从节点提升为主节点。

如果某个主节点没有从节点,那么当它发生故障时,集群将完全处于不可用状态

不过 Redis 也提供了一个参数cluster-require-full-coverage可以允许部分节点故障,其它节点还可以继续提供对外访问。

比如 7000 主节点宕机,作为 slave 的 7003 成为 Master 节点继续提供服务。当下线的节点 7000 重新上线,它将成为当前 70003 的从节点。

故障检测

65 哥:在《Redis 高可用篇:Sentinel 哨兵集群原理》我知道哨兵通过监控、自动切换主库、通知客户端实现故障自动切换,Cluster 又如何实现故障自动转移呢?

一个节点认为某个节点失联了并不代表所有的节点都认为它失联了。只有当大多数负责处理 slot 节点都认定了某个节点下线了,集群才认为该节点需要进行主从切换。

Redis 集群节点采用 Gossip 协议来广播自己的状态以及自己对整个集群认知的改变。比如一个节点发现某个节点失联了 (PFail),它会将这条信息向整个集群广播,其它节点也就可以收到这点失联信息。

关于 Gossip또한 CLUSTER MEET 명령을 사용하여 세 노드 7000, 7001, 7002를 클러스터에 연결할 수 있지만 세 인스턴스 중 어느 것도 해시를 처리하지 않기 때문에 클러스터는 여전히 오프라인 상태입니다. 슬롯.

cluster addedlots 명령을 사용하여 각 인스턴스의 해시 슬롯 수를 지정할 수 있습니다.

65 형제: 왜 수동으로 공식화해야 합니까? 🎜🎜🎜능력이 있는 사람은 더 열심히 일해야 합니다. 클러스터에 추가된 Redis 인스턴스의 구성이 서로 다르면 가비지 머신이 더 많은 것을 지원하기가 너무 어려울 것입니다. 🎜🎜3개의 인스턴스로 구성된 클러스터의 경우 다음 지침에 따라 각 인스턴스에 해시 슬롯을 할당합니다. 인스턴스 1은 0 ~ 5460 해시 슬롯을 담당하고, 인스턴스 2는 0~5460개의 해시 슬롯을 담당합니다. 5461~10922 해시 슬롯, 인스턴스 3은 해시 슬롯 10923~16383을 담당합니다. 🎜
GET 公众号:码哥字节
(error) MOVED 16330 172.17.18.2:6379
🎜키-값 쌍 데이터, 해시 슬롯 및 Redis 인스턴스 간의 매핑 관계는 다음과 같습니다. 🎜🎜데이터, 슬롯 ​​및 인스턴스 매핑🎜🎜Redis 키-값 쌍 키 "codebytes" CRC16 이후 계산 시, 해시 슬롯 16394의 총 수는 모듈로 계산되고 모듈러스 결과는 각각 인스턴스 1과 인스턴스 2에 매핑됩니다. 🎜🎜Redis 클러스터는 16384개의 슬롯이 모두 완전히 할당된 경우에만 정상적으로 작동할 수 있다는 점을 기억하세요. 🎜

복제 및 장애 조치

🎜65 Brother: Redis 클러스터는 어떻게 고가용성을 달성합니까? 마스터와 슬레이브는 여전히 읽기와 쓰기에서 분리되어 있습니까? 🎜🎜🎜Master는 슬롯 처리에 사용되며, Slave 노드는 "Redis 마스터-슬레이브 아키텍처 데이터 동기화🎜 》마스터 노드 데이터를 동기화하는 방법. 🎜🎜마스터가 오프라인이 되어도 마스터 노드 대신 슬레이브가 계속해서 요청을 처리합니다. 마스터 노드와 슬레이브 노드 사이에는 읽기-쓰기 분리가 없으며, 슬레이브는 마스터 장애에 대한 고가용성 백업으로만 사용됩니다. 🎜🎜Redis 클러스터는 각 마스터 노드에 대해 여러 개의 슬레이브 노드를 설정할 수 있습니다. 단일 마스터 노드에 장애가 발생하면 클러스터는 슬레이브 노드 중 하나를 마스터 노드로 자동 승격합니다. 🎜🎜마스터 노드에 슬레이브 노드가 없는 경우 실패하면 클러스터를 완전히 사용할 수 없게 됩니다. 🎜🎜그러나 Redis는 일부 노드가 실패하고 다른 노드는 계속 외부 액세스를 제공할 수 있도록 허용하는 cluster-require-full-coverage 매개변수도 제공합니다. 🎜🎜예를 들어 마스터 노드 7000이 다운되면 슬레이브 7003이 마스터 노드가 되어 계속해서 서비스를 제공합니다. 오프라인 노드 7000이 다시 온라인으로 전환되면 현재 70003의 슬레이브 노드가 됩니다. 🎜

오류 감지

🎜65 형제: "Redis 고가용성: Sentinel 클러스터 원리 🎜" Sentinel은 모니터링, 기본 데이터베이스 자동 전환, 클라이언트 알림을 통해 자동 장애 조치를 구현하는 것으로 알고 있습니다. 클러스터는 자동 장애 조치를 어떻게 구현하나요? 🎜🎜🎜한 노드가 특정 노드가 연결이 끊어졌다고 생각한다고 해서 모든 노드가 연결이 끊어졌다고 생각하는 것은 아닙니다. 슬롯 처리를 담당하는 대부분의 노드가 노드가 오프라인이라고 판단한 경우에만 클러스터는 해당 노드가 마스터-슬레이브 전환을 수행해야 한다고 간주합니다. 🎜🎜Redis 클러스터 노드는 Gossip 프로토콜을 사용하여 자신의 상태와 전체 클러스터에 대한 지식의 변화를 브로드캐스트합니다. 예를 들어, 노드가 특정 노드의 손실(PFail)을 발견하면 이 정보를 전체 클러스터에 브로드캐스트하고 다른 노드도 이 연결 손실 정보를 수신할 수 있습니다. 🎜🎜Gossip 프로토콜에 대해 Wukong 형제의 기사를 읽을 수 있습니다: "🎜바이러스 침입은 전적으로 배포에 달려 있습니다🎜"🎜🎜노드가 노드로부터의 연결 해제 횟수(PFail Count)를 수신하는 경우 클러스터의 대부분에 도달하면 해당 노드를 오프라인(실패)으로 확인된 것으로 표시한 다음 이를 전체 클러스터에 브로드캐스트하여 다른 노드도 해당 노드가 오프라인이라는 사실을 수락하고 즉시 제어권을 갖도록 할 수 있습니다. 손실된 노드에서 전환합니다. 🎜

Failover

슬레이브가 마스터 노드가 오프라인 상태에 들어간 것을 발견하면 슬레이브 노드는 오프라인 마스터 노드에 대한 장애 조치를 시작합니다.

  • 오프라인 마스터 및 노드 슬레이브 노드 목록에서 노드를 선택하여 새로운 마스터 노드가 됩니다.

  • 새 마스터 노드는 오프라인 마스터 노드에 대한 모든 슬롯 할당을 취소하고 이러한 슬롯을 자신에게 할당합니다.

  • 새 마스터 노드는 PONG 메시지를 클러스터에 브로드캐스트합니다. 이 PONG 메시지를 통해 클러스터의 다른 노드는 이 노드가 슬레이브 노드에서 마스터 노드로 변경되었으며 이 마스터 노드가 클러스터를 인수했음을 즉시 알 수 있습니다. 원래 마스터 노드가 수행한 작업입니다. 오프라인 노드가 처리를 담당하는 슬롯입니다.

  • 새 마스터 노드는 처리 슬롯과 관련된 명령 요청을 받기 시작하고 장애 조치가 완료됩니다.

마스터 선출 과정

65 형님: 새로운 마스터 노드는 어떻게 선출되나요?

  • 클러스터 +1의 구성 에포크는 초기 값이 0인 자체 시간 카운터이며 장애 조치가 수행될 때마다 +1이 됩니다.

  • 마스터 노드가 오프라인임을 감지한 슬레이브 노드는 CLUSTERMSG_TYPE_FAILOVER_AUTH_REQUEST 메시지를 클러스터에 브로드캐스트하며, 이 메시지를 수신하고 이 슬레이브 노드에 투표할 투표 권한이 있는 모든 마스터 노드를 요구합니다. CLUSTERMSG_TYPE_FAILOVER_AUTH_REQUEST消息,要求所有收到这条消息、并且具有投票权的主节点向这个从节点投票。

  • 这个主节点尚未投票给其他从节点,那么主节点将向要求投票的从节点返回一条CLUSTERMSG_TYPE_FAILOVER_AUTH_ACK消息,表示这个主节点支持从节点成为新的主节点。

  • 参与选举的从节点都会接收CLUSTERMSG_TYPE_FAILOVER_AUTH_ACK

  • 이 마스터 노드는 아직 다른 슬레이브 노드에 투표하지 않은 경우 마스터 노드는 투표가 필요한 슬레이브 노드에 CLUSTERMSG_TYPE_FAILOVER_AUTH_ACK 메시지를 반환하여 이 마스터 노드가 슬레이브 노드를 지원한다는 것을 나타냅니다. 새로운 마스터 노드가 됩니다.

선거에 참여하는 모든 슬레이브 노드는 CLUSTERMSG_TYPE_FAILOVER_AUTH_ACK 메시지를 받게 됩니다. 수집된 투표 수 >= (N/2) + 1 지원이면 슬레이브 노드가 새 마스터로 선출됩니다. 마디.

클러스터란 무엇입니까? Redis에 클러스터가 필요한 이유는 무엇입니까?구성 에포크에서 슬레이브 노드가 충분한 지지 투표를 수집할 수 없는 경우 클러스터는 새로운 구성 에포크에 들어가고 새 마스터 노드가 선출될 때까지 선거가 다시 개최됩니다.

Sentinel과 유사하게 둘 다 Raft 알고리즘을 기반으로 구현됩니다. 프로세스는 그림과 같습니다.

키-값 쌍과 인스턴스 간의 관계를 저장하기 위해 테이블을 사용하는 것이 가능합니까?

65 형제님, 테스트해 보겠습니다. "Redis 클러스터 솔루션은 해시 슬롯을 통해 다양한 인스턴스에 키-값 쌍을 할당합니다. 이 프로세스에는 키-값 쌍의 키에 대한 CRC 계산과 총 해시 수의 모듈로가 필요합니다. 테이블을 사용하여 키-값 쌍과 인스턴스 간의 대응 관계를 직접 기록하는 경우(예: 키-값 쌍 1은 인스턴스 2에 있고 키-값 쌍 2는 인스턴스 1에 있음) , 키와 해시 슬롯 간의 대응 관계를 계산할 필요가 없습니다. Redis는 왜 이를 수행하지 않습니까? "

글로벌 테이블 레코드를 사용하는 경우 키-값 쌍 간의 관계가 인스턴스가 변경되면(재샤딩, 인스턴스 증가 또는 감소) 표면을 수정해야 합니다. 단일 스레드 작업인 경우 모든 작업을 직렬화해야 하며 성능이 너무 느려집니다.

멀티 스레딩에는 잠금이 포함됩니다. 또한 키-값 쌍 데이터의 양이 매우 클 경우 키-값 쌍과 인스턴스 간의 관계에 대한 테이블 데이터를 저장하는 데 필요한 저장 공간도 매우 커집니다.

해시 슬롯 계산의 경우 해시 슬롯과 인스턴스 시간 간의 관계도 기록해야 하지만 해시 슬롯 수는 16384개로 훨씬 적고 오버헤드도 매우 작습니다.

클라이언트는 데이터가 있는 인스턴스를 어떻게 찾나요?

65 Brother: 클라이언트는 액세스된 데이터가 배포되는 인스턴스를 어떻게 결정하나요?

Redis 인스턴스는 해시 슬롯 정보를 Gossip 프로토콜을 통해 클러스터의 다른 인스턴스로 전송하여 해시 슬롯 할당 정보의 확산을 실현합니다.

이런 방식으로 클러스터의 각 인스턴스는 모든 해시 슬롯과 인스턴스 간의 매핑 관계 정보를 갖게 됩니다.

데이터를 분할할 때 키는 CRC16을 통해 값으로 계산된 다음 해당 슬롯을 얻기 위해 모듈로 16384를 얻습니다. 이 계산 작업은 클라이언트에 요청을 보낼 때 실행될 수 있습니다.

Redis 客户端定位数据所在节点단, 슬롯을 찾은 후에는 슬롯이 위치한 Redis 인스턴스를 추가로 찾아야 합니다.

클라이언트가 임의의 인스턴스에 연결되면 인스턴스는 해시 슬롯과 인스턴스 간의 매핑 관계로 클라이언트에 응답하고, 클라이언트는 해시 슬롯과 인스턴스 간의 매핑 정보를 로컬로 캐시합니다.

클라이언트가 요청하면 해당 키에 해당하는 해시 슬롯을 계산하고, 로컬에 캐시된 해시 슬롯 인스턴스 매핑 정보를 통해 데이터가 위치한 인스턴스를 찾아 해당 인스턴스로 요청을 보냅니다.

🎜🎜🎜해시 슬롯 재배포🎜🎜🎜65 형제: 새 인스턴스나 로드 밸런싱 재배포로 인해 해시 슬롯과 인스턴스 간의 매핑 관계가 변경되면 어떻게 해야 하나요? 🎜

集群中的实例通过 Gossip 协议互相传递消息获取最新的哈希槽分配信息,但是,客户端无法感知。

Redis Cluster 提供了重定向机制:客户端将请求发送到实例上,这个实例没有相应的数据,该 Redis 实例会告诉客户端将请求发送到其他的实例上

65 哥:Redis 如何告知客户端重定向访问新实例呢?

分为两种情况:MOVED 错误、ASK 错误

MOVED 错误

MOVED 错误(负载均衡,数据已经迁移到其他实例上):当客户端将一个键值对操作请求发送给某个实例,而这个键所在的槽并非由自己负责的时候,该实例会返回一个 MOVED 错误指引转向正在负责该槽的节点。

GET 公众号:码哥字节
(error) MOVED 16330 172.17.18.2:6379

该响应表示客户端请求的键值对所在的哈希槽 16330 迁移到了 172.17.18.2 这个实例上,端口是 6379。这样客户端就与 172.17.18.2:6379 建立连接,并发送 GET 请求。

同时,客户端还会更新本地缓存,将该 slot 与 Redis 实例对应关系更新正确

MOVED 指令

ASK 错误

65 哥:如果某个 slot 的数据比较多,部分迁移到新实例,还有一部分没有迁移咋办?

如果请求的 key 在当前节点找到就直接执行命令,否则时候就需要 ASK 错误响应了,槽部分迁移未完成的情况下,如果需要访问的 key 所在 Slot 正在从从 实例 1 迁移到 实例 2,实例 1 会返回客户端一条 ASK 报错信息:客户端请求的 key 所在的哈希槽正在迁移到实例 2 上,你先给实例 2 发送一个 ASKING 命令,接着发发送操作命令

GET 公众号:码哥字节
(error) ASK 16330 172.17.18.2:6379

比如客户端请求定位到 key = 「公众号:码哥字节」的槽 16330 在实例 172.17.18.1 上,节点 1 如果找得到就直接执行命令,否则响应 ASK 错误信息,并指引客户端转向正在迁移的目标节点 172.17.18.2。

ASK 错误

注意:ASK 错误指令并不会更新客户端缓存的哈希槽分配信息

所以客户端再次请求 Slot 16330 的数据,还是会先给 172.17.18.1 实例发送请求,只不过节点会响应 ASK 命令让客户端给新实例发送一次请求。

MOVED指令则更新客户端本地缓存,让后续指令都发往新实例。

集群可以设置多大?

65 哥:有了 Redis Cluster,再也不怕大数据量了,我可以无限水平拓展么?

答案是否定的,Redis 官方给的 Redis Cluster 的规模上线是 1000 个实例

65 哥:到底是什么限制了集群规模呢?

关键在于实例间的通信开销,Cluster 集群中的每个实例都保存所有哈希槽与实例对应关系信息(Slot 映射到节点的表),以及自身的状态信息。

在集群之间每个实例通过 Gossip协议传播节点的数据,Gossip 协议工作原理大概如下:

  1. 从集群中随机选择一些实例按照一定的频率发送 PING 消息发送给挑选出来的实例,用于检测实例状态以及交换彼此的信息。 PING 消息中封装了发送者自身的状态信息、部分其他实例的状态信息、Slot 与实例映射表信息。
  2. 实例接收到 PING 消息后,响应 PONG 消息,消息包含的信息跟 PING 消息一样。

集群之间通过 Gossip协议可以在一段时间之后每个实例都能获取其他所有实例的状态信息。

所以在有新节点加入,节点故障,Slot 映射变更都可以通过 PINGPONG 的消息传播完成集群状态在每个实例的传播同步。

Gossip 消息

发送的消息结构是 clusterMsgDataGossip结构体组成:

typedef struct {
    char nodename[CLUSTER_NAMELEN];  //40字节
    uint32_t ping_sent; //4字节
    uint32_t pong_received; //4字节
    char ip[NET_IP_STR_LEN]; //46字节
    uint16_t port;  //2字节
    uint16_t cport;  //2字节
    uint16_t flags;  //2字节
    uint32_t notused1; //4字节
} clusterMsgDataGossip;

所以每个实例发送一个 Gossip消息,就需要发送 104 字节。如果集群是 1000 个实例,那么每个实例发送一个 PING 消息则会占用 大约 10KB。

除此之外,实例间在传播 Slot 映射表的时候,每个消息还包含了 一个长度为 16384 bit 的 Bitmap

각 비트는 슬롯에 해당합니다. 값이 1이면 이 비트맵이 2KB를 차지하므로 PING 메시지는 약 12KB입니다. PING 消息大约 12KB。

PONGPING 消息一样,一发一回两个消息加起来就是 24 KB。集群规模的增加,心跳消息越来越多就会占据集群的网络通信带宽,降低了集群吞吐量。

实例的通信频率

65 哥:码哥,发送 PING 消息的频率也会影响集群带宽吧?

Redis Cluster 的实例启动后,默认会每秒从本地的实例列表中随机选出 5 个实例,再从这 5 个实例中找出一个最久没有收到 PING 消息的实例,把 PING 消息发送给该实例。

65 哥:随机选择 5 个,但是无法保证选中的是整个集群最久没有收到 PING 通信的实例,有的实例可能一直没有收到消息,导致他们维护的集群信息早就过期了,咋办呢?

这个问题问的好,Redis Cluster 的实例每 100 ms 就会扫描本地实例列表,当发现有实例最近一次收到 PONG 消息的时间 > cluster-node-timeout / 2。那么就立刻给这个实例发送 PING 消息,更新这个节点的集群状态信息。

当集群规模变大,就会进一步导致实例间网络通信延迟怎加。可能会引起更多的 PING 消息频繁发送。

降低实例间的通信开销

  • 每个实例每秒发送一条 PING消息,降低这个频率可能会导致集群每个实例的状态信息无法及时传播。
  • 每 100 ms 检测实例 PONG消息接收是否超过 cluster-node-timeout / 2,这个是 Redis 实例默认的周期性检测任务频率,我们不会轻易修改。

所以,只能修改 cluster-node-timeout的值:集群中判断实例是否故障的心跳时间,默认 15 S。

所以,为了避免过多的心跳消息占用集群宽带,将 cluster-node-timeout调成 20 秒或者 30 秒,这样 PONG 消息接收超时的情况就会缓解。

但是,也不能设置的太大。都则就会导致实例发生故障了,却要等待 cluster-node-timeout时长才能检测出这个故障,影响集群正常服务、

总结

  • 哨兵集群实现故障自动转移,但是当数据量过大导致生成 RDB 时间过长。而 Fork 执行的时候会阻塞主线程,由于数据量过大导致阻塞主线程过长,所以出现了 Redis 响应慢的表象。
  • 使用 Redis Cluster 集群,主要解决了大数据量存储导致的各种慢问题,同时也便于横向拓展。在面向百万、千万级别的用户规模时,横向扩展的 Redis 切片集群会是一个非常好的选择。
  • 集群的整个数据库被分为 16384 个槽(slot),数据库中的每个键都属于这 16384 个槽的其中一个,集群中的每个节点可以处理 0 个或最多 16384 个槽。
  • Redis 集群节点采用 Gossip 协议来广播自己的状态以及自己对整个集群认知的改变。
  • 客户端连接到集群候任何一个实例后,实例会将哈希槽与实例映射信息发送给客户端,客户端将信息保存,用于将 key 定位到对应的节点。
  • 集群并不能无限增加,由于集群通过 Gossip协议传播集群实例信息,所以通信频率是限制集群大小的主要原因,主要可以通过修改 cluster-node-timeout
  • PONGPING 메시지와 동일하며 전송 및 반환된 두 메시지의 합은 24KB입니다. 클러스터 크기가 증가함에 따라 점점 더 많은 하트비트 메시지가 클러스터의 네트워크 통신 대역폭을 차지하고 클러스터 처리량이 감소합니다.

인스턴스 통신 빈도

65 형제: Ma 형제님, PING 메시지 전송 빈도도 클러스터 대역폭에 영향을 미치죠?

Redis Cluster 인스턴스가 시작된 후 기본적으로 1초마다 로컬 인스턴스 목록에서 무작위로 5개의 인스턴스가 선택되며, 가장 오랫동안 PING 메시지를 받지 못한 인스턴스는 다음에서 검색됩니다. 이 5개의 인스턴스에 PING 메시지를 보냅니다.
🎜65 Brother: 5개를 무작위로 선택하세요. 하지만 선택한 인스턴스가 전체 클러스터에서 가장 오랫동안 PING 통신을 수신하지 못한 인스턴스가 될 것이라는 보장은 없습니다. 오래 전에 만료되도록 유지하는 클러스터 정보입니다. 🎜
🎜좋은 질문입니다. Redis 클러스터 인스턴스는 100ms마다 로컬 인스턴스 목록을 검색합니다. 인스턴스가 마지막으로 PONG 메시지를 수신한 시간은 다음과 같습니다. > 클러스터-노드-시간 초과/2. 그런 다음 즉시 이 인스턴스에 PING 메시지를 보내 이 노드의 클러스터 상태 정보를 업데이트합니다. 🎜🎜클러스터 크기가 커지면 인스턴스 간 네트워크 통신 지연이 더욱 늘어납니다. 더 많은 PING 메시지가 자주 전송될 수 있습니다. 🎜

인스턴스 간 통신 오버헤드 감소

위 내용은 클러스터란 무엇입니까? Redis에 클러스터가 필요한 이유는 무엇입니까?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
이 기사는 juejin.cn에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제