この記事では、Redis クラスターのマスター/スレーブ レプリケーションの原理について詳しく説明します。お役に立てば幸いです。
1. より高いパフォーマンスを実現するには: 同時実行性の高いアプリケーションは、単一マシンのパフォーマンスに影響を与えます。負荷を分散し、負荷分散を実現するには、より多くの Redis サーバーが必要です。
2 . 高可用性を達成するには: ダウンタイム/ハードウェア障害を防ぐために単一マシンの場合
#3. スケーラビリティを達成: 単一マシンのメモリとハードウェアには制限があり、水平拡張を実現します。冗長ストレージまたは共有ストレージを実現して、以上の特徴。Redis ビデオ チュートリアル ]
マスター/スレーブ レプリケーションを構成して有効にする方法は? ローカルに疑似クラスターを構築する場合を例に挙げると、ポート 6379 がスレーブ ノード、ポート 6378 がマスター ノードになります。 1. スレーブ ノードの redis.conf で masterip マスターポートのレプリカを設定します。スレーブ ノードを起動すると、自動的にマスター ノードに接続され、データの同期が開始されます。 新しいマスター ノードが置き換えられると、この構成は書き換えられます。 2、または redis-server プログラムの起動時に./redis-server --replicaof masterip masterport
slaveof masterip masterport
slaveof no one
2. マスターとの接続を確立し、マスターとの接続が確立されているかどうかを確認します。データはタイマーを介してマスター ノードから同期する必要があります。
ソース コードの説明:
//每1s执行这个方法 void replicationCron(void) { ... //检查是否需要连接到master 如果是REPL_STATE_CONNECT状态,必须连接到master //#define REPL_STATE_CONNECT 1 Must connect to master if (server.repl_state == REPL_STATE_CONNECT) { serverLog(LL_NOTICE,"Connecting to MASTER %s:%d", server.masterhost, server.masterport); //和master创建连接 if (connectWithMaster() == C_OK) { serverLog(LL_NOTICE,"MASTER <-> REPLICA sync started"); } } //发送ping命令给slave if ((replication_cron_loops % server.repl_ping_slave_period) == 0 && listLength(server.slaves)) { /* Note that we don't send the PING if the clients are paused during * a Redis Cluster manual failover: the PING we send will otherwise * alter the replication offsets of master and slave, and will no longer * match the one stored into 'mf_master_offset' state. */ int manual_failover_in_progress = server.cluster_enabled && server.cluster->mf_end && clientsArePaused(); if (!manual_failover_in_progress) { ping_argv[0] = createStringObject("PING",4); replicationFeedSlaves(server.slaves, server.slaveseldb, ping_argv, 1); decrRefCount(ping_argv[0]); } } //发送换行符到所有slave,告诉slave等待接收rdb文件 listRewind(server.slaves,&li); while((ln = listNext(&li))) { client *slave = ln->value; int is_presync = (slave->replstate == SLAVE_STATE_WAIT_BGSAVE_START || (slave->replstate == SLAVE_STATE_WAIT_BGSAVE_END && server.rdb_child_type != RDB_CHILD_TYPE_SOCKET)); if (is_presync) { if (write(slave->fd, "\n", 1) == -1) { /* Don't worry about socket errors, it's just a ping. */ } } } ... }
3. フル コピー プロセス - ディスクレスをサポートcopy または rdb 永続コピー
スレーブがマスターに接続されているときは、psync (以前は sync コマンドで、部分的な再同期は許可されていないため、現在は代わりに PSYNC を使用してください) コマンドでレプリケーションを初期化し、マスター ノードのレプリケーション ID と処理を最大オフセットを超えた後にマスターに送信します。
マスター ノードには、レプリケーション ID (マーク インスタンス) とオフセット (スレーブ ノードのストリームに書き込まれるマーク) の 2 つの属性があります。
Replication ID, offset
バックログが十分でない場合マスター ノードのバッファー作業中、またはレプリカが不明になった履歴レコード (レプリケーション ID) を参照している場合、完全な再同期が発生します。
ソース コードの説明:
//没有在rdb进程,没有aof重写进程 if (server.rdb_child_pid == -1 && server.aof_child_pid == -1) { time_t idle, max_idle = 0; int slaves_waiting = 0; int mincapa = -1; listNode *ln; listIter li; listRewind(server.slaves,&li); while((ln = listNext(&li))) { client *slave = ln->value; //判断slave是否是等待bgsave状态 if (slave->replstate == SLAVE_STATE_WAIT_BGSAVE_START) { //多久没有发送心跳或查询数据了 空闲时间间隔 idle = server.unixtime - slave->lastinteraction; if (idle > max_idle) max_idle = idle; slaves_waiting++; mincapa = (mincapa == -1) ? slave->slave_capa : (mincapa & slave->slave_capa); } } if (slaves_waiting && (!server.repl_diskless_sync || max_idle > server.repl_diskless_sync_delay)) { /* Start the BGSAVE. The called function may start a * BGSAVE with socket target or disk target depending on the * configuration and slaves capabilities. */ //bgsave rdb生成 startBgsaveForReplication(mincapa); } }
レプリケーション中にプロセス、スレーブ状態遷移プロセス。
#4. コマンド伝播段階では、完全同期が実行された後、マスターとスレーブはデータの一貫性を達成するためにコマンドを伝播します。
インスタンスがプライマリ インスタンスとして最初から再起動されるとき、またはレプリカが昇格されるたびプライマリ インスタンスに送信すると、このインスタンス用に新しいレプリケーション ID が生成されます。 2 つのレプリカが同じレプリケーション ID を持つ場合、それらは異なる時点で同じデータを持つ可能性があり、最新のデータ セットを保持する特定の履歴 (レプリケーション ID) については、オフセットは論理時間として理解されます。 Replication IDとOffsetの2つのデータで判断する必要があります。スレーブ ノードがどこにデータを同期しているかを判断するために使用されます。
1. スレーブ自体にデータがある場合はどうなりますか?
slave は最初に自身のデータを削除し、それから rdb ファイルをロードします。
2. rdb ファイルの生成プロセス中に、クライアントがコマンドを記述する場合、どのように対処すればよいでしょうか?
メモリ キャッシュに保存し、rdb 送信後にスレーブに送信します。
3. Redis レプリケーションはキーの有効期限をどのように処理しますか?
1. コピーはキーを期限切れにしませんが、ホストがキーを期限切れにするまで待機します。マスターはキーの有効期限が切れる(または LRU によりキーを削除する)と、すべてのレプリカに送信される DEL コマンドを合成します。
2. ただし、ホスト ドライバーの有効期限が切れるため、マスター サーバーが DEL コマンドを時間内に提供できないため、レプリカに論理的に期限切れのメモリ キーがまだ残っている場合があります。これに対処するために、レプリカは論理クロックを使用して、データ セットの整合性に違反しない読み取り操作の場合にのみ、キーが存在しないことを報告します (マスターからの新しいコマンドが到着するため)
3 . Lua スクリプトの実行中にキーの有効期限は実行されません。 Lua スクリプトが実行されると、概念的にはマスター ノードで時間が固定されるため、スクリプトの実行中は常に特定のキーが存在するか存在しません。これにより、キーがスクリプトの途中で期限切れになり、データセット内で同じ効果が保証される方法で同じスクリプトをレプリカに送信することがキーに要求されることがなくなります。
レプリカがプライマリに昇格すると、キーの期限切れが独立して開始され、古いプライマリからの支援は必要ありません。
1. データバックアップの問題は解決しましたが、RDB ファイルが大きく、転送時のリカバリ時間が長い大きなファイル
2. マスターが異常な場合は、手動でレプリカをマスターとして選択する必要があります
##3. 1 つのマスターと複数のスレーブ、1 つのマスターと 1 つのスレーブの場合、単一点の問題がまだ残っています 4. Redis バージョン 2.8.18 以降では、より高いパフォーマンスのディスクレス レプリケーションがサポートされています。プログラミング入門を参照してください。 !
以上がRedis におけるクラスターのマスター/スレーブ レプリケーションの原理の簡単な分析の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。