雪崩キャッシュ、なぜならキャッシュ破壊の問題と解決策のキャッシュ貫通

キャッシュ雪崩

中に発生しました

システム、5000回/秒、4,000時間がなくなってキャッシュは、唯一の1,000倍がデータベースに落ちたピークの要求が続くと仮定し、秒あたりのデータベースの並行処理1000は、通常のインジケータが動作することができている、しかし、キャッシュ一顧場合マシン、または同時にながら、キャッシュの失敗につながる、同じキャッシュの有効期限を設定し 2000年までのため、1秒抗データベース要求、毎秒5,000リクエストは、データベース上のすべての秋には、データベースはすぐに、死んでいるだろう、 DBAがデータベースを再起動する場合は、すぐに雪崩がキャッシュされる新しい要求を、殺されます。

ここに画像を挿入説明
ソリューション

  1. 事前:総崩壊を避け、可用性、マスタースレーブ+センチネルをRedisのクラスタをRedisの
  2. で物事:ehcacheをローカルキャッシュ+ hystrixは、MySQLによって殺されることを避けるために制限&ダウングレード
  3. その後:Redisの永続RDB + AOF、すぐにキャッシュデータを回復
  4. キャッシュの有効期限は、ランダムな値に設定され、障害を回避しながら、

キャッシュの浸透

中に発生しました

2番目のクライアントは4000が悪意のあるハッカーの攻撃で要求5000を送信した場合、すなわち、あなたはデータベースに見つけることができません。たとえば、ユーザIDが正の数で、ユーザーIDのハッカーの設定は、それが毎秒4000件のリクエストを送ってきた場合、ハッカーは、キャッシュは仕事、すぐに殺されたデータベースをしない、否定的です。

ここに画像を挿入説明
ソリューション

  1. リクエストパラメータの確認、直接不合理戻ります
  2. また、値がセットとして、空である、キャッシュにデータを見つけることができません-999「」
  3. 使用ブルームフィルタは、すぐにキーがデータベースに存在するかどうかを判断するために、何の直接のリターンはありません

キャッシュの内訳

中に発生しました

高い同時実行、ホットスポットデータを運ぶ、キーの有効期限を設定してください。このキーからのMySQL、データベースを死滅させることが可能である多数の要求からキャッシュにデータを再ロードするのに時間が期限切れ。キャッシュ手段は、ホットデータ破壊の失敗をキャッシュし、キャッシュ雪崩キャッシュミスの大きな数を参照します

ソリューション

  1. Setキーは無期限、または期限切れにする場合、別の非同期スレッドによるキーをリセット
  2. 取得するためのキャッシュからのデータは、デモを達成するために、分散ロックを書くために、ここで、プロセスからの負荷データをデータベースヌル、再ロックされると

Redisのは、分散ロックを達成します

私は、分散ロックの原則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

公開された385元の記事 ウォンの賞賛1471 ビュー90万+

おすすめ

転載: blog.csdn.net/zzti_erlie/article/details/104655455