Redis 開発における一般的な問題 - キャッシュの侵入 - キャッシュ雪崩 - Redis Brain の分割キャッシュの破壊
記事ディレクトリ
序文
日常の開発では、私たちは皆、データを保存するためにデータベースを使用します。一般的なシステム タスクでは通常、高い同時実行性がないため、これは問題になりませんが、一度大量のデータが必要になると、製品を急いで購入したり、ホームページへのアクセス数が瞬間的に多くなったりする場合、データベースを使用してデータを保存するだけのシステムは、ディスク指向であり、ディスクの読み取り/書き込み速度が遅いため、パフォーマンスに重大な欠点が生じます。比較的遅い。何千ものリクエストが受信され、システムは非常に短期間に何千もの読み取り/書き込み操作を完了する必要がある。多くの場合、これはデータベースが耐えられる量ではなく、データベース システムが異常な状態になるのは非常に簡単である麻痺し、最終的にはサービスのダウンタイムにつながる、本番環境に重大な問題が発生する。上記の問題を克服するために、プロジェクトでは通常、メモリベースのデータベースであり、特定の永続化機能を提供する NoSQL テクノロジを導入します。
Redis テクノロジーは NoSQL テクノロジーの 1 つですが、Redis の導入により、キャッシュの侵入、キャッシュなだれ、キャッシュの破壊などの問題が発生する可能性があります。この記事では、これらの問題についてさらに詳しく分析します。
1. Redis キャッシュの浸透
キャッシュペネトレーションとは何ですか?
簡単に言うと、データを取得するときは、まず redis に行ってデータを見つけます。結果が見つからない場合は、MySQL に行ってデータを見つけます。それでも結果が見つからない場合は、受信するすべてのスレッドが次のことを行う必要があります。この場合、データベースへの負荷が大きくなり、クラッシュする現象をキャッシュペネトレーションと呼びます。
2. Redis でのキャッシュ雪崩
3. Redis のスプリットブレイン問題
クライアントはメイン サーバーにデータを書き込みますが、メイン サーバーには同期する時間がありません。メイン サーバーが停止した場合は、この時点で新しいメイン サーバーが選択されます。元のメイン サーバーは一定の時間が経過すると回復します。この時点では、 、元のメインサーバー このサーバーはスレーブサーバーとしてのみ使用できます マスターサーバーのデータは同期できないことがわかります この問題は、redis のスプリットブレイン問題です。
解決
min-slaves-to-write 1 これは、クライアントがデータを書き込むとき、このデータを書き込むためにメイン サーバー上の少なくとも 1 つのスレーブ サーバーが正常に接続されている必要があることを意味します。
min-slaves-max-lag 10: これは、マスターとスレーブの同期時間が 10 秒であることを意味します。
4. キャッシュの内訳
ここで、キャッシュの侵入の違いに注意する必要があります。キャッシュ ブレークダウンとは、非常にホットで常に大量の同時実行を実行するキーを指します。大規模な同時実行は、このポイントへのアクセスに焦点を当てます。キーの有効期限が切れると、継続的な大規模な同時実行はキャッシュを突破し、データベースに直接リクエストします。たとえば、データベースに穴を開けるようなものです。障害。
キーの有効期限が切れると、大量の同時アクセス要求が発生します。このタイプのデータは一般にホット データです。キャッシュの有効期限が切れるため、データベースは同時にアクセスされ、最新のデータのクエリとキャッシュへの書き戻しが行われます。 、これにより、データベースに過剰な負荷が瞬時に発生します。
解決策:
1. ホットスポット データを無期限に設定します
キャッシュ層からは有効期限が設定されていないため、ホットスポット キーの有効期限が切れても問題はありません。
2. ミューテックスロックを追加する
分散ロック: 分散ロックを使用すると、1 つのスレッドだけが各キーに対してバックエンド サービスに同時にクエリを実行できるようになります。他のスレッドには分散ロックを取得する権限がないため、待つだけで済みます。この方法では、高い同時実行性の圧力が分散ロックに伝達され、分散ロックにとって大きな課題となります。
JAVAコードの実装
static Lock reenLock = new ReentrantLock();
public String findPubConfigByKey1(String key) throws InterruptedException {
PubConfig result = new PubConfig();
// 从缓存读取数据
result = redisService.getObject(PubConfigKeyConstants.TABLE_NAME + "_"+key, PubConfig.class) ;
if (result== null ) {
if (reenLock.tryLock()) {
try {
System.out.println("拿到锁了,从DB获取数据库后写入缓存");
// 从数据库查询数据
result = pubConfigRepository.queryPubConfigInfoByKey(key);
// 将查询到的数据写入缓存
Gson g = new Gson();
String value = g.toJson(result);
redisService.setNx(PubConfigKeyConstants.TABLE_NAME + "_"+key, value);
} finally {
reenLock.unlock();// 释放锁
}
} else {
// 先查一下缓存
result = redisService.getObject(PubConfigKeyConstants.TABLE_NAME + "_"+key, PubConfig.class) ;
if (result== null) {
System.out.println("我没拿到锁,缓存也没数据,先小憩一下");
Thread.sleep(100);// 小憩一会儿
return findPubConfigByKey1(key);// 重试
}
}
}
return result.getValue();
}
要約する
ビジネス システムの場合、常にケースバイケースでの分析が行われ、最適なものはなく、最適なものだけが存在します。
キャッシュの満杯やデータ損失など、その他のキャッシュの問題については、自分で学習できます。最後に、LRU、RDB、AOF という 3 つの単語について説明します。通常、私たちはオーバーフローに対処するために LRU 戦略を使用し、特定の状況下でデータのセキュリティを確保するために Redis の RDB および AOF 永続化戦略を使用します。
元のリンク: https://blog.csdn.net/fan521dan/article/details/104782315?spm=1001.2014.3001.5501