`
hbxflihua
  • 浏览: 659501 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

高并发下,如何防止缓存被“击穿”

阅读更多

对于一些设置了过期时间的key,如果这些key可能会在某些时间点被超高并发地访问,是一种非常“热点”的数据。这个时候,需要考虑另外一个问题:缓存被“击穿”的问题。

 

/**
	 * 启用新的get方法,防止缓存被“击穿”
	 * <p>
	 * 击穿 :缓存在某个时间点过期的时候,恰好在这个时间点对这个Key有大量的并发请求过来,
	 * 		这些请求发现缓存过期一般都会从后端DB加载数据并回设到缓存,这个时候大并发的请求可能会瞬间把后端DB压垮。
	 * 如何解决:业界比较常用的做法,是使用mutex。
	 * 		简单地来说,就是在缓存失效的时候(判断拿出来的值为空),不是立即去load db,而是先使用缓存工具的某些带成
	 * 		功操作返回值的操作(比如Redis的SETNX或者Memcache的ADD)去set一个mutex key,当操作返回成功时,再进行
	 * 		load db的操作并回设缓存;否则,就重试整个get缓存的方法。
	 * </p>
	 * @param key
	 * @param pjp
	 * @param cache
	 * @return
	 * @throws Throwable
	 */
	private Object get(final String key, final ProceedingJoinPoint pjp, final Cacheable cache) throws Throwable {
		@SuppressWarnings("unchecked")
		ValueOperations<String, Object> valueOper = redisTemplate.opsForValue();
		Object value = valueOper.get(key); // 从缓存获取数据
		if (value == null) { // 代表缓存值过期
			// 设置2min的超时,防止del操作失败的时候,下次缓存过期一直不能load db
			String keynx = key.concat(":nx");
			if (CacheUtils.setnx(keynx, "1", ExpireTime.TWO_MIN)) { // 代表设置成功
				value = pjp.proceed();
				if (cache.expire().getTime() <= 0) { // 如果没有设置过期时间,则无限期缓存
					valueOper.set(key, value);
				} else { // 否则设置缓存时间
					valueOper.set(key, value, cache.expire().getTime(), TimeUnit.SECONDS);
				}
				CacheUtils.del(keynx);
				return value;
			} else { // 这个时候代表同时候的其他线程已经load db并回设到缓存了,这时候重试获取缓存值即可
				Thread.sleep(10);
				return get(key, pjp, cache); // 重试
			}
		} else {
			return value;
		}
	}

 

分享到:
评论

相关推荐

    如何应对redis缓存雪崩,redis缓存穿透,redis缓存击穿,redis应对高并发的解决方案

    redis缓存雪崩,redis缓存穿透,redis缓存击穿 redis应对高并发造成的雪崩、穿透、击穿

    缓存击穿的现象及解决方案.pdf

    缓存击穿,也被称为热点Key问题,是指当少量被高并发访问并且缓存重建业务比较复杂的key突然失效时,无数的请求访问会在瞬间给数据库带来巨大的压力。这是因为当缓存失效后,大量的请求都会直接访问数据库,导致...

    聊聊高并发高可用那些事(Kafka、Redis、MySQL)

    - 高并发高可用方案 - Join语句还能不能用? - 主从同步有延迟怎么办? - .frm .myi .myd .ibd 文件 - 为什么表数据删掉一半,表文件大小不变? - 误删表数据除了跑路,还能干啥? - MySQL长连接导致内存溢出? - MySQL...

    深入理解高并发编程-核心技术原理

    (2)工作了3年的程序员小菜面试高并发岗位被吊打虐哭 (3)如何解决可见性和有序性问题?这次彻底懂了! 3、实战案例篇 (1) 如何实现亿级流量下的分布式限流?这些理论你必须掌握 (2) 亿级流量场景下如何为HTTP接口限流...

    Redis缓存设计与性能优化精要

    接着,针对缓存击穿与雪崩问题,提出过期时间随机化和高可用架构设计的解决方案。特别强调热点Key重建优化,避免并发高峰时的性能问题。另外,详细阐述了缓存与数据库双写一致性问题及解决策略。最后,提供了Redis...

    zxframe demo.rar

    zxframe主要用于有高访问量的项目,对高并发瓶颈有成套成熟解决方案,让你的服务稳健可用 *.支持读写分离,分库分表,读数据源熔断,数据源运行监控 *.支持JPA,既有hibernate的便捷操作,又有mybatis的sql集中编写...

    【大厂面试题】分布式详细解析及其答案

    在我们日常的开发中,无不都是使用数据库来进行数据的存储,由于一般的系统任务中通常不会存在高并发的情况,所以这样看起来并没有什么问题,可是一旦涉及大数据量的需求,比如一些商品抢购的情景,或者是主页访问量...

    Redis面试专题.pdf

    为什么高并发下有时单线程的 redis 比多线程的memcached 效率要高? 2.redis 主从复制如何实现的?redis 的集群模式如何实现?redis 的 key 是如何寻址的? 3.使用 redis 如何设计分布式锁?说一下实现思路?使用 zk...

    Redis经典面试题:redis是单线程架构还是多线程架构

    Redis是一种快速而灵活的内存数据库,以其快速读取速度、...而缓存击穿则是指当一个高访问频率的请求请求一个不存在的缓存项,这个请求会直接传递给数据源服务器,这将导致服务器爆发大量的请求,从而造成数据库崩溃。

    分布式存储极致性能Redis6视频.zip

    目录网盘文件永久链接 01_大纲简介 02_redis官网查阅和基本配置 03_逐渐又加入了多线程特性 04_多线程io多路复用入门简介...31_高并发的淘宝聚划算案例落地 32_分布式锁理论简介 33_分布式锁的起手式案例有问题 .......

    Java思维导图xmind文件+导出图片

    缓存击穿、缓存雪崩预防策略 Redis批量查询优化 Redis高性能集群之Twemproxy of Redis 数据存储 MongoDB NOSQL简介及MongoDB支持的数据类型分析 MongoDB可视化客户端及JavaApi实践 手写基于MongoDB的ORM框架...

    redisStudy.zip

    缓存穿透指的是使用不存在的key进行大量的高并发查询,这导致缓存无法命中,每次请求都要穿透到后端数据库系统进行查询,数据库压力过大。 常用解决方案:将空值缓存起来。 其他解决方案:使用布隆过滤器(guava ...

    布隆过滤器(bloom filter)及php和redis实现布隆过滤器的方法

    在一个高并发的计数系统中,如果一个key没有计数,此时我们应该返回0,但是访问的key不存在,相当于每次访问缓存都不起作用了。那么如何避免频繁访问数量为0的key而导致的缓存被击穿? 有人说, 将这个key的值置为0...

    Sivyer9303.github.io

    MenuJVM jvm错误排查手段及工具 多线程及高并发 容器类 类加载机制 堆外内存 jvm内存模型Redis 持久化与主从同步 redis为什么高效 缓存雪崩、缓存穿透、缓存击穿 一致性hash 分布式锁 redis限流 高可用设计RocketMq ...

Global site tag (gtag.js) - Google Analytics