做网站 做app好,湛江建设厅网站,平台游戏,山西网站建设运营公司目录
1.redis的基本策略
2.Redis中的缓存淘汰策略 3.Redis内存不足的情况 4.几种淘汰策略的实现原理
5.项目实践与优化策略
5.1 配置案例
5.2 项目优化策略参考 数据库存储会将数据保存到磁盘中#xff0c;而Redis的核心数据是在内存中的#xff0c;而Redis本身主要用来…目录
1.redis的基本策略
2.Redis中的缓存淘汰策略 3.Redis内存不足的情况 4.几种淘汰策略的实现原理
5.项目实践与优化策略
5.1 配置案例
5.2 项目优化策略参考 数据库存储会将数据保存到磁盘中而Redis的核心数据是在内存中的而Redis本身主要用来做缓存当 Redis 的内存达到最大限制时会发生什么情况redis 会怎么处理呢
Redis性能很高官方给的数据 读110000次/s写 81000次/s。但是长期使用Key会不断增加Redis作为缓存使用物理内存也会满内存与硬盘交换(swap)虚拟内存也会被占满频繁的IO操作会导致性能急剧下降。
在使用Redis时我们一般会为Redis的缓存空间设置一个大小不会让数据无限制地放入Redis缓存中。可以使用下面命令来设定缓存的大小比如设置为4GB
既然 Redis 设置了缓存的容量大小那缓存被写满就是不可避免的。当缓存被写满时我们需要考虑下面两个问题决定淘汰哪些数据如何处理那些被淘汰的数据?
进而 我们可以提出几个连环炮问题
第一问如果不处理让redis的内存达到最大会出现什么情况
第二问如果必须淘汰掉一些过期数据该淘汰谁
第三问一种淘汰策略够吗还有哪些常见的策略不同策略分别适合什么类型的业务
第四问淘汰策略该如何配置是否会对系统性能产生影响
事实上面试也经常是这样从简单问题开始用连环炮的方式不断递递进直到我们的知识盲区。
1.redis的基本策略
redis的过期策略可以概括为两种情况定期删除 惰性删除
定期删除redis默认每隔100ms就随机抽取一些设置了过期时间的key检查其是否过期如果有过期就删除。注意这里是随机抽取的。为什么要随机呢你想一想假如 redis 存了几十万个 key 每隔100ms就遍历所有的设置过期时间的 key 的话就会给 CPU 带来很大的负载。
那为什么不用定时删除策略呢 定时删除用一个定时器来负责监视key过期则自动删除。虽然内存及时释放但是十分消耗CPU资源。在大并发请求下CPU要将时间应用在处理请求而不是删除key因此没有采用这一策略。
惰性删除定期删除可能导致很多过期的key 到了时间并没有被删除掉。这时就要使用到惰性删除。在你获取某个key的时候redis会检查一下这个key如果设置了过期时间并且过期了是的话就删除。
定期删除 惰性删除存在的问题。如果某个key过期后定期删除没删除成功然后也没再次去请求key也就是说惰性删除也没生效。这时如果大量过期的key堆积在内存中redis的内存会越来越高导致redis的内存块耗尽。那么就应该采用内存淘汰机制。
2.Redis中的缓存淘汰策略
介绍缓存策略之前我们先看几种常见的通用缓存处理算法 1.最近最少使用Least Recently Used, LRULRU 策略会根据键的最近使用时间来判断其热度。当内存空间不足时会优先淘汰最久未使用的键即最近最少被使用的键。 2.先进先出First In, First Out, FIFOFIFO 策略按照键的插入顺序来决定淘汰顺序。最先插入的键会被最先淘汰。 3.最少使用Least Frequently Used, LFULFU 策略根据键被访问的频率来决定淘汰顺序。访问次数较少的键会被优先淘汰。 4.随机Random随机策略会随机选择要淘汰的键。 Redis提供了8种缓存淘汰策略如下 1、noeviction不进行淘汰数据。一旦缓存被写满再有写请求进来Redis就不再提供服务而是直接返回错误。Redis 用作缓存时实际的数据集通常都是大于缓存容量的总会有新的数据要写入缓存这个策略本身不淘汰数据也就不会腾出新的缓存空间我们不把它用在 Redis 缓存中。 2、volatile-ttl在设置了过期时间的键值对中移除即将过期的键值对。 3、volatile-random在设置了过期时间的键值对中随机移除某个键值对。 4、volatile-lru在设置了过期时间的键值对中移除最近最少使用的键值对。 5、volatile-lfu在设置了过期时间的键值对中移除最近最不频繁使用的键值对 6、allkeys-random在所有键值对中随机移除某个key。 7、allkeys-lru在所有的键值对中移除最近最少使用的键值对。 8、allkeys-lfu在所有的键值对中移除最近最不频繁使用的键值对。 虽然看起来很多但其实很简单。
noeviction就是不淘汰。volatile打头的就是从设置了过期时间的元素中移除一些 相对应的allkeys就是从全部键中选择。很明显前者速度快但是不彻底后者正好相反。以lru为后缀的就是使用最近最少使用的策略以lfu就是最近最不频繁的策略random就是随机选。
通常情况下推荐优先使用 allkeys-lru 策略。这样可以充分利用 LRU 这一经典缓存算法的优势把最近最常访问的数据留在缓存中提升应用的访问性能。 如果你的业务数据中有明显的冷热数据区分建议使用 allkeys-lru 策略。 如果业务应用中的数据访问频率相差不大没有明显的冷热数据区分建议使用 allkeys-random 策略随机选择淘汰的数据就行。 如果没有设置过期时间的键值对那么 volatile-lruvolatile-lfuvolatile-random 和 volatile-ttl 策略的行为, 和 noeviction 基本上一致。但是一般来说allkeys-lru和volatile-lru是使用最广泛的策略。 3.Redis内存不足的情况
Redis故障个人经验不是很多这里通过查阅整理了几种常见的redis内存不足的提示信息和原因解释我们一起来看一下
错误信息解释OOM command not allowed when used memory Redis 的内存已经耗尽无法执行当前命令。Redis out of memoryRedis 已经耗尽了可用的内存无法继续存储更多的数据。如果内存不足时读数据也可能失败。Max number of clients reached Redis 已经达到最大连接数限制无法接受更多的客户端连接。命令执行缓慢当 Redis 的内存接近饱和状态时性能可能会下降。由于 Redis 需要进行内存淘汰操作来释放空间这可能会导致命令执行的延迟增加。内存淘汰命中率下降为了腾出内存空间Redis 会根据配置的内存淘汰策略清除一些键。这可能导致一些数据被删除从而影响应用程序的行为例如缓存命中率下降等。连接失败当 Redis 内存不足以处理更多的客户端连接时新的连接请求可能会被拒绝或延迟处理。这可能导致连接失败或长时间等待。 4.几种淘汰策略的实现原理
在Redis的设计中内存淘汰的实现原理与其数据结构和管理机制紧密关联不同的内存淘汰策略有不同的实现方式。 一般来说volatile-*策略适合大部分键值对都设置了过期时间的场景而*lru策略则适合数据的重要性随时间逐渐降低的场景。当然这些策略都不是定死的可能需要根据实际情况进行调整和优化。
首先当我们开启Redis的maxmemory策略并设置了相应的内存上限后Redis就会在达到这个上限时触发数据淘汰操作。这个操作是如何进行的呢它主要依赖于Redis的内存淘汰策略。
我们以allkeys-lru策略为例这个策略的原理是什么呢
LRU代表Least Recently Used即最近最少使用。Redis为每个存储在内存中的key都维护了一个LRU标识这个标识用于记录该key最后一次被访问的时间。当Redis需要淘汰数据时它会从所有的key中挑选一部分key检查它们的LRU标识然后淘汰其中最少被访问的key。
这就好比我们收拾房间当空间不足时我们会选择几乎不用的东西进行淘汰以便腾出空间。
同理volatile-lru策略也是基于LRU原理只不过它只会考虑那些设置了过期时间的key。
allkeys-random和volatile-random策略则是在所有key或者设置了过期时间的key中随机选择一个进行淘汰就像是“闭眼摸象”。
volatile-ttl策略则是在设置了过期时间的key中找出生存时间TTL最短的进行淘汰也就是“谁生命短谁先走”。
我们再次描述一下每种策略的淘汰方式
volatile-ttl策略则是在设置了过期时间的key中找出生存时间TTL最短的进行淘汰也就是“谁生命短谁先走”。noeviction实现原理十分简单就是当内存达到上限时对于所有的写操作都返回错误。allkeys-lru它的实现基于Redis的数据结构和LRULeast Recently Used最近最少使用策略。在Redis中每个键值对都有一个LRU字段表示这个键值对上一次被访问的时间。当内存达到上限时Redis会观察一部分键值对的LRU字段选择其中LRU值最小即最久未被访问的键值对进行淘汰。volatile-lru与allkeys-lru类似只不过它只对设置了过期时间的键值对进行观察和淘汰。allkeys-random每当需要淘汰数据时Redis随机选取一部分键值对然后从中随机淘汰一个。这种方式的优点是简单且开销较小缺点是淘汰的数据可能是重要的数据。volatile-random与allkeys-random类似只是它只对设置了过期时间的键值对进行随机淘汰。volatile-ttl这个策略的实现也依赖Redis的数据结构。每个设置了过期时间的键值对都有一个ttltime to live生存时间字段。当内存达到上限时Redis会观察一部分设置了过期时间的键值对的ttl字段选择其中ttl值最小即最快过期的键值对进行淘汰。 Redis中的LRU算法并没有严格按照常规的LRU算法的方式实现而是基于LRU算法的思想做了自己的优化。我们知道实现LRU算法时需要将所有的数据按照访问时间距离当前时间的长短排序放到一个双向链表中基于这个链表实现数据的淘汰。但Redis中存储的数据量是非常庞大的如果要基于常规的LRU算法就需要把所有的key全部放到这个双向链表中这样就会导致这个链表非常非常大不止需要提供更多的内存来存放这个链表结构而且操作这么庞大的链表的性能也是比较差的。
所以Redis中的LRU算法是这样实现的首先定义一个淘汰池这个淘汰池是一个数组大小为16然后触发淘汰时会根据配置的淘汰策略先从符合条件的key中随机采样选出5可在配置文件中配置个key然后将这5个key按照空闲时间排序后放到淘汰池中每次采样之后更新这个淘汰池让这个淘汰池里保留的总是那些随机采样出的key中空闲时间最长的那部分key。需要删除key时只需将淘汰池中空闲时间最长的key删掉即可。
为了方便理解它的思想放上一张图原始地址
5.项目实践与优化策略
5.1 配置案例
当你配置 Redis 的淘汰策略时你可以通过编辑 Redis 配置文件来实现。 。可以根据需要将 maxmemory-policy 设置为你选择的淘汰策略例如 allkeys-lru、volatile-lfu 等。同时你还可以使用 maxmemory 配置项来设置 Redis 的最大内存限制。rdbcompression 用于启用在内存中存储数据时的压缩它减少了数据占用的内存空间。其次rdbcompression 用于在进行 RDB 快照持久化时启用压缩以减小生成的 RDB 文件的大小。
# 当达到最大内存限制时Redis 的淘汰策略
# 可选值noeviction禁止淘汰, allkeys-lruLRU算法, allkeys-lfuLFU算法, allkeys-random随机淘汰,
# volatile-lruLRU算法仅针对设置了过期时间的键, volatile-lfuLFU算法仅针对设置了过期时间的键,
# volatile-random随机淘汰仅针对设置了过期时间的键
# 默认值noeviction
maxmemory-policy noeviction# Redis 的最大内存限制以字节为单位。
# 当达到最大内存限制时Redis 将根据淘汰策略进行键的淘汰。
# 默认值0无限制
maxmemory 102400# 启用压缩存储
# 开启压缩存储可以减少存储数据所占用的内存空间但会增加 CPU 负载。
# 默认值no
rdbcompression yes# 保存 RDB 文件时启用压缩
# 当进行 RDB 快照持久化时启用压缩可以减少 RDB 文件的大小。
# 默认值no
rdbcompression yes5.2 项目优化策略参考
在项目中我们可以参考如下原则来优化
定时删除TTL可以为 Redis 中的键设置过期时间Time To LiveTTL让键在一定时间后自动过期并被删除。这样可以确保过期的键及时被清除释放内存空间。
延迟删除Lazy Expire延迟删除是一种优化手段当键过期时并不立即删除而是在访问该键时才进行删除操作。这可以减少删除操作的开销并在实际需要时进行键的清除。
内存碎片整理Memory Defragmentation在 Redis 中当删除一些键后可能会导致内存出现碎片化。这些碎片化的内存空间无法被有效利用。内存碎片整理是一种优化手段通过重新分配内存来整理碎片化的内存空间以提高内存的利用率。
压缩存储Memory CompressionRedis 4.0 版本引入了内存压缩Memory Compression功能使用 LRU 算法对键进行压缩以减少内存使用。压缩存储可以在某些场景下显著降低内存占用。
内存分配器优化Redis 使用的内存分配器可以影响其性能和内存管理。选择适合的内存分配器如 jemalloc可以提高 Redis 的性能和内存利用率。
redis缓存在使用的时候还会存在很多问题其中最常见的也是面试经常考的就是击穿, 穿透, 雪崩, 污染四个问题。这几个概念是什么意思 以及如何解决在这里有比较好的解释了我们就不细说了。