专栏名称: java一日一条
主要是讲解编程语言java,并且每天都推送一条关于java编程语言的信息
目录
相关文章推荐
芋道源码  ·  30K ... ·  13 小时前  
芋道源码  ·  Spring Cloud Gateway ... ·  昨天  
芋道源码  ·  面试官:int(1) 和 int(10) ... ·  昨天  
芋道源码  ·  Spring Boot + URule ... ·  昨天  
芋道源码  ·  Spring-Security ... ·  2 天前  
51好读  ›  专栏  ›  java一日一条

缓存穿透、缓存击穿和缓存雪崩实践

java一日一条  · 公众号  · Java  · 2019-10-14 18:11

正文

请到「今天看啥」查看全文


+ p.getId() + "数据做了缓存" ); return p; }


在这个例子里面isAllowNullValue = true表示允许换存NULL值,magnification = 10表示NULL值和非NULL值之间的时间倍率是10,也就是说当缓存值为NULL是,二级缓存的有效时间将是1个小时。


限流

应对缓存穿透的常用方法之一是限流,常见的限流算法有滑动窗口,令牌桶算法和漏桶算法,或者直接使用队列、加锁等,在layering-cache里面我主要使用分布式锁来做限流。


layering-cache数据读取流程:

数据读取流程.jpg


下面是读取数据的核心代码:

private  T executeCacheMethod(RedisCacheKey redisCacheKey, Callable valueLoader) {    Lock redisLock = new Lock(redisTemplate, redisCacheKey.getKey() + "_sync_lock");    // 同一个线程循环20次查询缓存,每次等待20毫秒,如果还是没有数据直接去执行被缓存的方法    for (int i = 0; i < RETRY_COUNT; i++) {        try {            // 先取缓存,如果有直接返回,没有再去做拿锁操作            Object result = redisTemplate.opsForValue().get(redisCacheKey.getKey());            if (result != null) {                logger.debug("redis缓存 key= {} 获取到锁后查询查询缓存命中,不需要执行被缓存的方法", redisCacheKey.getKey());                return (T) fromStoreValue(result);            }

// 获取分布式锁去后台查询数据 if (redisLock.lock()) { T t = loaderAndPutValue(redisCacheKey, valueLoader, true); logger.debug("redis缓存 key= {} 从数据库获取数据完毕,唤醒所有等待线程", redisCacheKey.getKey()); // 唤醒线程 container.signalAll(redisCacheKey.getKey()); return t; }






请到「今天看啥」查看全文