ホームページ  >  記事  >  データベース  >  Redis に 6 ノード クラスターをインストールする方法

Redis に 6 ノード クラスターをインストールする方法

WBOY
WBOY転載
2023-06-03 09:19:281136ブラウズ

はじめに

redis クラスター はネイティブ クラスター ソリューションであり、現在、高可用性と安定性の点で大きな進歩を遂げています。統計や観察によると、redis クラスター アーキテクチャを採用する企業やコミュニティが増えており、事実上の標準となっています。その主な特徴は分散化であり、proxy エージェントは必要ありません。主な設計目標の 1 つは、線形スケーラビリティを達成することです。

redis クラスター サーバー自体に依存するだけでは、正式に約束された機能を完了できません。広い意味では、redis クラスター には、redis サーバーと、jedis などのクライアント実装の両方が含まれる必要があります。それらは全体です。

分散ストレージは、シャーディングとレプリカを扱うことに他なりません。 redis クラスター の中心となる概念はスロットであり、これを理解すればクラスターの管理方法はほぼ理解できます。

メリットとデメリット

これらの特徴を理解すると、運用や保守は実際より簡単になります。まず、より明らかなメリットとデメリットを見てみましょう。

利点

1. 追加の Sentinel クラスターは必要なく、ユーザーに一貫したソリューションを提供し、学習コストを削減します。

2. 分散型アーキテクチャでは、ノードはピアツーピアであり、クラスターは数千のノードをサポートできます。

3. slotの概念を抽象化し、slotの運用保守を行います。

4. レプリカ機能は、ほとんどの場合、手動介入なしで自動フェイルオーバーを実現できます。

欠点

1. クライアントは一部のデータをキャッシュし、比較的複雑な Cluster プロトコルを実装する必要があります。

2. データは非同期でコピーされるため、データの強力な一貫性は保証できません。

3. リソースの分離は難しく、特に複数の企業がクラスターを共有している場合、トラフィックのバランスが崩れることがよくあります。データがどこにあるのかわかりません。また、ホット データは 特別な最適化 では実現できません。

4. スレーブ データベースは完全にコールド スタンバイなので、読み取り操作を共有できません。追加の作業が必要です。

5、MultiOp、および Pipeline のサポートは制限されているため、古いコードのアーキテクチャをアップグレードする場合は注意してください。

6. データ移行は slot ではなく key に基づいており、プロセスが遅くなります。

基本原理

スロットから key までの位置決めプロセスは、明らかに 2 層の配線です。

キーのルーティング

redisクラスターは、一般的に使用される一貫性ハッシュとは関係がなく、主にハッシュスロットの概念を使用します。 key にアクセスする必要がある場合、redis クライアントはまず crc16 アルゴリズムを使用してこの key の値を計算します。次に、この値に対して mod 操作を実行します。

crc16(key)mod 16384

したがって、各 keyhash スロットの 1 つに当てはまります。 16384 は 2^14 (16k) に相当します。redis ノードがハートビート パケットを送信するとき、このハートビート パケットにすべてのスロット情報を含める必要があるため、最適化するために最善を尽くす必要があります。興味があるなら、デフォルトのスロット数が 16384 である理由がわかります。

サーバーの簡単な原理

前述したように、redis クラスターは合計 16384 個のスロットを定義し、すべてのクラスター操作はこのスロット データを中心にエンコードされます。サーバーは、単純な配列を使用してこの情報を保存します。

存在するかどうかを判断する操作は、bitmap を使用して保存するのが最も省スペースです。 redis クラスター は、slot という配列を使用して、現在のノードがこのスロットを保持しているかどうかを保存します。

配列の長さは 16384/8=2048 バイト であるため、0 または 1 を使用して、このノードが特定のスロットを所有しているかどうかを識別できます。

実際、操作を完了するには最初のデータ ClusterState のみが必要であり、別の次元の Slot 配列が保存されるため、エンコードやエンコードが容易になります。ストレージ。ノードは、処理を担当するスロットを 2 か所 (clusterNode 構造のスロットと numslots) に記録することに加えて、メッセージを通じてクラスター内の他のノードに独自の slots 配列も送信します。他のノードは現在所有しているスロットです。

データベース内の 16384 個のスロットすべてがノードによって処理されると、クラスターはオンライン状態 (ok) になります。逆に、データベース内のいずれかのスロットが処理されない場合、クラスターはオフライン状態 (失敗) になります。 )。

クライアントが関連コマンドをノードに送信すると、コマンドを受信したノードは、コマンドによって処理される key がどのスロットに属するかを計算し、そのスロットが割り当てられているかどうかを確認します。それ自体に。自分のものでない場合は、クライアントを正しいノードに誘導します。

したがって、クライアントはクラスター内の任意のマシンに接続することで操作を完了できます。

6 ノード クラスターのインストール

準備

3 シャード クラスターを組み立てると仮定します。各シャードにはコピーがあります。この場合、必要な node インスタンスの合計数は 3*2=6 となります。 redis は設定ファイルを指定することで起動できますが、ここで行うのは設定ファイルを変更することです。

デフォルトの構成ファイルのコピーを 6 つコピーします。

for i in {0..5}
do
cp redis.conf  redis-700$i.conf
done

修改其中的配置文件内容,拿redis-7000.conf来说,我们要启用它的cluster模式。

cluster-enabled yes
port 7000
cluster-config-file nodes-7000.conf

nodes-7000.conf会保存一些集群信息到当前节点,所以需要独立。

启动&关闭

同样的,我们使用脚本来启动它。

for i in {0..5}
do
nohup ./redis-server redis-700$i.conf &
done

为了演示,我们暴力把它关闭。

ps -ef| grep redis | awk '{print $2}' | xargs kill -9

组合集群

我们使用redis-cli进行集群的组合。redis将自动完成这个过程。这一系列的过程,是通过发送指令给每个节点进行组合的。

./redis-cli --cluster create 127.0.0.1:7000 127.0.0.1:7001 127.0.0.1:7002 127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005 --cluster-replicas 1

几个高级原理

节点故障

集群中的每个节点都会定期地向集群中的其他节点发送ping消息,以此来检测对方是否在线,如果接收ping消息的节点没有在规定的时间内返回pong消息,那么发送ping消息的节点就会将接收ping消息的节点标记为疑似下线(PFAIL)。

如果在一个集群里面,半数以上节点都将某个主节点 x 报告为疑似下线,那么这个主节点x将被标记为已下线(FAIL),将x标记为FAIL的节点会向集群广播一条关于 x 的FAIL消息,所有收到这条FAIL消息的节点都会立即将 x 标记为FAIL

大家可以注意到这个过程,与 es 和 zk 的节点判断类似,都是半数以上才进行判断,所以主节点的数量一般都是奇数。由于没有最小组群配置,理论上会有脑裂(暂时并未遇到过)。

主从切换

当一个节点发现自己的主节点进入fail状态,将会从这个节点的从节点当中,选出一台,执行slaveof no one命令,变身为主节点。

新的节点完成自己的槽指派以后,会向集群广播一条pong消息,以便让其他节点立即知道自己的这些变化。它告诉别人:我已经是主节点了,我已经接管了有问题的节点,成为了它的替身。

redis内部对集群的这些管理,大量使用了已经定义好的这些指令。所以这些指令不仅仅供我们从命令行使用,redis自己内部也用。

数据同步

当一台从机连接到master之后,会发送一个sync指令。master在收到这个指令后,会在后台启动存盘进程。执行完毕后,master将整个数据库文件传输到slave,这样就完成了第一次全量同步。

接下来,master会把自己收到的变更指令,依次传送给slave,从而达到数据的最终同步。从redis 2.8开始,就支持主从复制的断点续传,如果主从复制过程中,网络连接断掉了,那么可以接着上次复制的地方,继续复制下去,而不是从头开始复制一份。

数据丢失

redis cluster中节点之间使用异步复制,并没有类似kafka这种ack的概念。节点之间通过gossip协议交换状态信息,用投票机制完成SlaveMaster的角色提升,完成这个过程注定了需要时间。在发生故障的过程中就容易存在窗口,导致丢失写入的数据。比如以下两种情况。

一、命令已经到到master,此时数据并没有同步到slavemaster会对客户端回复ok。如果这个时候主节点宕机,那么这条数据将会丢失。redis这样做会避免很多问题,但对一个对数据可靠性要求较高的系统,是不可忍受的。

二、由于路由表是在客户端存放的,存在一个时效问题。如果分区导致一个节点不可达,提升了某个从节点,但原来的主节点在这个时候又可以用了(并未完成failover)。如果客户端的路由表没有及时更新,那么写入错误的节点可能导致数据丢失。

所以redis cluster在通常情况下运行的很好,在极端情况下某些值丢失问题,目前无解。

复杂的运维

redis cluster的运维非常的繁杂,虽然已经进行了抽象,但这个过程依然不简单。有些指令,必须在详细了解它的实现原理之后,才能真正放心的去用。

扩容会用到的一些命令。在实际使用的过程中,可能需要多次频繁地输入这些命令,且输入的过程中还要监视它的状态,所以基本上是不可能人工跑这些命令的。

运维的入口有两个。一个是使用redis-cli连接任意一台,然后发送cluster打头的命令,这部分命令大多数是对槽进行操作。 在开始组合集群时,就是反复调用这些命令进行的具体逻辑执行。

另外一个入口是使用redis-cli命令,加上--cluster参数和指令。这种形式主要是用来管控集群节点信息 ,比如增删节点等。所以推荐使用这种方式。

redis cluster提供了非常复杂的命令,难于操作和记忆。推荐使用类似CacheCloud的工具进行管理。

下面是几个例子。

通过向节点 A 发送 CLUSTER MEET 命令,客户端可以让接收命令的节点 A 将另一个节点 B 添加到节点 A 当前所在的集群里面:

CLUSTER MEET  127.0.0.1 7006

通过cluster addslots命令,可以将一个或者多个槽指派给某个节点负责。

127.0.0.1:7000> CLUSTER ADDSLOTS 0 1 2 3 4 . . . 5000

设置从节点。

CLUSTER REPLICATE <node_id>

redis-cli —cluster

redis-trib.rb是官方提供的Redis Cluster的管理工具,但最新版本已经推荐使用redis-cli进行操作。

向集群中添加新节点

redis-cli --cluster add-node 127.0.0.1:7006 127.0.0.1:7007 --cluster-replicas 1

从集群中删除节点

redis-cli --cluster del-node 127.0.0.1:7006 54abb85ea9874af495057b6f95e0af5776b35a52

迁移槽到新的节点

redis-cli --cluster reshard 127.0.0.1:7006 --cluster-from 54abb85ea9874af495057b6f95e0af5776b35a52 --cluster-to 895e1d1f589dfdac34f8bdf149360fe9ca8a24eb  --cluster-slots 108

类似的命令还有很多。

create:创建集群 check:检查集群 info:查看集群信息 fix:修复集群 reshard:在线迁移slot rebalance:平衡集群节点slot数量 add-node:添加新节点 del-node:删除节点 set-timeout:设置节点的超时时间 call:在集群所有节点上执行命令 import:将外部redis数据导入集群

其他方案概览

主从模式

redis最早支持的,就是M-S模式,也就是一主多从。redis单机qps可达到 10w+,但是在某些高访问量场景下,依然不太够用。一般通过读写分离来增加slave,减少主机的压力。

既然是主从架构,就面临着同步问题,redis主从模式的同步分为全同步和部分同步。当刚创建一个从机的时候,不可避免的要进行一次全量同步。等全量同步结束之后,进入增量同步阶段。这个和redis cluster是没什么区别的。

这种模式还是比较稳定的,但要额外做一些工作。用户需要自行开发主从切换的功能,也就是使用哨兵去探测每个实例的健康状况,然后通过指令进行集群状态的改变。

当集群规模增大,主从模式会很快遇到瓶颈。所以一般会采用客户端hash的方法进行扩展,包括类似于memcached的一致性哈希。

客户端hash的路由可能会很复杂,通常会通过发布jar包或者配置的方式维护这些meta信息,这也给线上环境增加了很多不确定性。

不过,通过加入类似ZK主动通知的功能,将配置维护在云端,可以显著降低风险。笔者曾经维护过的几千个redis节点,就是用这种方式进行管理的。

代理模式

代码模式在redis cluster出现之前,非常流行,比如codis。代理层通过把自己模拟成一个redis,接收来自客户端的请求,然后按照自定义的路由逻辑进行数据分片以及迁移,而业务方不需要改动任何代码。除了能够平滑的进行扩容,一些主从切换、FailOver的功能也在代理层完成,客户端甚至可以没有任何感知。这类程序又称为分布式中间件。

一个典型的实现如下图,背后的redis集群甚至可以是混合的。

但这种方式的缺点也是显而易见的。首先,它引入了一个新的代理层,在结构上、运维上都显复杂。需要进行大量的编码,比如failover、读写分离、数据迁移等。另外,proxy层的加入,对性能也有相应的损耗。

多个proxy一般使用lvs等前置进行负载均衡的设计,如果proxy层的机器很少而后端redis的流量很高,那么网卡会成为主要的瓶颈。

Nginx也可以作为redis的代理层,比较专业的说法叫做Smart Proxy。这种方式较为偏门,如果你对nginx比较熟悉,不失为一种优雅的做法。

使用限制和坑

redis的速度特别的快。一般越快的东西,出问题的时候造成的后果越大。

つい最近、私は redis の仕様を書きました:「Redis の仕様、これが最も適切かもしれません」。仕様はアーキテクチャと同じであり、会社の環境に適したものが最適ですが、いくつかの基本的なアイデアを提供します。

厳しく禁止されているものは、通常、前世代の落とし穴です。 redis-cluster については、本仕様書の内容に加え、以下の点が追加されます。

1. redis クラスター は 1,000 ノードをサポートできると主張していますが、これは行わない方がよいでしょう。ノードの数が 10 に増えると、クラスター内で多少のジッターを感じることがあります。このような大規模なクラスターは、ビジネスがすでに非常に良好であることを証明しているため、クライアントのシャーディングを検討してください。

2. ホット スポットを必ず避けてください。すべてのトラフィックが特定のノードに到達すると、一般に深刻な結果が生じます。

3. redis を大きな key に配置しないでください。大量の遅いクエリが生成され、通常のクエリに影響を与えます。

4. ストレージとして使用していない場合、キャッシュには有効期限を設定する必要があります。トイレを占領しているのにうんこをしないという感覚は非常に迷惑です。

5. トラフィックが大きい場合は、aof を有効にせず、rdb のみを有効にします。

6、redis クラスター 操作では、パイプライン の使用と マルチキー の使用を減らすと、多くの予測不可能な結果が生成されます。

以上がRedis に 6 ノード クラスターをインストールする方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はyisu.comで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。