Redis-预热雪崩击穿穿透

news/2024/12/22 14:00:52/

预热雪崩穿透击穿

缓存预热

缓存雪崩

有这两种原因

  1. redis key 永不过期or过期时间错开
  2. redis 缓存集群实现高可用
    1. 主从哨兵
    2. Redis Cluster
    3. 开启redis持久化aof,rdb,尽快恢复集群
  3. 缓存结合预防雪崩:本地缓存 ehcache + redis 缓存
  4. 服务降级:Hystrix 或者 sentinel 限流降级
  5. 人民币玩家:阿里云给了你多少广告?笑

缓存穿透

恶意请求不存在的数据

  1. guava BloomFilter

  • 误判问题,但是概率小可以接受,不能从布隆过滤器删除 -> 布隆过滤器可能会错误地判断某个元素存在于集合中(称为误报),但不会错误地判断一个存在的元素不存在
  • 全部合法的key都需要放入 Guava布隆过滤器+redis里面,不然数据就是返回null

案例

<dependency><groupId>com.google.guava</groupId><artifactId>guava</artifactId><version>31.1-jre</version>
</dependency>
@Service
@Slf4j
public class GuavaBloomFilterService {// 1.定义一个常量public static final int _1W = 10000;// 2.定义我们guava布隆过滤器,初始容量public static final int SIZE = 100 * _1W;// 3.误判率,它越小误判的个数也越少(思考:是否可以无限小? 没有误判岂不是更好)public static double fpp = 0.0000000000003;  // 这个数越小所用的hash函数越多,bitmap占用的位越多  默认的就是0.03,5个hash函数   0.01,7个函数// 4.创建guava布隆过滤器private static BloomFilter<Integer> bloomFilter = BloomFilter.create(Funnels.integerFunnel(), SIZE, fpp);public void guavaBloomFilter() {// 1. 往 bloomFilter 中添加数据for (int i = 0; i < SIZE; i++) {bloomFilter.put(i);}// 2. 故意取10w个不在范围内的数据进行测试,来进行误判率演示List<Integer> list = new ArrayList<>(10 * _1W);// 3. 验证for (int i = SIZE; i < SIZE + (10 * _1W); i++) {if (bloomFilter.mightContain(i)) {
//                log.info("被误判了:{}", i);list.add(i);}}log.info("误判总数量:{}", list.size());log.info("误判率:{}", list.size() / (10 * _1W));}
}
@SpringBootTest
public class GuavaTest {@ResourceGuavaBloomFilterService guavaBloomFilterService;/*** guava版本布隆过滤器,helloworld 入门级演示*/@Testpublic void testGuavaWithBloomFilter() {System.out.println("testGuavaWithBloomFilter");// 1. 创建 guava版布隆过滤器BloomFilter<Integer> bloomFilter = BloomFilter.create(Funnels.integerFunnel(), 100);//2. 判断指定的元素是否存在System.out.println(bloomFilter.mightContain(1));System.out.println(bloomFilter.mightContain(2));// 2. 添加数据bloomFilter.put(1);bloomFilter.put(2);System.out.println(bloomFilter.mightContain(1));System.out.println(bloomFilter.mightContain(2));}@Testpublic void testGuavaWithBloomFilter2() {guavaBloomFilterService.guavaBloomFilter();}}

fpp 默认 0.03

fpp要求越高,bit位数越多,hash函数越多

guava 黑名单使用

缓存击穿

对比穿透和击穿

互斥更新->对于更新的方法

聚划算案例

功能分析

数据结构使用 list

代码

@ApiModel(value = "聚划算活动product信息")
@AllArgsConstructor
@NoArgsConstructor
@Data
public class Product {// 产品idprivate Long id;// 产品名称private String name;// 产品价格private Integer price;// 产品详情private String detail;
}
@Service
@Slf4j
public class JHSTaskService {private static final String JHS_KEY = "jhs";private static final String JHS_KEY_A = "jhs:a";private static final String JHS_KEY_B = "jhs:b";@AutowiredRedisTemplate redisTemplate;/*** 模拟从数据库读取20件特价商品* @return 商品列表*/private List<Product> getProductsFromMysql() {List<Product> list = new ArrayList<>();for (int i = 0; i < 20; i++) {Random random = new Random();int id = random.nextInt(1000);Product product = new Product((long) id, "product" + i, i, "detail");list.add(product);}log.info("模拟从数据库读取20件特价商品完成{}", list);return list;}@PostConstructpublic void initJHSAB() {log.info("启动AB的定时器 天猫聚划算模拟开始===========");new Thread(() -> {while (true) {// 2.模拟从mysql查到数据,加到 redis 并返回给页面List<Product> list = getProductsFromMysql();redisTemplate.delete(JHS_KEY);redisTemplate.opsForList().leftPushAll(JHS_KEY, list);redisTemplate.expire(JHS_KEY, 86410L, TimeUnit.SECONDS);// 5.暂停一分钟,间隔1分钟执行一次,模拟聚划算一天执行的参加活动的品牌try {Thread.sleep(1000* 60);} catch (InterruptedException e) {e.printStackTrace();}}}, "t1").start();}}

测试类

@SpringBootTest
@Slf4j
public class JhsTest {private static final String JHS_KEY = "jhs";private static final String JHS_KEY_A = "jhs:a";private static final String JHS_KEY_B = "jhs:b";@Autowiredprivate RedisTemplate redisTemplate;@Testpublic void find() {int page = 1;int size = 10;List<Product> list = null;long start = (page - 1) * size;long end = start + size - 1;try {list = redisTemplate.opsForList().range(JHS_KEY, start, end);if (CollectionUtils.isEmpty(list)) {// TODO 走 mysql 查询}log.info("参加活动的商家={}", list);} catch (Exception e) {// 出异常了,一般 redis 宕机了或者redis网络抖动导致timeoutlog.error("jhs exception{}", e);e.printStackTrace();//  ..... 重试机制 再次查询 mysql}log.info(list.toString());}}

测试方法,先跑主启动类(后台更新聚划算商品信息),然后手动执行测试类测试查询

问题分析

delete 执行间隙,这一瞬间缓存击穿,打到mysql

解决

@PostConstructpublic void initJHSAB() {log.info("启动AB的定时器 天猫聚划算模拟开始===========");new Thread(() -> {while (true) {// 2.模拟从mysql查到数据,加到 redis 并返回给页面List<Product> list = getProductsFromMysql();//                redisTemplate.delete(JHS_KEY);
//                redisTemplate.opsForList().leftPushAll(JHS_KEY, list);
//                redisTemplate.expire(JHS_KEY, 86410L, TimeUnit.SECONDS);// 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.暂停一分钟,间隔1分钟执行一次,模拟聚划算一天执行的参加活动的品牌try {Thread.sleep(1000* 60);} catch (InterruptedException e) {e.printStackTrace();}}}, "t1").start();}
@Testpublic void findAB() {int page = 1;int size = 10;List<Product> list = null;long start = (page - 1) * size;long end = start + size - 1;try {list = redisTemplate.opsForList().range(JHS_KEY_A, start, end);if (CollectionUtils.isEmpty(list)) {log.info("---------A缓存已经过期或活动结束了,记得人工修补,B缓存继续顶着");// A 没有来找 Blist = redisTemplate.opsForList().range(JHS_KEY_B, start, end);if (CollectionUtils.isEmpty(list)) {// TODO 走 mysql 查询}}log.info("参加活动的商家={}", list);} catch (Exception e) {// 出异常了,一般 redis 宕机了或者redis网络抖动导致timeoutlog.error("jhs exception{}", e);e.printStackTrace();//  ..... 重试机制 再次查询 mysql}log.info(list.toString());}

小总结


http://www.ppmy.cn/news/1536291.html

相关文章

如何制作一个企业网站,建设网站的基本步骤有哪些?

企业网站是企业的门面和名片&#xff0c;决定网民对企业的第一印象&#xff0c;因此&#xff0c;现在很多公司想做一个属于自己网站&#xff0c;但是不知道怎么做&#xff0c;更不知道从何做起&#xff0c;更别说做成了。为了能够让大家清楚如何做一个企业网站&#xff0c;现在…

前端练习小项目 —— 让图片变得更 “色”

前言&#xff1a;相信读者在学习完了HTML、CSS和JavaScript之后已经想要迫不及待的想找一个小型的项目来练练手&#xff0c;那么这篇文章就正好能满足你的 “需求”。 ✨✨✨这里是秋刀鱼不做梦的BLOG ✨✨✨想要了解更多内容可以访问我的主页秋刀鱼不做梦-CSDN博客 在开始学习…

【项目安全设计】软件系统安全设计规范和标准(doc原件)

1.1安全建设原则 1.2 安全管理体系 1.3 安全管理规范 1.4 数据安全保障措施 1.4.1 数据库安全保障 1.4.2 操作系统安全保障 1.4.3 病毒防治 1.5安全保障措施 1.5.1实名认证保障 1.5.2 接口安全保障 1.5.3 加密传输保障 1.5.4终端安全保障 资料获取&#xff1a;私信或者进主页。…

解决json格式转换被特殊字符截断问题

SyntaxError&#xff1a;Unexpected end of JSON input 当我们使用navigateTo跳转传参的时候&#xff0c;在小程序中需要先转换为json字符串的格式化&#xff0c;但是如果我们传递的参数中有特殊字符的&#xff1f;/&amp的话&#xff0c;可能导致字符串被截断&#xff0c;此…

OpenHarmony(鸿蒙南向开发)——标准系统方案之瑞芯微RK3566移植案例(上)

往期知识点记录&#xff1a; 鸿蒙&#xff08;HarmonyOS&#xff09;应用层开发&#xff08;北向&#xff09;知识点汇总 鸿蒙&#xff08;OpenHarmony&#xff09;南向开发保姆级知识点汇总~ 持续更新中…… 本文章是基于瑞芯微RK3566芯片的khdvk_3566b开发板&#xff0c;进行…

系统架构设计师-英文翻译题(2022年下半年)

Micro-service is a software development technology, which advocates dividing a single application into a group of small services, which coordinates and cooperates with each other to provide ultimate value for users. 微服务是一种软件开发技术&#xff0c;它主…

【JavaEE】http/https 超级详解

&#x1f525;个人主页&#xff1a; 中草药 &#x1f525;专栏&#xff1a;【Java】登神长阶 史诗般的Java成神之路 &#x1f98a;一.定义 HTTP&#xff08;HyperText Transfer Protocol&#xff09;即超文本传输协议&#xff0c;他是应用非常广泛的应用层协议&#xff0c;是…

「Java开发指南」如何用MyEclipse为iPhone搭建Spring应用程序?

本教程将引导您完成在iPhone上使用的软件组件生成&#xff0c;这就产生了一个完全实现的可运行iPhone应用程序&#xff0c;可以立即用于验证和测试生成的iPhone组件。在本教程中&#xff0c;您将学习如何&#xff1a; 从数据库表搭建到现有项目部署应用程序 MyEclipse v2024.…