이 기사에서는 클러스터 관련 문제를 주로 소개하는 Redis 관련 지식을 제공합니다. Redis 클러스터는 분산 데이터베이스 솔루션으로, 샤딩을 통해 데이터를 공유하고 복제 및 전송 기능을 제공하는 데 도움이 되기를 바랍니다. 모든 사람.
추천 학습: Redis 학습 튜토리얼
여러 Redis 고가용성 솔루션. 포함: "마스터-슬레이브 모드", "센티넬 메커니즘" 및 "센티넬 클러스터".
Redis는 가장 단순한 독립형 버전에서 데이터 지속성, 마스터-슬레이브 다중 복사본, 센티널 클러스터로 발전했습니다. 이러한 최적화를 통해 성능과 안정성이 더욱 높아졌습니다.
그러나 시간이 지남에 따라 회사의 사업 규모는 폭발적으로 성장했습니다. 현재 아키텍처 모델이 여전히 그렇게 많은 트래픽을 감당할 수 있을까요?
예를 들어 다음과 같은 요구 사항이 있습니다. Redis를 사용하여 5천만
개의 키-값 쌍을 저장하고 각 키-값 쌍은 약 512B
이므로 빠르게 배포할 수 있습니다. 외부 서비스를 제공하고 클라우드 호스트를 사용하여 Redis 인스턴스를 실행하는 경우 클라우드 호스트의 메모리 용량을 선택하는 방법은 무엇입니까? 5000 万
个键值对,每个键值对大约是 512B
,为了能快速部署并对外提供服务,我们采用云主机来运行 Redis 实例,那么,该如何选择云主机的内存容量呢?
通过计算,这些键值对所占的内存空间大约是 25GB(5000 万 *512B)。
想到的第一个方案就是:选择一台 32GB 内存的云主机来部署 Redis。因为 32GB 的内存能保存所有数据,而且还留有 7GB,可以保证系统的正常运行。
同时,还采用 RDB 对数据做持久化,以确保 Redis 实例故障后,还能从 RDB 恢复数据。
但是,在使用的过程中会发现,Redis 的响应有时会非常慢。通过 INFO命令
查看 Redis 的latest_fork_usec
指标值(表示最近一次 fork 的耗时),结果发现这个指标值特别高。
这跟 Redis 的持久化机制有关系。
在使用 RDB 进行持久化时,Redis 会 fork
子进程来完成,fork
操作的用时和 Redis 的数据量是正相关的,而 fork
在执行时会阻塞主线程。数据量越大,fork 操作造成的主线程阻塞的时间越长。
所以,在使用 RDB
对 25GB 的数据进行持久化时,数据量较大,后台运行的子进程在 fork
创建时阻塞了主线程,于是就导致 Redis 响应变慢了。
显然这个方案是不可行的,我们必须要寻找其他的方案。
为了保存大量数据,我们一般有两种方法:「纵向扩展」和「横向扩展」:
首先,「纵向扩展」的好处是,实施起来简单、直接。不过,这个方案也面临两个潜在的问题。
fork
子进程时就可能会阻塞。与「纵向扩展」相比,「横向扩展」是一个扩展性更好的方案。这是因为,要想保存更多的数据,采用这种方案的话,只用增加 Redis 的实例个数就行了,不用担心单个实例的硬件和成本限制。
Redis 集群就是基于「横向扩展」实现的 ,通过启动多个 Redis 实例组成一个集群,然后按照一定的规则,把收到的数据划分成多份,每一份用一个实例来保存。
Redis 集群是一种分布式数据库方案,集群通过分片
(sharding
,也可以叫切片
INFO 명령어
를 이용하여 Redis의 latest_fork_usec
지표 값(최근 포크에 소요된 시간)을 확인한 결과 이 지표 값이 유난히 높은 것으로 나타났다. 🎜🎜이것은 Redis의 지속성 메커니즘과 관련이 있습니다. 🎜🎜지속성을 위해 RDB를 사용하는 경우 Redis는 작업을 완료하기 위해 fork
합니다. fork
작업 시간은 양과 정비례합니다. Redis의 데이터 및 fork
는 실행 중에 기본 스레드를 차단합니다. 데이터 양이 많을수록 포크 작업으로 인해 메인 스레드가 차단되는 시간이 길어집니다. 🎜🎜그래서 RDB
를 사용하여 25GB의 데이터를 유지하는 경우 데이터의 양이 많고 fork
시 백그라운드에서 실행 중인 하위 프로세스가 차단됩니다. 기본 스레드로 인해 Redis 응답이 느려집니다. 🎜🎜분명히 이 솔루션은 실현 가능하지 않으며 다른 솔루션을 찾아야 합니다. 🎜fork
할 때 메인 스레드가 차단될 수 있다는 것입니다. 🎜🎜두 번째 질문:수직 확장은 하드웨어와 비용으로 인해 제한됩니다. 결국 메모리를 32GB에서 64GB로 확장하는 것은 쉽지만, 1TB까지 확장하려면 하드웨어 용량과 비용의 한계에 직면하게 됩니다. 🎜🎜🎜"수직 확장"에 비해 "수평 확장"이 더 나은 확장성 솔루션입니다. 더 많은 데이터를 절약하고 이 솔루션을 사용하려면 Redis 인스턴스 수만 늘리면 단일 인스턴스의 하드웨어 및 비용 제한에 대해 걱정할 필요가 없기 때문입니다. 🎜🎜Redis 클러스터는 "수평 확장"을 기반으로 구현됩니다. 여러 Redis 인스턴스를 시작하여 클러스터를 구성한 후 특정 규칙에 따라 수신된 데이터를 여러 부분으로 나누고 각 부분을 하나의 인스턴스를 사용하여 저장합니다. 🎜샤딩
(샤딩
, 슬라이싱
이라고도 함)을 통과합니다. ) 데이터를 공유하고 복제 및 장애 조치 기능을 제공합니다. 🎜🎜방금 했던 시나리오로 돌아가서, 25GB 데이터를 5개로 균등하게 나누고(물론 균등하게 나눌 필요는 없음), 5개의 인스턴스를 사용하여 저장한다면 각 인스턴스에는 5GB만 저장하면 됩니다. 데이터. 아래 그림과 같이: 🎜
그러면 슬라이싱 클러스터에서는 인스턴스가 5GB 데이터에 대한 RDB를 생성할 때 데이터의 양이 훨씬 적고 fork
하위 프로세스는 일반적으로 오랫동안 메인 스레드를 차단하지 않습니다. . fork
子进程一般不会给主线程带来较长时间的阻塞。
采用多个实例保存数据切片后,我们既能保存 25GB 数据,又避免了 fork
子进程阻塞主线程而导致的响应突然变慢。
在实际应用 Redis 时,随着业务规模的扩展,保存大量数据的情况通常是无法避免的。而 Redis 集群,就是一个非常好的解决方案。
下面我们开始研究如何搭建一个 Redis 集群?
一个 Redis 集群通常由多个节点组成,在刚开始的时候,每个节点都是相互独立地,节点之间没有任何关联。要组建一个可以工作的集群,我们必须将各个独立的节点连接起来,构成一个包含多节点的集群。
我们可以通过 CLUSTER MEET
命令,将各个节点连接起来:
CLUSTER MEET <ip> <port></port></ip>
命令说明:通过向一个节点 A 发送 CLUSTER MEET
命令,可以让接收命令的节点 A 将另一个节点 B 添加到节点 A 所在的集群中。
这么说有点抽象,下面看一个例子。
假设现在有三个独立的节点 127.0.0.1:7001
、 127.0.0.1:7002
、 127.0.0.1:7003
。
我们首先使用客户端连上节点 7001
:
$ redis-cli -c -p 7001
然后向节点 7001
发送命令,将节点 7002
添加到 7001
所在的集群里:
127.0.0.1:7001> CLUSTER MEET 127.0.0.1 7002
同样的,我们向 7003
发送命令,也添加到 7001
和 7002
所在的集群。
127.0.0.1:7001> CLUSTER MEET 127.0.0.1 7003
通过
CLUSTER NODES
命令可以查看集群中的节点信息。
现在集群中已经包含 7001
、 7002
和 7003
三个节点。不过,在使用单个实例的时候,数据存在哪儿,客户端访问哪儿,都是非常明确的。但是,切片集群不可避免地涉及到多个实例的分布式管理问题。
要想把切片集群用起来,我们就需要解决两大问题:
接下来,我们就一个个地解决。
在切片集群中,数据需要分布在不同实例上,那么,数据和实例之间如何对应呢?
这就和接下来要讲的 Redis Cluster
方案有关了。不过,我们要先弄明白切片集群和 Redis Cluster
的联系与区别。
在 Redis 3.0 之前,官方并没有针对切片集群提供具体的方案。从 3.0 开始,官方提供了一个名为
Redis Cluster
的方案,用于实现切片集群。
实际上,切片集群是一种保存大量数据的通用机制,这个机制可以有不同的实现方案。 Redis Cluster
方案中就规定了数据和实例的对应规则。
具体来说, Redis Cluster
方案采用 哈希槽(Hash Slot),来处理数据和实例之间的映射关系。
在 Redis Cluster
方案中,一个切片集群共有 16384
个哈希槽(2^14),这些哈希槽类似于数据分区,每个键值对都会根据它的 key,被映射到一个哈希槽中。
在上面我们分析的,通过 CLUSTER MEET
命令将 7001
、7002
、7003
三个节点连接到同一个集群里面,但是这个集群目前是处于下线状态的,因为集群中的三个节点没有分配任何槽。
那么,这些哈希槽又是如何被映射到具体的 Redis 实例上的呢?
我们可以使用 CLUSTER MEET
命令手动建立实例间的连接,形成集群,再使用CLUSTER ADDSLOTS
命令,指定每个实例上的哈希槽个数。
CLUSTER ADDSLOTS <slot> [slot ...]</slot>
🎜🎜 이제 클러스터에는 이미Redis5.0 提供
여러 인스턴스를 사용하여 데이터 조각을 저장한 후에는 25GB의 데이터를 저장할 수 있을 뿐만 아니라 메인 스레드를 차단하는CLUSTER CREATE
fork
하위 프로세스로 인해 발생하는 갑작스러운 응답 속도 저하도 방지할 수 있습니다. 🎜🎜실제로 Redis를 적용하게 되면 사업 규모가 커지면서 많은 양의 데이터를 저장하는 것은 불가피한 경우가 많습니다. 그리고 Redis 클러스터는 매우 좋은 솔루션입니다. 🎜🎜Redis 클러스터 구축 방법을 시작해볼까요? 🎜Redis 클러스터 구축
🎜Redis 클러스터는 일반적으로 여러 노드로 구성됩니다. 처음에는 각 노드가 서로 독립적이며 노드 간에 관계가 없습니다. 작동하는 클러스터를 형성하려면 독립 노드를 연결하여 여러 노드를 포함하는 클러스터를 형성해야 합니다. 🎜🎜CLUSTER MEET
명령을 통해 각 노드를 연결할 수 있습니다: 🎜127.0.0.1:7001> CLUSTER ADDSLOTS 0 1 2 3 4 ... 5000🎜명령 설명: 노드 A에
- ip: 클러스터에 추가할 노드의 IP
- port: to 클러스터 노드 포트에 추가
CLUSTER MEET
명령을 전송하면 명령을 받은 노드 A가 다른 노드 B를 추가할 수 있습니다. 클러스터의 노드 A. 🎜🎜이것은 다소 추상적입니다. 예를 살펴보겠습니다. 🎜🎜이제 세 개의 독립 노드127.0.0.1:7001
,127.0.0.1:7002
,127.0.0.1:7003
이 있다고 가정해 보겠습니다. 🎜🎜🎜🎜먼저 클라이언트를 사용합니다 터미널을 노드7001
에 연결합니다: 🎜127.0.0.1:7002> CLUSTER ADDSLOTS 5001 5002 5003 5004 ... 10000🎜 그런 다음 노드7001
에 명령을 보내 노드7002
를7001
에 추가합니다. > 위치한 클러스터에서: 🎜127.0.0.1:7003> CLUSTER ADDSLOTS 10001 10002 10003 10004 ... 16383🎜마찬가지로7003
에 명령을 보내고7001
및7002가 있는 클러스터에도 추가합니다. 코드>가 위치해 있습니다. 🎜<pre class="brush:php;toolbar:false">crc16(key,keylen) & 0x3FFF;</pre> <blockquote>🎜 <code>CLUSTER NODES
명령을 통해 클러스터의 노드 정보를 볼 수 있습니다. 🎜
7001
, 7002
및 7003
의 3개 노드가 포함되어 있습니다. 그러나 단일 인스턴스를 사용하면 데이터가 어디에 있는지, 클라이언트가 데이터에 액세스하는 위치가 매우 명확합니다. 그러나 클러스터를 슬라이싱하면 필연적으로 여러 인스턴스의 분산 관리 문제가 발생합니다. 🎜🎜슬라이싱 클러스터를 사용하려면 두 가지 주요 문제를 해결해야 합니다. 🎜Redis Cluster
솔루션과 관련된 내용입니다. 하지만 먼저 슬라이싱 클러스터와 Redis Cluster
의 연결과 차이점을 이해해야 합니다. 🎜🎜Redis 3.0 이전에는 공식적으로 클러스터 슬라이싱에 대한 구체적인 솔루션을 제공하지 않았습니다. 3.0부터는 슬라이싱 클러스터를 구현하기 위해 Redis Cluster
라는 공식 솔루션을 사용합니다. 🎜
🎜사실 클러스터 슬라이싱은 대량의 데이터를 저장하기 위한 일반적인 메커니즘입니다. 이 메커니즘은 다양한 구현 솔루션을 가질 수 있습니다. Redis Cluster
체계는 데이터와 인스턴스에 해당하는 규칙을 규정합니다. 🎜🎜구체적으로 Redis Cluster
솔루션은 해시 슬롯(해시 슬롯)을 사용하여 데이터와 인스턴스 간의 매핑 관계를 처리합니다. 🎜Redis 클러스터
솔루션에서 슬라이스 클러스터에는 총 16384
개의 해시 슬롯(2^14)이 있습니다. , 이러한 해시 슬롯은 데이터 파티션과 유사하며 각 키-값 쌍은 해당 키에 따라 해시 슬롯에 매핑됩니다. 🎜🎜위 분석에서 7001
, 7002
, 7003
3개 노드는 CLUSTER MEET
을 통해 연결되어 있습니다. 명령 동일한 클러스터로 이동하지만 이 클러스터는 현재 오프라인 상태입니다. 클러스터의 세 노드에 할당된 슬롯이 없기 때문입니다. 🎜🎜그렇다면 이러한 해시 슬롯은 특정 Redis 인스턴스에 어떻게 매핑됩니까? 🎜🎜CLUSTER MEET
명령을 사용하여 인스턴스 간 연결을 수동으로 설정하여 클러스터를 형성한 다음 CLUSTER ADDSLOTS
명령을 사용하여 각 인스턴스의 해시 슬롯 수를 지정할 수 있습니다. 사례. 🎜MOVED <slot> <ip>:<port></port></ip></slot>
🎜Redis5.0은 클러스터를 생성하는 CLUSTER CREATE
명령을 제공합니다. 이 명령을 사용하면 Redis는 이러한 슬롯을 클러스터 인스턴스에 균등하게 자동으로 배포합니다. 🎜
举个例子,我们通过以下命令,给 7001
、7002
、7003
三个节点分别指派槽。
将槽 0 ~ 槽5000 指派给 给 7001
:
127.0.0.1:7001> CLUSTER ADDSLOTS 0 1 2 3 4 ... 5000
将槽 5001 ~ 槽10000 指派给 给 7002
:
127.0.0.1:7002> CLUSTER ADDSLOTS 5001 5002 5003 5004 ... 10000
将槽 10001~ 槽 16383 指派给 给 7003
:
127.0.0.1:7003> CLUSTER ADDSLOTS 10001 10002 10003 10004 ... 16383
当三个 CLUSTER ADDSLOTS
命令都执行完毕之后,数据库中的 16384 个槽都已经被指派给了对应的节点,此时集群进入上线状态。
通过哈希槽,切片集群就实现了数据到哈希槽、哈希槽再到实例的分配。
但是,即使实例有了哈希槽的映射信息,客户端又是怎么知道要访问的数据在哪个实例上呢?
一般来说,客户端和集群实例建立连接后,实例就会把哈希槽的分配信息发给客户端。但是,在集群刚刚创建的时候,每个实例只知道自己被分配了哪些哈希槽,是不知道其他实例拥有的哈希槽信息的。
那么,客户端是如何可以在访问任何一个实例时,就能获得所有的哈希槽信息呢?
Redis 实例会把自己的哈希槽信息发给和它相连接的其它实例,来完成哈希槽分配信息的扩散。当实例之间相互连接后,每个实例就有所有哈希槽的映射关系了。
客户端收到哈希槽信息后,会把哈希槽信息缓存在本地。当客户端请求键值对时,会先计算键所对应的哈希槽,然后就可以给相应的实例发送请求了。
当客户端向节点请求键值对时,接收命令的节点会计算出命令要处理的数据库键属于哪个槽,并检查这个槽是否指派给了自己:
MOVED
错误,然后重定向(redirect)到正确的节点,并再次发送之前待执行的命令。节点通过以下算法来定义 key
属于哪个槽:
crc16(key,keylen) & 0x3FFF;
通过
CLUSTER KEYSLOT <key></key>
命令可以查看 key 属于哪个槽。
当节点计算出 key 所属的 槽 i
之后,节点会判断 槽 i
是否被指派了自己。那么如何判断呢?
每个节点会维护一个 「slots数组」,节点通过检查 slots[i]
,判断 槽 i
是否由自己负责:
slots[i]
对应的节点是当前节点的话,那么说明 槽 i
由当前节点负责,节点可以执行客户端发送的命令;slots[i]
对应的不是当前节点,节点会根据 slots[i]
所指向的节点向客户端返回 MOVED
错误,指引客户端转到正确的节点。格式:
MOVED <slot> <ip>:<port></port></ip></slot>
比如:MOVED 10086 127.0.0.1:7002
,表示,客户端请求的键值对所在的哈希槽 10086
,实际是在 127.0.0.1:7002
这个实例上。
通过返回的 MOVED
命令,就相当于把哈希槽所在的新实例的信息告诉给客户端了。
这样一来,客户端就可以直接和 7002
连接,并发送操作请求了。
同时,客户端还会更新本地缓存,将该槽与 Redis 实例对应关系更新正确。
集群模式的
redis-cli
客户端在接收到MOVED
错误时,并不会打印出MOVED
错误,而是根据MOVED
错误自动进行节点转向,并打印出转向信息,所以我们是看不见节点返回的MOVED
错误的。而使用单机模式的redis-cli
客户端可以打印MOVED
错误。
其实,Redis 告知客户端重定向访问新实例分两种情况:MOVED
和 ASK
。下面我们分析下 ASK
重定向命令的使用方法。
在集群中,实例和哈希槽的对应关系并不是一成不变的,最常见的变化有两个:
重新分片可以在线进行,也就是说,重新分片的过程中,集群不需要下线。
举个例子,上面提到,我们组成了 7001
、7002
、7003
三个节点的集群,我们可以向这个集群添加一个新节点127.0.0.1:7004
。
$ redis-cli -c -p 7001 127.0.0.1:7001> CLUSTER MEET 127.0.0.1 7004 OK
然后通过重新分片,将原本指派给节点 7003
的槽 15001 ~ 槽 16383 改为指派给 7004
。
在重新分片的期间,源节点向目标节点迁移槽的过程中,可能会出现这样一种情况:如果某个槽的数据比较多,部分迁移到新实例,还有一部分没有迁移咋办?
在这种迁移部分完成的情况下,客户端就会收到一条 ASK
报错信息。
如果客户端向目标节点发送一个与数据库键有关的命令,并且这个命令要处理的键正好属于被迁移的槽时:
ASK
错误,指引客户端转向目标节点,并再次发送之前要执行的命令。看起来好像有点复杂,我们举个例子来解释一下。
如上图所示,节点 7003
正在向 7004
迁移 槽 16383
,这个槽包含 hello
和 world
,其中键 hello
还留在节点 7003
,而 world
已经迁移到 7004
。
我们向节点 7003
发送关于 hello
的命令 这个命令会直接执行:
127.0.0.1:7003> GET "hello" "you get the key 'hello'"
如果我们向节点 7003
发送 world
那么客户端就会被重定向到 7004
:
127.0.0.1:7003> GET "world" -> (error) ASK 16383 127.0.0.1:7004
客户端在接收到 ASK
错误之后,先发送一个 ASKING
命令,然后在发送 GET "world"
命令。
ASKING
命令用于打开节点的ASKING
标识,打开之后才可以执行命令。
ASK
错误和 MOVED
错误都会导致客户端重定向,它们的区别在于:
槽 i
的 MOVED
错误之后,客户端每次遇到关于 槽 i
的命令请求时,都可以直接将命令请求发送至 MOVED
错误指向的节点,因为该节点就是目前负责 槽 i
的节点。槽 i
的 ASK
错误之后,客户端只会在接下来的一次命令请求中将关于 槽 i
的命令请求发送到 ASK
错误指向的节点,但是 ,如果客户端再次请求 槽 i
中的数据,它还是会给原来负责 槽 i
的节点发送请求。这也就是说,ASK 命令的作用只是让客户端能给新实例发送一次请求,而且也不会更新客户端缓存的哈希槽分配信息。而不像 MOVED
命令那样,会更改本地缓存,让后续所有命令都发往新实例。
我们现在知道了 Redis 集群的实现原理。下面我们再来分析下,Redis 集群如何实现高可用的呢?
Redis 集群中的节点也是分为主节点和从节点。
举个例子,对于包含 7001
~ 7004
的四个主节点的集群,可以添加两个节点:7005
、7006
。并将这两个节点设置为 7001
的从节点。
设置从节点命令:
CLUSTER REPLICATE <node_id></node_id>
如图:
如果此时,主节点 7001
下线,那么集群中剩余正常工作的主节点将在 7001
的两个从节点中选出一个作为新的主节点。
例如,节点 7005
被选中,那么原来由节点 7001
负责处理的槽会交给节点 7005
处理。而节点 7006
会改为复制新主节点 7005
。如果后续 7001
重新上线,那么它将成为 7005
的从节点。如下图所示:
集群中每个节点会定期向其他节点发送 PING
消息,来检测对方是否在线。如果接收消息的一方没有在规定时间内返回 PONG
消息,那么接收消息的一方就会被发送方标记为「疑似下线」。
集群中的各个节点会通过互相发消息的方式来交换各节点的状态信息。
节点的三种状态:
一个节点认为某个节点失联了并不代表所有的节点都认为它失联了。在一个集群中,半数以上负责处理槽的主节点都认定了某个主节点下线了,集群才认为该节点需要进行主从切换。
Redis 集群节点采用 Gossip 协议来广播自己的状态以及自己对整个集群认知的改变。比如一个节点发现某个节点失联了 (PFail),它会将这条信息向整个集群广播,其它节点也就可以收到这点失联信息。
我们都知道,哨兵机制可以通过监控、自动切换主库、通知客户端实现故障自动切换。那么 Redis Cluster
又是如何实现故障自动转移呢?
当一个从节点发现自己正在复制的主节点进入了「已下线」状态时,从节点将开始对下线主节点进行故障切换。
故障转移的执行步骤:
SLAVEOF no one
命令,成为主节点PONG
消息,让集群中其他节点知道,该节点已经由从节点变为主节点,且已经接管了原主节点负责的槽这个选主方法和哨兵的很相似,两者都是基于 Raft算法
的领头算法实现的。流程如下:
大于等于 N/2 + 1
时,该从节点就会当选为新的主节点;集群中的各个节点通过发送和接收消息来进行通信,我们把发送消息的节点称为发送者,接收消息的称为接收者。
节点发送的消息主要有五种:
클러스터의 각 노드는 Gossip
프로토콜, Gossip을 통해 서로 다른 노드의 상태 정보를 교환합니다.
는 MEET
, PING
, PONG
의 세 가지 메시지로 구성됩니다. Gossip
协议交换不同节点的状态信息, Gossip
是由 MEET
、PING
、PONG
三种消息组成。
发送者每次发送 MEET
、PING
、PONG
消息时,都会从自己已知的节点列表中随机选出两个节点(可以是主节点或者从节点)一并发送给接收者。
接收者收到 MEET
、PING
、PONG
MEET
, PING
, PONG
메시지를 보낼 때마다 알려진 노드 목록에서 두 개를 무작위로 선택합니다. (마스터 노드일 수도 있고 슬레이브 노드일 수도 있음)이 수신자에게 함께 전송됩니다. MEET
, PING
및 PONG
메시지를 받으면 다음 두 노드를 알고 있는지 여부에 따라 다른 처리를 수행합니다. 이미 존재하는 경우; , 이는 이전에 통신이 완료되었음을 의미하며 원래 선택한 노드의 정보가 업데이트됩니다.
추천 학습: 🎜Redis 튜토리얼🎜🎜위 내용은 Redis 고가용성 클러스터를 단계별로 이해해 보세요.의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!