Cache avalanche
Occurred during
Suppose there follows a system, the peak request 5000 times / second, 4,000 times gone cache, only 1,000 times fell on the database, the database concurrency 1000 per second is a normal indicator can work, but if the cache dang machine, or set the same cache expiration time, leading to failure of the cache while at the same time , 5,000 requests per second will all fall on the database, the database immediately is dead, because one second anti database request up to 2000, If the DBA to restart the database, it will be killed immediately a new request, which is cached avalanche.
Solution
- Beforehand: redis availability, master-slave + Sentinel, redis cluster, avoiding total collapse
- Things in: ehcache local cache + hystrix limiting & downgrade to avoid being killed by MySQL
- Afterwards: redis persistence RDB + AOF, quickly recover cache data
- Cache expiration time is set to a random value, while avoiding failure
Cache penetration
Occurred during
If the second client sends a request 5000, where 4000 is the malicious hacker attacks, i.e., you can not find in the database. For example, the user id is a positive number, user id hackers configuration is negative, if it has been sent 4000 requests per second, the hacker, the cache does not work, the database quickly killed.
Solution
- Checking the request parameters, return directly unreasonable
- Also can not find the data into the cache, value is empty, as set -999 ""
- Use Bloom filter, to quickly determine whether a key is present in the database, there is no direct return
Cache breakdown
Occurred during
Set an expiration time of the key, carrying high concurrency, a hotspot data. From this key expired some time to reload the data into the cache from MySQL, a large number of requests it is possible to kill the database. Refers to a large number of cache avalanche cache miss, the cache means caches hot data breakdown failure
Solution
- Set key never expires, or when to expire, resetting the key by another asynchronous thread
- When the data from the cache to get is null, re-lock the database to load data from the process, here to write a distributed lock to achieve demo
Redis achieve Distributed Lock
Previous article I wrote about the principle Redis implementation of distributed locks, there is no longer a detailed overview
Redis distributed lock Why write?
1. Run the lock
SET resource_name random_value NX PX 30000
2. Unlock script execution
if redis.call("get", KEYS[1]) == ARGV[1] then
return redis.call("del", KEYS[1])
else
return 0
end
Write a distributed lock tools
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));
}
}
Tools to write quite simple
Sample Code
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;
}
Reference blog
[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