Redis为了避免直接从后端数据库中读取数据,才诞生的一个内存数据库

那么这个避免读取,不等于将后端数据库所有的数据都缓存起来,如果将后端数据库的所有数据都缓存起来,那么性价比就降下来了,1TB的内存价格和1TB的硬盘价格是非常悬殊的,而且往往实际场景中存在八二原则,即80%的请求只访问了20%的数据,所以合理的选择将数据存入Redis才是王道

那么我们本章就从两个方面入手,分别从缓存大小的抉择和缓存淘汰策略的选择来分别讲解

1.缓存大小的抉择

缓存容量设置是否合理,会直接影响使用缓存的性价比,通常希望以最小的代价获取到最大的收益,所以将昂贵的内存资源用在关键地方非常重要了

下面有张图,蓝线代表八二原则中的数据局部性 红线就是当前应用负载下,数据局部性的变化

图片

对于蓝线,因为是八二原则的代表,所以在20%之后,就会急速的下降访问量,形成了一个长长的尾巴,称为长尾效应

在实际的使用中,因为现在应用中,用户的个性化需求越来越多,在一个业务中用户访问的数据可能并不是那集中的20%,所以导致成为了80%的访问量上去了,称之为重尾效应

所以在实际应用中,不能单一的将容量设置为后端数据库容量的20%

可以考虑将其放大或者放小,兼顾性价比和访问性能

而设置缓存的大小,可以使用如下的命令

CONFIG SET maxmemory 4gb

那么说完了缓存大小的设置之后,我们明确下如何选择淘汰的策略

Redis一共提供了8种淘汰策略

图片

不进行淘汰的,只有Noeviction

其表示在使用内存超过了maxmemory值的时候,并不会淘汰,而是在写满之后,不提供任何服务,直接返回错误

然后就是其他的内存策略,volatile-random volatile-ttl volatile-lru 和 volatile-lfu这四类分为一种,表示会删除有过期时间的key

在内存使用量达到了一定额度,或者设定的过期时间快到了,都会开启淘汰筛选策略

volatile-ttl 会按照过期时间先后进行删除

volatile-random 会在设置了过期时间的键值对中,随机删除

volatile-lru 会使用LRU算法筛选设置了过期时间的键值对

volatile-lfu 使用LFU算法筛选过期键值对

然后是allkeys-lru allkeys-random allkeys-lfu 这几种淘汰策略,其扩大了筛选范围,扩大到了所有键值对,和键值对是否设置了过期没有关系了

allkeys-random 策略,从所有键值对中随机选择并删除数据

allkeys-lru 使用LRU算法在所有数据中筛选

allkeys-lfu 使用LFU算法在所有数据中筛选

LRU算法大家并不陌生,在Redis中是如何体现的呢?

因为LRU基本上是利用链表的数据结构实现的,而Redis中维护一个所有key都存在的链表实在太过于耗时了,所以进行了简化,减轻数据淘汰对缓存性能的影响,Redis在头中记录了时间戳,然后淘汰开始的时候,会随机选出N个数据,作为一个候选集,然后淘汰一部分lru小的数据

选择多少个数据作为采样(即N),可以通过配置来设置

CONFIG SET maxmemory-samples 100

当再次出发淘汰策略的时候,Redis挑选数据进入第一次淘汰时的集合作为补充,这时候的补充挑选标准是lru字段必须要小于候选集合中最小的lru值,如果达到了N值,那么就开始淘汰

在上面的淘汰策略中

推荐使用allkeys-lru,但是这样没法设置固定值,因为固定值可能也会出现过期删除的情况,所以有固定值的时候推荐使用volatile-lru

其次我们不能指望,在淘汰的key的时候,由Redis做什么事,所以我们需要在数据被修改的时候就将其写回数据库

本章总结一下

我们说了Redis缓存大小的选型和Redis的淘汰策略,从淘汰策略来看,一种是所有的数据都是候选集,一种是设置了过期时间的数据是候选集

无论是那种候选集,都可以选择淘汰策略是随机还是LRU算法还是LFU算法,确定这些,就可以实际的使用Redis筛选了

那么最后一个问题Redis缓存是符合只读缓存还是读写缓存

是只读缓存还是读写缓存取决于实际应用中的使用方式,没有什么固定之说

发表评论

邮箱地址不会被公开。 必填项已用*标注