redis缓存总结

一、简介

其实,redis在实际项目中应用在缓存占了绝大多数场景,缓存能够有效降低访问数据库的压力,避免频繁请求数据库,一定程度上提高了系统的响应速度。一般比如临时性的文件、微信access_token等等都比较适合放在redis缓存中。

缓存工作流程图:

大体步骤:

【a】客户端发起一个请求;

【b】首先我们先去redis缓存中查询是否存在命中的数据,如果redis缓存中存在数据,则直接返回缓存中的数据,如果缓存未命中,那么这时候我们再去请求后端数据库查询;

【c】判断数据库中是否存在数据,如果存在则将数据库中查询出来的数据更新到redis缓存中,并且返回客户端,如果数据库中不存在该数据,则返回null;

【d】客户端接收到响应数据,整个请求结束;

二、缓存方式

  • key永不过期
  • 设置key过期时间

(1)、不设置过期时间

如果我们不对key设置过期时间,相当于数据永久保留的意思,那么随着时间的推移,必然会造成内存逐渐增大以及缓存中数据与数据库中的数据不同步的问题。

那么如何避免上面所说的两个问题呢?

  • 内存逐渐增大:我们可以通过设置redis的最大内存大小,让redis按照配置的策略删除不用的key信息,具体我们可以修改redis.conf如下地方:
# redis最大内存大小
maxmemory 1GB

# 内存释放策略
# MAXMEMORY POLICY: how Redis will select what to remove when maxmemory
# is reached. You can select among five behaviors:

# 五种缓存清理策略任选
# Least Recently Used
# 最近最少使用策略移除设置了过期的key
# volatile-lru -> Evict using approximated LRU among the keys with an expire set.
# 最近最少使用策略移除key
# allkeys-lru -> Evict any key using approximated LRU.

# Least Frequently Used
# 根据数据的历史访问频率来淘汰数据
# volatile-lfu -> Evict using approximated LFU among the keys with an expire set.
# allkeys-lfu -> Evict any key using approximated LFU.

# 随机清除过期的key
# volatile-random -> Remove a random key among the ones with an expire set.
# 随机清除key
# allkeys-random -> Remove a random key, any key.

# 移除最近要过期的key
# volatile-ttl -> Remove the key with the nearest expire time (minor TTL)

# 永不过期,默认策略
# noeviction -> Don't evict anything, just return an error on write operations.

# 默认使用永不过期策略maxme
mory-policy noeviction

参数说明:

maxmemory:最大内存大小,单位字节,当超出了这个限制时Redis会依据maxmemory-policy参数指定的策略来删除不需要的key直到Redis占用的内存小于指定内存
maxmemory-policy:redis删除无效key的策略

(2)、设置过期时间

设置key的过期时间,就涉及到该如何设置过期时间以及过期时间设置多大才合适。同样随着时间的推移,内存也会逐渐变大,所以我们也需要配置一下redis最大内存和key删除的策略(最近最少使用、最近最频繁使用规则等),这里建议key的过期时间不要都设置成一样的,这样的话,在某个时间点,大量的key过期,然后所有请求就直接怼到数据库去了,瞬间炸裂,其实就是避免发生缓存雪崩现象。

注意:对过期时间设置合理范围内的随机值

三、缓存穿透

缓存穿透,指的就是缓存中以及数据库中都不存在的数据,这个时候有可能是攻击者在尝试攻击网站,导致数据库压力大大增加。

解决方案:

  • 第一种方案:缓存空值key-null:采用缓存空值的方式,如果从数据库查询的对象为空,也放入缓存,只是设定的缓存过期时间较短,比如设置为60秒;
  • 第二种方案:对请求的参数在业务层进行校验;

四、缓存雪崩

缓存雪崩,在前面已经大概介绍过,指的就是如果很多key的过期时间都设置成一样,假如都设置成60分钟,那么一个小时之后,所有key都过期,所有请求就都直接到数据库了,导致数据库瞬间压力炸裂。

解决方案:

  • 针对业务场景的不同,灵活设置key的过期时间,防止同一时间大量数据过期现象发生;
  • 对热点信息设置时间长一些,对冷点数据设置时间短一些;
  • 如果缓存数据库是分布式部署,将热点数据均匀分布在不同的缓存数据库中;

五、缓存击穿

缓存击穿,指的是某个具体的key,可能承担着非常大的并发量,假如刚好到了该key的过期时间,持续续的大并发就穿破缓存,直接请求到数据库,引起数据库压力瞬间增大,造成过大压力。

解决方案:

  • 第一种方案:设置key永不过期即可;
  •  
  • 第二种方案:redis互斥锁:从缓存中获取数据,如果数据为空的话,那么就需要从数据库中查询,但是在查询数据库之前必须先获得锁;
  • 如果获得锁成功的线程才能执行查询数据库操作、更新缓存里面的数据,更新成功并且释放锁;
  • 对于没有获得锁的线程,必须先等待一会,比如休眠几秒钟之后,然后再去尝试从缓存中获取数据,这样就避免了同一时间都去数据库查询数据;

六、总结

以上就是关于redis作为缓存服务器的一些配置说明以及缓存穿透、雪崩以及击穿等的概念以及给出了相应的解决方案,在项目中注意以下几点:

  • 灵活设置redis的最大内存大小以及key删除策略;
  • 灵活配置redis中key的过期时间,不要都配置一样的过期时间,不同类别配置不同过期时间,防止缓存雪崩现象;
  • 对热点数据设置key永不过期,防止缓存击穿;

以上只是笔者学习的一些总结,希望能对小伙伴们有一点点帮助,如有不对之处,还请及时指正,相互学习。 

发布了197 篇原创文章 · 获赞 86 · 访问量 13万+

猜你喜欢

转载自blog.csdn.net/Weixiaohuai/article/details/103575357