JAVA并发编程与高并发解决方案 - 视频第12章(高并发之缓存思路)
别人的博文整理了视频中的内容,我就mark就好了。
https://suprisemf.github.io/2018/08/03/缓存之特征、场景和组件介绍a/
https://suprisemf.github.io/2018/08/03/缓存之初识Redis/
https://suprisemf.github.io/2018/08/03/高并发下缓存的常见问题/
其中第二篇博文中稍微补充点东西
redis的小例子
RedisConfig
package com.mmall.concurrency.example.cache;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import redis.clients.jedis.JedisPool;
@Configuration
public class RedisConfig {
@Bean(name = "redisPool")
public JedisPool jedisPool(@Value("${jedis.host}") String host,
@Value("${jedis.port}") int port) {
return new JedisPool(host, port);
}
}
RedisClient
package com.mmall.concurrency.example.cache;
import org.springframework.stereotype.Component;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import javax.annotation.Resource;
// http://redis.cn/
@Component
public class RedisClient {
@Resource(name = "redisPool")
private JedisPool jedisPool;
public void set(String key, String value) throws Exception {
Jedis jedis = null;
try {
jedis = jedisPool.getResource();
jedis.set(key, value);
} finally {
if (jedis != null) {
jedis.close();
}
}
}
public String get(String key) throws Exception {
Jedis jedis = null;
try {
jedis = jedisPool.getResource();
return jedis.get(key);
} finally {
if (jedis != null) {
jedis.close();
}
}
}
}
CacheController
package com.mmall.concurrency.example.cache;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
@RequestMapping("/cache")
public class CacheController {
@Autowired
private RedisClient redisClient;
@RequestMapping("/set")
@ResponseBody
public String set(@RequestParam("k") String k, @RequestParam("v") String v)
throws Exception {
redisClient.set(k, v);
return "SUCCESS";
}
@RequestMapping("/get")
@ResponseBody
public String get(@RequestParam("k") String k) throws Exception {
return redisClient.get(k);
}
}
其中第三篇博文中稍微补充点东西
缓存的雪崩现象
缓存雪崩就是指由于缓存的原因,导致大量请求到达后端数据库,从而导致数据库崩溃,整个系统崩溃,发生灾难。导致这种现象的原因有很多种,上面提到的“缓存并发”,“缓存穿透”,“缓存颠簸”等问题,其实都可能会导致缓存雪崩现象发生。这些问题也可能会被恶意攻击者所利用。还有一种情况,例如某个时间点内,系统预加载的缓存周期性集中失效了,也可能会导致雪崩。为了避免这种周期性失效,可以通过设置不同的过期时间,来错开缓存过期,从而避免缓存集中失效。
从应用架构角度,我们可以通过限流、降级、熔断等手段来降低影响,也可以通过多级缓存来避免这种灾难。
此外,从整个研发体系流程的角度,应该加强压力测试,尽量模拟真实场景,尽早的暴露问题从而防范。