赞
踩
@PostConstruct初始化数据
大量key同时过期
主从+哨兵
Redis Cluster
开启Redis持久化机制aof/rdb,尽快恢复缓存集群
ehcache本地缓存+redis缓存
Hystrix或者阿里sentinel限流&降级
阿里云-云数据库Redis版
先查redis无,后查mysql无,都查询不到该条记录,但是请求每次都会打到数据库上面去,导致后台数据库压力暴增
恶意攻击:不同key打入缓存,由于存在空对象缓存和缓存回写(看自己业务需求),redis中的无关紧要的key也会越写越多(设置缓存过期时间)
白名单案例
全部合法的key都需要放入Guava版布隆过滤器+redis里面,不然数据就是返回nul
POM
<!--guava Google 开源的 Guava 中自带的布隆过滤器-->
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>23.0</version>
</dependency>
YML
server.port=7777 spring.application.name=redis # ========================logging===================== logging.level.root=info logging.level.com.atguigu.redis7=info logging.pattern.console=%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger- %msg%n logging.file.name=redis.log logging.pattern.file=%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger- %msg%n # ========================swagger===================== spring.swagger2.enabled=true #在springboot2.6.X结合swagger2.9.X会提示documentationPluginsBootstrapper空指针异常, #原因是在springboot2.6.X中将SpringMVC默认路径匹配策略从AntPathMatcher更改为PathPatternParser, # 导致出错,解决办法是matching-strategy切换回之前ant_path_matcher spring.mvc.pathmatch.matching-strategy=ant_path_matcher # ========================redis单机===================== spring.redis.database=0 # 修改为自己真实IP spring.redis.host=192.168.1.129 spring.redis.port=6379 spring.redis.password=111111 spring.redis.lettuce.pool.max-active=8 spring.redis.lettuce.pool.max-wait=-1ms spring.redis.lettuce.pool.max-idle=8 spring.redis.lettuce.pool.min-idle=0 # ========================alibaba.druid===================== spring.datasource.type=com.alibaba.druid.pool.DruidDataSource spring.datasource.driver-class-name=com.mysql.jdbc.Driver spring.datasource.url=jdbc:mysql://localhost:3306/datatest?useUnicode=true&characterEncoding=utf-8&useSSL=false spring.datasource.username=root spring.datasource.password=111111 spring.datasource.druid.test-while-idle=false # ========================mybatis=================== mybatis.mapper-locations=classpath:mapper/*.xml mybatis.type-aliases-package=com.atguigu.redis7.entities # ========================redis集群===================== #spring.redis.password=111111 ## 获取失败 最大重定向次数 #spring.redis.cluster.max-redirects=3 #spring.redis.lettuce.pool.max-active=8 #spring.redis.lettuce.pool.max-wait=-1ms #spring.redis.lettuce.pool.max-idle=8 #spring.redis.lettuce.pool.min-idle=0 ##支持集群拓扑动态感应刷新,自适应拓扑刷新是否使用所有可用的更新,默认false关闭 #spring.redis.lettuce.cluster.refresh.adaptive=true ##定时刷新 #spring.redis.lettuce.cluster.refresh.period=2000 #spring.redis.cluster.nodes=192.168.111.185:6381,192.168.111.185:6382,192.168.111.172:6383,192.168.111.172:6384,192.168.111.184:6385,192.168.111.184:6386
案例
@Test public void testGuavaWithBloomFilter() { //1 创建guava版布隆过滤器 BloomFilter<Integer> bloomFilter = BloomFilter.create(Funnels.integerFunnel(), 100); //2 判断指定的元素是否存在 System.out.println(bloomFilter.mightContain(1)); System.out.println(bloomFilter.mightContain(2)); System.out.println(); //3 讲元素新增进入bloomfilter bloomFilter.put(1); bloomFilter.put(2); System.out.println(bloomFilter.mightContain(1)); System.out.println(bloomFilter.mightContain(2)); }
黑名单案例
大量的请求同时查询一个 key 时,此时这个key正好失效了,就会导致大量的请求都打到数据库上面去
常见问题:热点key失效
分析
问题:热点key突然失效导致缓存击穿
升级加固
多个线程同时去查询数据库的这条数据,在第一个查询数据的请求上使用一个互斥锁来锁住它。
其他的线程走到这一步拿不到锁就等着,等第一个线程查询到了数据,然后做缓存。后面的线程进来发现已经有缓存了,就直接走缓存。
// Controller method @RequestMapping(value = "/pruduct/find",method = RequestMethod.GET) @ApiOperation("聚划算案例,每次1页每页5条显示") public List<Product> find(int page, int size) { List<Product> list=null; long start = (page - 1) * size; long end = start + size - 1; try { // 采用redis list结构里面的lrang命令来实现加载和分页查询 list = redisTemplate.opsForList().range(JHS_KEY,start,end); if(CollectionUtils.isEmpty(list)) { //TODO 走mysql查询 } log.info("参加活动的商家:{}",list); }catch (Exception e){ // 出异常了,一般redis宕机了或者redis网络抖动导致timeout log.error("jhs exception:{}",e); e.printStackTrace(); // ....再次查询mysql } return list; }
// 模拟数据 @PostConstruct public void initJHSAB(){ log.info("启动AB定时器计划任务天猫聚划算功能模拟.........."+DateUtil.now()); //1 用线程模拟定时任务,后台任务定时将mysql里面的参加活动的商品刷新到redis里 new Thread(() -> { while (true) { //2 模拟从mysql查出数据,用于加载到redis并给聚划算页面显示 List<Product> list = this.getProductsFromMysql(); //3 先更新B缓存且让B缓存过期时间超过A缓存,如果A突然失效了还有B兜底,防止击穿 redisTemplate.delete(JHS_KEY_B); redisTemplate.opsForList().leftPushAll(JHS_KEY_B,list); redisTemplate.expire(JHS_KEY_B,86410L,TimeUnit.SECONDS); //4 再更新A缓存 redisTemplate.delete(JHS_KEY_A); redisTemplate.opsForList().leftPushAll(JHS_KEY_A,list); redisTemplate.expire(JHS_KEY_A,86400L,TimeUnit.SECONDS); //5 定时更新缓存,模拟聚划算一天执行的参加活动的品牌 try { TimeUnit.MINUTES.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } } },"t1").start();
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。