Redis应用之缓存实现

举报
波波烤鸭 发表于 2022/03/30 01:27:13 2022/03/30
【摘要】 文章目录 Redis缓存1.缓存概述2.缓存方式2.1不设置过期时间2.2设置过期时间 3.名称解释缓存穿透缓存雪崩缓存击穿 4.总结   Redis的众多应用场景中缓存绝对是...


Redis缓存

1.缓存概述

  缓存(Cache)的作用是减少服务器对数据源的访问频率,从而提高数据库的稳定性。访问的流程如下。
在这里插入图片描述
流程图
在这里插入图片描述
代码逻辑

public Goods searchArticleById(Long goodsId){
	Object object = redisTemplate.opsForValue().get(String.valueOf(goodsId));
	if(object != null){// 缓存查询到了结果
		return (Goods)object;
	}
	// 开始查询数据库
	Goods goods = goodsMapper.selectByPrimaryKey(goodsId);
	if(goods!=null){
		// 将结果保存到缓存中
		redisTemplate.opsForValue().set(String.valueOf(goodsId),goods,60,TimeUnit.MINUTES);;
	}
	return goods;
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

2.缓存方式

  缓存中的数据在redis中的存储方式有两种,一种是永久存在,不设置过期时间,第二种是设置过期时间。这两种方式都需要尽可能的保证数据的一致性(和数据源中的数据保持同步)。

2.1不设置过期时间

  当我们将缓存数据的key设置为永久存在时会存在数据同步和内存消耗逐渐增大的情况,解决方式如下:
数据同步

  1. 禁止直接操作数据源,避免因数据源直接被改动而造成缓存数据不一致的问题
  2. 如果有其他系统操作同一个数据源,这种情况肯定会产生数据不一致的情况。
  3. 系统执行DML操作时,应该将缓存中对应的数据删除。用户下一次相关请求时直接从数据源中获取。

内存消耗
  随着业务的增多,缓存数据必然会越来越多,所占用的内存也随之增多,系统的压力也会变大,这时一种方式是给key设置过期时间,但是过期时间长短不太好把握,这时我们可以通过设置redis最大内存来实现,并让Redis按照一定的规则淘汰不需要的缓存键,这种方式在redis只作为缓存使用时非常实用。
具体实现方式:修改redis配置文件(redis.conf)中的maxmemory参数既可,限制Redis最大可用内存大小(单位字节),当超出了这个限制时Redis会依据maxmemory-policy参数指定的策略来删除不需要的key直到Redis占用的内存小于指定内存。
在这里插入图片描述

规则 说明
volatile-lru 使用LRU算法删除一个key(只对设置了过期时间的key有效)
allkeys-lru 使用LRU算法删除一个key
volatile-lfu 使用LFU算法删除一个key(只对设置了过期时间的key有效)
allkeys-lfu 使用LFU算法删除一个key
volatile-random 随机删除一个key(只对设置了过期时间的key有效)
allkeys-random 随机删除一个key
volatile-ttl 删除过期时间最近的一个key
noeviction 不删除key,只返回错误

LRU:(Least recently used,最近最少使用)算法根据数据的历史访问记录来进行淘汰数据,其核心思想是“如果数据最近被访问过,那么将来被访问的几率也更高”
LFU:(Least Frequently Used)算法根据数据的历史访问频率来淘汰数据,其核心思想是“如果数据过去被访问多次,那么将来被访问的频率也更高”。

2.2设置过期时间

  对保存到Redis中的key设置过期时间,但同样也会遇到问题,比如过期时间怎么设置,内存资源同样也会过大。
内存资源
  同样需要设置maxmemory来限制redis使用的最大内存和配置maxmemory-policy来指定删除策略。
过期时间设置
  过期时间不要设置统一固定的时间,比如60分钟,这样会造成相同时间点大量缓存被清空,数据库访问量突然增大的情况,我们应该对过期时间设置合理范围内的随机值。比如:采取不同分类商品,缓存不同周期。在同一分类中的商品,加上一个随机因子。这样能尽可能分散缓存过期时间,而且,热门类目(女装)的商品缓存时间长一些,冷门类目(图书)的商品缓存时间短一些,也能节省缓存服务的资源。

public Goods searchArticleById(Long goodsId){
	Object object = redisTemplate.opsForValue().get(String.valueOf(goodsId));
	if(object != null){// 缓存查询到了结果
		return (Goods)object;
	}
	// 开始查询数据库
	Goods goods = goodsMapper.selectByPrimaryKey(goodsId);
	if(goods!=null){
		Random random = new Random();
		// 将结果保存到缓存中
		if(goods.getGoodsCategory().equals("女装")){
			int time = 3600 + random.nextInt(3600);
			// 热门商品
			redisTemplate.opsForValue()
						.set(String.valueOf(goodsId)
							,goods
							,time
							,TimeUnit.MINUTES);
		}else{
			int time = 600 + random.nextInt(600);
			// 冷门商品
			redisTemplate.opsForValue()
						.set(String.valueOf(goodsId)
							,goods
							,time
							,TimeUnit.MINUTES);
		}
	}else{
		// 防止缓存穿透
		redisTemplate.opsForValue()
						.set(String.valueOf(goodsId)
							,null
							,60
							,TimeUnit.MINUTES);
	}
	return goods;
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37

3.名称解释

缓存穿透

  缓存穿透,是指查询一个数据库一定不存在的数据。正常的使用缓存流程大致是,数据查询先进行缓存查询,如果key不存在或者key已经过期,再对数据库进行查询,并把查询到的对象,放进缓存。如果数据库查询对象为空,则不放进缓存。

public Goods searchArticleById(Long goodsId){
	Object object = redisTemplate.opsForValue().get(String.valueOf(goodsId));
	if(object != null){// 缓存查询到了结果
		return (Goods)object;
	}
	// 开始查询数据库
	Goods goods = goodsMapper.selectByPrimaryKey(goodsId);
	if(goods!=null){
		// 将结果保存到缓存中
		redisTemplate.opsForValue().set(String.valueOf(goodsId),goods,60,TimeUnit.MINUTES);
	}else{
redisTemplate.opsForValue().set(String.valueOf(goodsId),null,60,TimeUnit.SECONDS);
	}
	return goods;
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

  采用缓存空值的方式,如果从数据库查询的对象为空,也放入缓存,只是设定的缓存过期时间较短,比如设置为60秒。

缓存雪崩

  缓存雪崩,是指在某一个时间段,缓存集中过期失效.解决方式就是上面设置过期时间中使用的方式,灵活设置过期时间。

缓存击穿

  缓存击穿,是指一个key非常热点,在不停的扛着大并发,大并发集中对这一个点进行访问,当这个key在失效的瞬间,持续的大并发就穿破缓存,直接请求数据库,就像在一个屏障上凿开了一个洞。解决方式直接设置为永久key就可以了。mutex key互斥锁可以学习下,但一般情况下用不上!

4.总结

  搞清楚了缓存的这些知识点我们选择就比较清楚了,具体的灵活使用。

  1. 设置Redis最大使用内存是必须的。
  2. 通过不同的策略设置过期时间。
  3. 如果是热点key我们可以直接设置为永久key。

文章来源: dpb-bobokaoya-sm.blog.csdn.net,作者:波波烤鸭,版权归原作者所有,如需转载,请联系作者。

原文链接:dpb-bobokaoya-sm.blog.csdn.net/article/details/88615333

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。