キャッシュサーバとして、Redisの
このブログは続いている上でブログが技術的なポイントの共有を終了していません。
技術が成熟しているが、キャッシュサーバとしてRedisのは、多くの企業のための1つの選択肢ですが、また、いくつかの問題があります。キャッシュキャッシュは、故障キャッシュ、キャッシュ無効化の問題、そして、参照は、分散ロックを貫通するもたらされます。
1.1、バッファ浸透
今日のプロジェクトでは、サービス層はDAO層、DAO層を呼び出して、再度データベースを照会するために、主に垂直MVCアーキテクチャです。直接データを返す、またはデータベースを照会するために行くがある場合、キャッシュサーバとしてのRedisは、キャッシュサーバのクエリが行く照会するDAO層を呼び出すために、サービス層です。データベース上の圧力を低下させる、ディスクI / Oの動作を減らすために多くを行う、見ることができます。
今、私たちは状況が1-1000のデータIDを持つデータベースに存在することを前提としています。さて、手動で誰かが要求IDをシミュレートするならば、キャッシュサーバ内のデータが存在しないので、データベースを照会するために行くだろう、1001年です。それはデータベースを照会するために、無効な要求が多数あるのであれば質問は、です。データベースには、必然的にこのような状況は、キャッシュの浸透と呼ばれ、耐え難い苦痛の原因となります。
どのようにそれを解決するには?
異なる要求IDの数が多いにもデータベースを照会するために行く場合ので1は、キャッシュ・サーバーに直接保存されたヌル値に問い合わせ、このアプローチは、推奨されません。
図2に示すように、流量制限インタフェース、融合ダウングレード
このプロジェクトでは、重要なインタフェースの電流制限の制限に加えて、より多くの悪意のある攻撃に対する要求を行わなければならないが、また、ダウングレードヒューズを用意して行ってください、このアプローチは効果的に無効な要求の大きな数を制御することができます。
3、ブルームフィルタ
ブルームフィルタはすぐに要素がコレクション内に存在するか否かを判断するために、典型的なシナリオを迅速に特定のコンテナが存在するか否かを決定するためのキーであり、直接的なリターンがない、ハッシュセットと同様です。ブルームフィルタは、アルゴリズムとコンテナのサイズをハッシュするキーは、実際はほとんどの会社が選択されているということです。
1.2、バッファの内訳
高い同時実行では、いくつかのホットな値クエリが、この時間はちょうど直接データベースに落ちる多数の要求で、その結果、キャッシュ、キャッシュミスを満了し、今回はそのような要求の多くは、データベースがクラッシュすることがあります。
ソリューション:
1は、ホットキーは無期限に設定されています。
2、ミューテックスを使用。
両方のケースでは、キャッシュミスの一部ですが、小さなディテールもあります。これは特に、高度に同時の期間内に、複数のキャッシュの同時故障の問題です。複数のキャッシュの無効化のこの問題を回避するために、我々はタイムアウトを設定し、彼らは一定時間+ランダムな時間を使うことができます。データベースキャッシュの無効化を照会する多数の要求を可能避けるために。
1.3、分散ロック
2分散ロックのZooKeeperに基づい; .. 3分散ロックのRedisに基づいて、典型的にはロック分散三の実装、楽観的ロックデータベース1があり、ここでのみ分散ロックのRedisに基づいて記録します。
分散ロック・要件など:
- 相互に排他的:クラスタ内の分散アプリケーションを確実にするために、同じロックは、同時に一台のマシン上の一つのスレッドで実行することができます。
- ロックを保持するプロセスでは、クライアントのクラッシュのロックを解除せずにそこが、他のクライアントがロックできるようにすることができます:デッドロックを避けます。
以下のコードを参照します:
public List<Goods> goodsManager() {
System.out.println("调用过了业务层的goodsManager方法");
return goodsDao.queryAllPage();
// 1,先去查询缓存服务器
List<Goods> goodsList = (List<Goods>) redisTemplate.opsForValue().get("goods");
if(goodsList == null){
// 2,申请分布式锁
RedisConnection conn = redisTemplate.getConnectionFactory().getConnection();
if(conn.setNX("lock".getBytes(), "1".getBytes())){
// 3,给分布式锁设置一个超时时间
conn.expire("lock".getBytes(), 60);
System.out.println("去数据库中查询所有的商品");
// 4,缓存中没有商品列表的数据
goodsList = goodsDao.queryAllPage();
// 5,将结果放入缓存中
redisTemplate.opsForValue().set("goods", goodsList);
redisTemplate.expire("goods", 5, TimeUnit.MINUTES);
// 6,释放分布式锁
conn.del("lock".getBytes());
} else {
try {
Thread.sleep(50);
goodsManager();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return goodsList;
} else {
//缓存服务器中有商品列表的数据
return goodsList;
}
}
コードデザインのアイデア:
1、要求は、メソッドを呼び出しています。
2、があるかどうか、データベースを照会ない場合は、キャッシュのクエリをRedisのために行きます。
ネイティブコネクタ(SETNX)分散ロックを使用して、図3に示すように、得られ、次いでタイムアウトを設定されています。
設定されたタイムアウトの理由は、デッドロックを防ぐために、心より少ないロックの崩壊後に得られたスレッドが発生した場合ので、タイムアウトを設定することです。
図4に示すように、データをデータベースに照会し、データベースに格納されています。
図5に示すように、ロックが解除されます。
1.4、アバランシェ効果
簡単に言えば、同時にキャッシュキーの数が多い(キー)は、(無効)有効期限が切れて、新しいキャッシュと多数の要求が即座にデータベース接続例外が生じ落ちた場合には、サーバーに保存されていない即時。
ソリューション:
1、あなたはシンを使用して、分散ロック、単一のアーキテクチャプロジェクトを使用することができます
2、期限切れになることはありません
図3に示すように、同時にキャッシュの大部分の故障を防止するために、キャッシュのタイムアウトに一定時間+ランダムタイムアウトが設けられています。
4、高可用性クラスタリング
springbootと統合1.5、Redisのキャッシュ
キャッシュコメント@Enablecachingスタート機能を開くことがまず
@Cacheable
この方法は、ノートをマークし、実行前にサーバーのキャッシュに照会され、キャッシュサーバが結果を持っている場合は、単純に結果を返し、現在のメソッドが実行されません。ない結果場合、メソッドは、メソッドの本体で行われ、この方法は、キャッシュサーバに値を返します。
@CachePut
メモや注釈が似て@Cacheable機能、唯一の違いは、該当するキャッシュサーバは、値に関係なく存在しないことであるメソッドを追加し、更新するための適切なメソッドを呼び出して行くだろう。
@CacheEvict
指定されたキャッシュを削除し、削除方法が一般的に使用されます。
二、Redisの持続性
### 2.1,redis提供两种持久化方式:
- RDB:それは、メモリ内の現在の瞬間Redisのデータ構造のバックアップ(私たちは、スナップショットを呼んでいるもの)です。
- AOF:その役割はRedisのは、特定の条件下で、後でこれらのコマンドの実装続いRedisのは、返信Redisのデータで保存することができるファイルに格納され、順次実行されたコマンドを書き込むときに書き込みコマンドを実行することです。
2.2、RDB原則分析
RDBの永続性は、2つの動作モード、持続性のために手動操作を持っています。
- 保存:現在のRedisのサーバーは、永続性が完了するまで、ラインを禁止すべきブロックします。
- bgsave:トリガモードは、子プロセスをforkし、子プロセスは、そのときのフォークの子プロセスのみ発生し、ブロッキング、永続的なプロセスを担当しています。
bgsave最大の違いとすることができます、あなたがそうすることを希望しない場合は、そうでない場合は、誰が、災害に気づくんだろう、クライアントの書き込み操作をブロックしませんが、bgsaveが失敗した場合、Redisのデフォルトのアクセスを受け付けを停止することbgsaveを保存ストップ・オン・bgsave-書き込み、エラーはいいいえへ
自動永続化のためのもう一つのトリガーは、我々は、設定ファイルで最初のスナップショットのルールを設定することができます。
書き込みコマンドを実行するとき900 1 900秒以下を保存し、スナップショットバックアップが
300 10 10を保存し、300秒以内にスナップショットバックアップをするとき、書き込みコマンドを実行した
60万10000は、スナップショットを使用して、60秒以内にするとき、書き込みコマンドを実行し保存バックアップ
注:バックアップRedisのコマンドを実行すると、コマンドを記述することは禁止されます
2.3、AOF原則分析
プロセス全体のAOF図は、大きく2つのステップに分けることができ、ステップは、リアルタイムコマンドを書き込むことで、第2のステップはAOFファイルの書き換えで、上書きがAOFファイルのサイズを低減することです。
AOFファイルの追加一般的なプロセスは次のとおりです。コマンド書き込み - > aof_buf(バッファ)に追加 - >同期AOFディスクに。なぜあなたはそれがディスクに同期をバッファbuf書くのですか?リアルタイムで書かれている場合、I / O操作は、主に、システムのパフォーマンスが低下しますディスクの多くをもたらすでしょうから。
以下の構成についてAOFの永続性について。
appendonly no
AOFのバックアップが有効になっているあなたははい代わりにそれを有効にする必要がある場合は、デフォルトでは何も、有効になっていないされていません。appendfilename "appendonly.aof"
ファイルには、追加の書き込みコマンドがappendonly.aofで定義します- #
appendfsync always
- 常に表すRedisのコマンドを実行するたびに、AOFに保存されたファイルを同期しますパフォーマンスが収益に影響を与えますが、セキュリティが非常に高いです。
appendfsync everysec
evarysec
(デフォルト)毎秒同期時間を表し、パフォーマンスが向上しますが、セキュリティが低下する、1秒以内にコマンドを失われることがあります。#appendfsync no
no
彼らは、性能が保証され、手動でコマンドを同期させる必要があり、彼らは同期していないと述べたが、セキュリティが貧弱です。
2.4、Redisのメモリ復旧戦略
リサイクルポリシーパラメータメモリmaxmemoryポリシーは、最大メモリが取られたときにメモリが処理され、redis.confのRedisの構成で使用されています。
Redisのは、メモリ戦略のうち6を提供しています
volatile-lru:
最も最近の戦略のうち、使用、Redisのは(ばかり回復タイムアウト)に、それらの設定キーのタイムアウトを回復しました。allkeys-lru:
フェーズアウト戦略の最小使用すると、最小限のペアを持つすべてのキーをRedisの。volatile-random:
ランダム排除戦略がに設定されたキーのタイムアウトを削除しています。allkeys-random:
無作為化フェーズアウト戦略は、すべてのキーと値のペアを削除する(使用しません)。volatile-ttl:
ポリシーに残りのキー最短生存時間を削除します。noeviction(默认):
ない任意のキーと値のペアのうち、メモリがいっぱいになると、読み取り専用モードに入ります。
メモリ回復メカニズム、LRUアルゴリズムと計算で正確ではないのTTLのRedisにおけるアルゴリズムが、近似アルゴリズムで。3 maxmemory-サンプルに検出Redisの設定はデフォルトのデフォルトの数があります。
三、Redisの可用性
3.1、マスタースレーブのレプリケーション
ユーザー時間の非常に大きな額では、単一のRedis確かに完全に十分ではありません。だから、より頻繁に我々は、/書き込み分離を読んでより頻繁に書き込み操作をより読まれる別の前提を読み出し/書き込みすることを好む、そう長くのための複数のサーバ上のデータは、単一のサーバの圧力を排除することができます。
したがって、図サーバーに示した構造のために:
単一の書き込み別々のキャッシュ機能を実現するために、サーバーが書き込み動作のために責任があると仮定し、読み出し動作のために残りの3つ。しかし、3台のサーバを残りのそれらの間でデータを同期させることが、データを読み取ることができないことを、欠陥の一種であり明らかです。これは、その後、我々は彼らの間でデータを通信する必要がある、データの不整合が発生します。
図のようにコンセプトから簡単マスターコピー主にマスターデータの書き込み動作の責任は、残りの(スレーブ)から3データの責任は、操作をお読みください。データが書き込まれると、我々はサーバー間でデータの一貫性を達成するように、設定された属性に応じて自動的に、残りの3台のサーバーに更新されたデータをコピーしています。
マスター・コピー・プロセスから、実質的に:
プライマリ・サーバ(マスタ)のことを確実にする1。
図2は、サーバからの起動時、メインサーバと同期コマンドを送信します。マスターサーバーは、同期コマンドを受信した場合、データをバックアップするbgsaveコマンドを実行されますが、プライマリサーバとクライアントが書くことを拒否することはありませんが、クライアントの書き込みバッファからコマンドを記述すること。プライマリサーバが受信しない前に戻るスナップショット・ファイルまで、私たちは、クライアントに応じて、既存のデータを使用することを決定しますまたはエラーは、構成に応じて、サーバから返されます。
bgsaveコマンドは、プライマリサーバの後に実行された場合3、サーバから送信されたバックアップファイルを起動し、サーバからのすべての既存のデータを破棄します。この時間は、スナップショット・ファイルから送信された負荷を開始します。
実行bgsaveも解決するには、サーバーからバックアップファイルの完了後、サーバーに送信されます後にバックアップファイルを送信した後、プライマリサーバは、コマンドバッファを書く4は、以降のコマンドマスターサーバーを待つようになりました。
図5に示すように、同期は、書き込みコマンドを完了するために、各マスターサーバー完了した後、マスター・スレーブの同期が完了すると、同期サーバからのライトコマンドに同時に送られます。
スレーブ構成: IPとポートマスターセットを設定マスターパスワードをslaveof server port
masterauth root
これまでのところ、それが行われていますか?
、ちょうどマスターコピーから終了し、上記の手順ではなく、個別の読み取りや書き込みが完了していません。プライマリ(マスター)サーバーがダウンした場合や、すべての後、全体のキャッシュサーバがハングアップ。サーバーとして(スレーブ)の動作を記述することができない場合==そして==その後、どのようにそれ(センチネルモード)を解決するには?
3.2、センチネルモード
1.どのような見張りモード?
マスターのダウンタイムを手動でマスターにスレーブに切り替えるために必要がある場合は、このアプローチは、手動による介入、時間のかかるが必要です。したがって、センチネルモデルは、私たちは、この問題を解決することができます。
2、簡単にセンチネルモデル
- Sentinelは別のプロセスです。
- Sentinelは、マスターとスレーブを含む複数のRedisのサーバーを検出します。その動作状態を検出し、そのRedisのサーバの応答をコマンドを送信することにより。
- センチネルダウンマスタを検出したとき、自動的にサブスクリプションモデル、ホストスイッチを発行して、構成ファイルを変更する他のスレーブに通知し、スレーブマスタに切り替えます。
- 高可用性センチネルを達成するために、複数のSentinelモデルで構成することができる、すなわち、各サーバ上で実行されている検出センチネルプロセスの複数の異なるサーバが互いにセンチネル二十から二を監視するのRedis。
- マルチモードをセンチネル、一度ダウンマスター、センチネル1は、この結果を検出し、すぐにフェイルオーバーしますが、利用できないだけでセンチネルマスタースーパーバイザはありません。他の警備員も検出し、マスターが利用できないと、一定量がある場合、それはハンドオーバーが完了した後、それはサブスクリプションの発行を通じてできるようになり、センチネルの中で最初の投票、歩哨によって開始され、投票の結果、スイッチング動作を形成することになりますホストサーバの実装の上に自分自身の各センチネル・サーベイランス。
3、センチネルモードの設定
3.1、#設定センチネル設定ファイル:redis/src/sentinel.conf
3.2、#を無効保護モードprotected-mode no
3.3、最後の2は、スイッチングが失敗しない1つのまたは2以上のセンチネルメインサービス表し#メインリスニングサービスの設定、サーバ名(カスタム)IPプライマリサービスポート2をsentinel monitor
3.4、#は、サービスのパスワードを定義サーバー名(上記と同じ)パスワードをsentinel auth-pass
3.5、#スタートセンチネルモード。
./redis-sentinel sentinel.conf
図4に示すように、他の関連する構成
sentinel down-after-milliseconds :
数ミリ秒内のサービスのRedisはお答えできませんセンチネルのRedisの検出指定されたサービス時には、単一のオフラインSentinelは、主観的時間という、デフォルトは30秒です。
sentinel failover-timeout:
このミリ秒数、ハンドオーバの失敗よりは3分間、失敗とみなされたときに、ミリ秒単位のフェイルオーバー操作の数を指定します。
sentinel notification-script:
指定されたセンチネルは、スクリプトが警察を呼び出し、異常なRedisの例を検出します。
3.3、クラスタの断片
前記キャッシュサーバの二十から二複数のクラスタ間の断片化原理の相互通信、各マスターインスタンスから設定コピーと複数のインスタンスを有します。主な例に格納されるデータの最小合計量から設定制限複製を解決するために、データベース朱キーと値のペアの一部として設定され、保存された各複製は、大幅にキャッシュサーバのサイズを拡大しました。
次のようにその構造は次のとおりです。
図1に示すように、クラスタの断片化特性
図1に示すように、クライアント・ノードが直接のRedis、無中間層プロキシに接続されています。
2、[0から16383]スロット(スロット)、保守を担当するクラスタに物理ノードの全てをマッピングするのRedisクラスター。
図3は、すべてのノードが相互接続されたとのRedis(PING-PONG機構)、バイナリデータの送信を最適化するために内部ゴシッププロトコルです。
4、より多くのクラスタの半分よりによってノード障害検出を有効にするときに障害を検出するノード。
==質問:Redisのクラスタが16,384ハッシュスロットを内蔵し、それは彼がキーにスロットかを決定する方法ですか?==
クラスタはRedisのキー値演算結果を使用すること、RedisのCRC16アルゴリズムキー、及び残り番号16384の結果配置され、各キーに対応する番号が0から16383までの間に溝をハッシュ化する場合、 Redisの約ノードの数に応じて異なるノードにマッピングされたハッシュスロットに等しくなります。
2、クラスタセットアップ手順
前置条件:
削除のRedis / srcの下appendonly.aof、dump.rdb、ノード-6379.conf3ファイル。
1、redis.conf、クラスタ構成情報散開星団を変更し、
cluster-enabled yes
クラスタの設定ファイルを指定して、
cluster-config-file nodes-
ポートの.conf
Redisの-trib.rbクラスタ管理ツールはRubyで実装されているよう2は、Redisの-trib.rb Redisのでクラスタを設定するので、私たちはルビー環境をインストールする必要があります。
2.1、インストールのRuby 2.2、インストールRubyGemsの依存のRedisyum -y install zlib ruby rubygems
gem install -l redis-3.3.0.gem
3、我々はスクリプトを使用することができるので、環境に依存した後にインストールコマンド
注:当社解凍したディレクトリSRCでこのスクリプトファイル。
コマンドを実行します。
--replicas 0 192.168.10.167:6379 192.168.10.167:6380 192.168.10.167:6381オープンポート16379のRedisの+ 1Wを作成./redis-trib.rb - 0レプリカ:指定したデータの数が0であります。
図4は、クラスタの状態を表示する
クライアントを介して次のコマンドを入力:
クラスタノード:このコマンドは、スロットの割り当てを表示することができ
、全体のRedisは16,384スロットを提供し、/のRedis-trib.rbスクリプトは16384であり、実現N個のノードに割り当てられた平均スロット。
IVの概要
このブログのテキスト重い、ほとんどの問題の原因と解決策を説明。一緒に以前とブログは、高可用性へのエントリーからRedisのです。そのほとんどは、プレーン、レコードを作るために、仕事に遭遇します。しかし、説明が簡単である、予期しない問題の多くは、まだありますが、より明確に詳細に記述されたプログラムや原則に問題になります次の更新で継続されます。
限られた容量に、より詳細な技術的なポイントは、不快感は、メッセージ(メール)アドバイスを残してください、少なくとも場合は、記録されません。
読んでくれてありがとう!