キャッシュ雪崩
中に発生しました
システム、5000回/秒、4,000時間がなくなってキャッシュは、唯一の1,000倍がデータベースに落ちたピークの要求が続くと仮定し、秒あたりのデータベースの並行処理1000は、通常のインジケータが動作することができている、しかし、キャッシュ一顧場合マシン、または同時にながら、キャッシュの失敗につながる、同じキャッシュの有効期限を設定し 2000年までのため、1秒抗データベース要求、毎秒5,000リクエストは、データベース上のすべての秋には、データベースはすぐに、死んでいるだろう、 DBAがデータベースを再起動する場合は、すぐに雪崩がキャッシュされる新しい要求を、殺されます。
ソリューション
- 事前:総崩壊を避け、可用性、マスタースレーブ+センチネルをRedisのクラスタをRedisの
- で物事:ehcacheをローカルキャッシュ+ hystrixは、MySQLによって殺されることを避けるために制限&ダウングレード
- その後:Redisの永続RDB + AOF、すぐにキャッシュデータを回復
- キャッシュの有効期限は、ランダムな値に設定され、障害を回避しながら、
キャッシュの浸透
中に発生しました
2番目のクライアントは4000が悪意のあるハッカーの攻撃で要求5000を送信した場合、すなわち、あなたはデータベースに見つけることができません。たとえば、ユーザIDが正の数で、ユーザーIDのハッカーの設定は、それが毎秒4000件のリクエストを送ってきた場合、ハッカーは、キャッシュは仕事、すぐに殺されたデータベースをしない、否定的です。
ソリューション
- リクエストパラメータの確認、直接不合理戻ります
- また、値がセットとして、空である、キャッシュにデータを見つけることができません-999「」
- 使用ブルームフィルタは、すぐにキーがデータベースに存在するかどうかを判断するために、何の直接のリターンはありません
キャッシュの内訳
中に発生しました
高い同時実行、ホットスポットデータを運ぶ、キーの有効期限を設定してください。このキーからのMySQL、データベースを死滅させることが可能である多数の要求からキャッシュにデータを再ロードするのに時間が期限切れ。キャッシュ手段は、ホットデータ破壊の失敗をキャッシュし、キャッシュ雪崩キャッシュミスの大きな数を参照します
ソリューション
- Setキーは無期限、または期限切れにする場合、別の非同期スレッドによるキーをリセット
- 取得するためのキャッシュからのデータは、デモを達成するために、分散ロックを書くために、ここで、プロセスからの負荷データをデータベースヌル、再ロックされると
Redisのは、分散ロックを達成します
私は、分散ロックの原則Redisの実装について書いた前の記事では、詳細な概要は、もはやありません
1.ロックを実行します
SET resource_name random_value NX PX 30000
2.ロック解除スクリプトの実行
if redis.call("get", KEYS[1]) == ARGV[1] then
return redis.call("del", KEYS[1])
else
return 0
end
分散ロック・ツールを書きます
public class LockUtil {
private static final String OK = "OK";
private static final Long LONG_ONE = 1L;
private static final String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
public static boolean tryLock(String key, String value, long expire) {
Jedis jedis = RedisPool.getJedis();
SetParams setParams = new SetParams();
setParams.nx().px(expire);
return OK.equals(jedis.set(key, value, setParams));
}
public static boolean releaseLock(String key, String value) {
Jedis jedis = RedisPool.getJedis();
return LONG_ONE.equals(jedis.eval(script, 1, key, value));
}
}
非常にシンプル書くためのツール
サンプルコード
public String getData(String key) {
String lockKey = "key";
String lockValue = String.valueOf(System.currentTimeMillis());
long expireTime = 1000L;
String value = getFromRedis(key);
if (value == null) {
if (LockUtil.tryLock(lockKey, lockValue, expireTime)) {
// 从数据库取值并放到redis中
LockUtil.releaseLock(lockKey, lockValue);
} else {
// sleep一段时间再从缓存中拿
Thread.sleep(100);
getFromRedis(key);
}
}
return value;
}
参考ブログ
[1] https://blog.csdn.net/zeb_perfect/article/details/54135506
[2] https://blog.csdn.net/kongtiao5/article/details/82771694
[3] HTTPS://www.javashitang .COM /?p = 596