粉丝1438获赞1.0万

说一说 redis 的过期策略和内存淘汰策略,在 redis 里面呢,它同时使用了两种过期策略,第一种就是惰性过期策略,第二种是定期过期策略。那什么是惰性过期?什么是定期过期呢?那么接下来呢,我们就一起看一下。 第一种呢,也是惰性删除,也是惰性过期。当客户端呢,尝试访问某一个 k 的时候,原理时呢,他会先检查这个 k 呢,是否设置了过期时间进行一个判断,如果说他过期了,就会立马进行一个删除,那么没有过期呢,他就不会进行一个主动删除, 这就是呢惰性删除策略,这种策略呢,就最大化的节省了我们的 cpu 资源,对不对?只有当他访问的时候呢,才会进行处理,但是呢,他对内存呢,是非常不友好的, 因为一些极端情况下呢,他可能会出现大量的过去 key, 他是没有被访问,所以呢他也不会被清除,他就占用了大量的内存,那这个怎么理解呢?为了本视频的文档,我已经整理好了,并且与往期内容一起汇入,放在了视频的最后面,坚持看完, 一定对你有关。那比如说我们这个呢是客户端,这个呢是我们的 redis, 那现在客户端呢,他就会一直带我们的 k 来进行一个访问,对不对?比如说这里是 k 一,那么 redis 呢,就会针对这个 k 一进行我们的这一个判断进行处理。 但是呢,有一些情况下,于是呢,我们这个 radis 里面呢,它存在了一部分 k, 比如说我们的 k 二 k 三,那么这部分 k 呢,它在我们之前某一段时间里面,可能呢它被频繁的访问了,那么 radis 呢就缓存起来了,但是过了那一段时间之后,我们的这些 k 呢, 他呢一直没有在被访问呢,因此呢,他的一个过期时间呢,也已经到期了,也就呢他们是无效的 k 了。但是呢,我们的惰性策略是不是只有当他访问的时候才会进行删除,因此呢,我们这部分没有在被访问的数据呢,他就会一直占用我们的 redis 的内存,这也就是惰性策略的一个缺陷,因 呢 redis 的过期策略呢,它还有一个搭配使用的,也就是呢一个定期删除,也是定期策略。 redis 呢,它每隔一段时间都会随机的抽取一部分过期的 c 呢来进行检查, 并且它是一个循环并列的方式,那么呢足够来检查我们的 k 呢是否过期了,过期就会删除我们这些已过期的 k, 我们的定期策略呢,他其实呢就是针对于我们这一部分一直没有访问的数据呢来进行检查,而且呢我们也可以调整我们这个定时扫描的时间间隔 和每次扫描的一个限定耗时,这样呢我们就可以达到我们这个 cpu 和内存资源的一个平衡,对不对?这就是 reds 的过期策略,它其实呢是通过了我们这个惰性过期和定期过期呢两种策略呢,来保证我们这一个 cpu 和内存资源的一个平衡。我们可以简单的看一下,我们 假如 redis 里面呢,当时就放了二十万个 k, 并且呢都有过期时间,如果说我们每隔一百毫秒就去检查这全部的 k, 那么我们的 cpu 负载是不是会特别的高,最后呢就可能会挂掉,所以呢,我们的 redis 它采取的第一个就是定期过期, 那每个一百毫秒呢,他是随机的抽取一定的 k 呢,来进行检查和删除,但是呢,我们是不是还会存在于很多的 k, 他是没有被删除的,因为我们这里呢只是抽取了一部分数据量的, 所以呢, redis 就还搭配的使用的一个惰性策略,那么当我们获取 k 的时候呢,他会先来检查一下,后期的话呢,也会进行一个删除。 那么需要注意的就是呢,如果说我们的定期删除漏掉了很多的过期 k, 而且他也没有走我们的惰性删除,也就是呢,他是没有来进行访问的,而我们的定期删除呢,他并没有将我们大部分过期的 k 进行一个删除, 这个时候是不是都积压在我们的内存里面了,所以呢,他也可能会导致我们这个内存溢出,又或者呢我们的业务量太大了,内存呢直接是不够用,然后就出现了一个溢出。 为了针对于这个问题呢, reds 就引入了一个内存淘汰策略,那么也就是我们开始讲的这个标题对不对?那么就是 reds 的内存淘汰策略呢,有哪一些?那么它首先一个定义呢,内存淘汰策略呢,它是允许 reds 在我们这个内存资源紧张的时候呢, 根据我们的配置的一些策略呢,主动删除我们的一些键词队,从而呢释放我们这个内存空间,保持我们这个 redis 的一个稳定性。 第一种是我们这个不淘汰的策略,他呢当我们这个内存不足的时候呢,他就直接将新写入的命呢返回一个错误,这个策略呢,他可以保证我们数据的完整性,但是呢他会导致我们这个写入操作失败,他是可以读, 但是他是不可以写的。第二种呢,就是我们最近最少使用,那么也就是呢,我们设置了过期时间的 k 里面,他会选择我们最少使用的 k, 也就是我们这个过期时间的 k, 他虽然没有到期,但是如果说你使用的很少,那么呢我们也可以将这部分少的数据呢, 先进行一个删除,先保留我们这些最常用高频使用的这些 k, 清理一些内存出来,给到我们新的数据写入,对不对?那么这就是第二种, 那么第三种呢,根据我们这个过期时间,那么它的含义呢,就是我们这个 redis 里面,是不是呢,我们有很多的 k, 每一个 k 呢,它都有自己的一个过期时间,那些剩余时间最短的 k 呢,它就会由形式的删除。 那么其实这个呢就代表呢,我们可能先放入我们这个 redis 里面的这些 key 呢,它可能会被弦删除,那比如说一个 key 呢,它是一分钟前放的,它可能还剩余四分钟,那么 有一个 k 呢,他是三分钟前放的,他只剩两分钟了,那么我们这个只剩余两分钟的这个 k 呢,他就可能会被我们这一个策略呢,先进行一个删除,保留了我们这个时间长的。第四种呢,就是随机删除,那这个呢就很好理解了,直接呢从我们这一些 过期时间 k 里面呢,直接选择一个 k 进行一个删除,但是要注意了,他是随机的,也就是呢,我不管你是使用的频繁还是使用的不频繁,还是时间长还是时间短,我选中的就直接进行删除。 第五种呢,是我们全局最近最少使用的,也就是针对于我们所有的 k 呢,来选择最少使用的 k 进行删除, 他就不管我们是否设置了过期时间,因为有一些 k 是不是呢,我们不会给他设置过期时间,也就是说呢,我们永不过期的 k 呢,他也可能会被删除,对不对?但是他是最少使用的 k, 最后一种呢,就是全局随机删除,这种呢也很简单,那么 也就是呢,我们设置了有效时间,或者是没有设置有效时间,那么他都是进行一个随机的删除,那么他也是不管你是否使用的频繁,还是剩余时间长短,是否是设置了过去时间,那么他都会被进行一个删除, 这也就是 redis 的内存淘汰策略,它呢,其实跟我们这一个过期策略呢,其实是相辅相成的对不对?他们都是为了有效的利用我们的存储空间来提高我们这个系统性能, 并且呢要防止我们这个内存溢出。那本节课的分享就到这里了,如果大家听完有些收获,记得点赞评论加关注,如果是有些疑问也可以在评论区留言讨论,我这边呢会一一进行解答。大家想获取本篇笔记呢,可以在评论区扣一,然后私信获取。


release 过期删除和内存淘汰策略? release 是一种常用的基于内存的非关系型数据库,通常用来缓存热点数据,从而达到提升访问速度的目的。 因为瑞丽丝的容量是基于内存大小,所以有可能会有大量的 k 而导致瑞丽丝产生物理内存满的现象,所以瑞丽丝提供了两种方式来处理这些 k。 第一种方式呢是过期删除,第二种方式是内存淘汰。 首先我们看一下过期策略,也就是客户端会主动给瑞丽丝的 k 设置一个过期时间,当达到过期时间以后,瑞丽丝会有相应的删除。第一种删除方式是惰性删除, 也就是不会根据过期时间来删,只有当可以被操作的时候才会去检查是否过期并进行相应的删除。这种方式呢,就有可能导致冷数据长期存在于瑞里斯当中,无法得到释放,从而占用内存。 另外一种方式呢是定期删除,但由于 radis k 过多,也不可能把所有 k 都捞出来进行查看,所以只会随机检查部分的 k, 并且清理过去数据。 当过去数据达到百分之二十五的时候呢,你再会再次进行随机检查,那如果没达到就会中断这次随机检查, 并且要控制整个定期删除的时间在一定范围内。然而过期策略无法完全保证内存不会溢出的情况,所以还需要配合内存淘汰机制。内存淘汰机制也就是 reds 内存满 来的时候,会进行相应的策略进行 k 的淘汰。第一种类呢就是默认策略,也就是在申请内存的时候操作报错。第二种是先进先出,越早过期的 k 呢,就越早删除。第三种比较简单,随机删除。 第四种是 l l u, 就是最近最少使用的 k 会先删除。那么最后一种是 l f u, 最不经常使用的 k 会先删除。最后三种呢,也会根据操作的 k 是过期 k 还是所有 k 会进行再次细分。 最后我们看一下刚才提到的几种算法设计。第一种 i 发 fo 是先进先出,那么机遇列表,也就是将新数据插入到列表的头部,将老数据从列表的尾部移出即可。第二种 l u, 就是删除最近最少使用的数据,同样在头部进行添加,尾部进行移除。当有数据被访问时,会将数据移到列表的头部即可。第三种 l f u, 就是删除最近最不经常使用, 在尾部添加和移除数据,并且在添加数据后会对整体进行一个访问的次数的排序。最后的是访问次数最少的,可以进行移除。

好,这一节我们来看一下 redis 常用操作秘密。 redis 主要是带领大家,呃,就是和大家一起回顾一下啊,回顾一下这个 我们经常使用的一些 redis 的一些命令啊,啊,无非就是像他的一个管理的命令啊,常见的一个什么管理的命令, 然后跟 key 啊,操作 key 相关的啊,可以操作。嗯,还有 super 啊, super 类型的呀,一盒类型的,还有这个六张,嗯,韩系,韩系类型的啊, 等等啊。呃,首先来看一下啊,这里就写到一个 小盆里面来,呃,启动 ready, 启动 ready 时我们可以,就是比如说你如果配置了那个 pass 就 就可以直接执行,我们一个是 plus, 你的并目就 release 杠 server 啊,就是这样来执行 release 杠 sewer, 那这个你嗯还可以指定参数啊,就是那你 redis come redis com 啊,在哪啊?我这随便写一下啊, 是你的那个 redis 点控这个配置文件啊,你放在哪了?呃,就是说还有你这个 加上 redis, 最简单的就是一一个就行了,还有 redis 看 so, 然后可以指定端口号啊,张张 port 啊,默认的是六三七九,那我可以直接六三八零是不是也可以啊?对, 好,这个是启动 redis, 启动 redis 之后我们就要进行连接啊,你配置的这个黄金边上 呃,系配置到了 pass 里面去了。看你这里就不需要点杠啊,你任意目录都可以执行,看,我这个是在呃 reds 杠 c r i 所在的目录就这样执行啊,最简单的就直接就这样可以连接,但是如果我想连接远程的啊, 这个二十七点零零表示连接本机的,但是你这个 ip 地址你可以指定其他的位置啊,六三八零幺三七九啊,根据 实际情况来连接。呃, release on c r i 那我也可以搭档啊,搭档就关,关闭, 停止是 release, 停止 release, 你还可以用 care 的,秘密就是你 release 用这个 p i d, 这个 p i d 是个字啊,不要这样去写,就是一个它的一个提成号儿啊,都可以删掉啊,都可以停止这个 release 啊。 oh, 那么你连接之后,嗯,你这连接进去之后,其实你是看联通性就直接性啊,那一般啊,如果是正常的,就是他会响应一个碰啊碰啊,那这个是 redis 常用操作命令,它 这里面的这个啊,启动命令以及连接相关的一些命令管理命令啊,这一节就先讲这里,接下来我们就讲这个可以操作的。

瑞丽时装过期 k 的删除策略有哪些?定期删除,每秒实施过期扫描,从过期字典中随机扫描二十个 k 删除,其中已经过期的建制过期比率超过四分之一就重复此步骤。惰性删除。 近期删除策略会导致部分 k 不一定被删除。多言删除会在读写一个 k 时判断这个 k 是否已过期,若已过期则删除这个 k。 每日一问, k 没有设置过去时间会不会被删除?

radius 的数据过期策略是什么? radius 使用数据过期策略来自动删除已经过期的数据,以释放内存空间并确保数据的新鲜性。 radius 的数据过期策略主要有两种,一定时删除策略 t t l time to laugh 定时删除策略是 redis 最常用的数据过期策略。每个键都可以设置一个过期时间,表示键将在一定时间内自动过期。过期时间以秒为单位,当客户端尝试访问一个已经过期的键时, redis 将自动删除该键并返回空值。二惰性删除策略 laziness 惰性删除策略是一种非常轻量级的删除策略。 redis 不会再见过期时立即删除它,而是在访问键时检查其是否过期,然后删除过期的键。这一 意味着如果某个键永远不会被访问,即使设置了过期时间,他也不会被自动删除,只有在访问时才会被删除。 redis 的过期策略在内存管理和数据自动清理方面非常有用。通过合理设置过期时间,可以确保 redis 中的数据始终保持最新, 同时不会让内存被长时间占用。开发人员可以根据数据的生命周期来选择合适的过期时间,以满足应用程序的需求。此外,过期策略也可以减少手动数据清理的工作量。


面试官问, register 的 k 过期了,内存会立即释放掉吗?这个问题看似简单,是一道送问题,但是如果你回答不全面, 它立马就会变成面试中的送命题。今天我会把 register 的 内存释放策略彻底给大家讲透。这道题其实是前天啊,我一个粉丝给我吐槽他去美团阿面遇到的这道题目,当时面试官啊就问的比较深,然后在这道题上就挂了。 通过给他复盘,我意识到很多人都可能会有一个错误的认知,所以我把这道题拿出来给大家去重点来讲讲。我们先要纠正一个误区,很多人对于 read 内存释放的理解还停留在一种理想但是错误的限行模型上, 就是 t t l 归零之后数据就会消失,然后内存就会释放。但是在高平方生产环境中啊,如果 race 真的 敢这么做啊,系统啊早就崩溃了。我们可以去设想一个场景,就比如在大错零点的关键节点,有五百万个 k 同时过期, 如果 radis 试图立即去释放内存的话,它的后果会是什么? cpu 首先会立即飙升到百分之百,主线头会卡死,因为它在疯狂的扫描删除,导致所有线上全部的请求都会超时,很明显这不是优化,而是系统性的灾难。 所以 radis 根本就没有为每个 k 都挂一个定时器。 radis 它其实采用的是 懒惰加贪婪的这种混合的策略。首先我们来看第一种机制,就是惰性删除,就是当你去访问这个 k 的 时候,他才会去检查是否应该删除, 这属于一种被动的清理策略,如果你过期了,我就删,如果没过期,就返回一个例。这种惰性删除看似比较简单高效,但是他有个致命的陷阱,就是冷数据堆积。 如果有大量设置了过期时间, k 写入之后再没有被访问过,那它们永远都不会触发惰性删除, 就像僵尸一样赖在内存里面,最终随着时间的推移不停地去堆积或占用内存空间,最终就可能导致 register 达到了 max memory 的 限制,触发 o o m 的 告警。 所以为了清理这些无人问津的冷数据,哎, register 哎,必须主动出击,这就是它的第二种策略,叫定期删除。 那这里有个面试的最大的误区,很多人都以为 register 会开一个后台县城去扫描删除 这一项,实际是删除操作依然是运行在主县城中的。它是有一个啊,周期性的任务去触发的啊,我们可以去看一下它的原码啊,这个原码我已经整理到笔记中了,我们来看一下。大家如果想自己去看 register 原码了,可以拿到这份笔记之后去找一下这个位置。 在主线段中啊,有一个啊, c r 框方法,这里面它其实依然是在主线段中跑的啊,然后这里面它会判断 判断你是不是主节点,如果是主节点,它才会执行主动过去的策略,也就意味着从节点它不会执行主动过去的策略,这里是不是又埋了一个坑啊。然后它会去辨认 rads 的 每一个 d b, 在 这里,它会去随机的从字典里面去拿到这个 k, 检测是否过期,如果过期的话就删除。注意啊,它的执行时间如果超过了二十五毫秒,它会强制地跳出循环。 这是啊 register 的 内部的定期删除的机制。 register 实际上它会啊,每一百毫秒触发一次 several coin。 它会啊,从过期的字典中啊,随机抽取二十个 key, 检查被清理其中已过期的 k。 这里有个非常核心的一个决策啊,就是如果这二十个 k 中啊过期的比例超过了百分之二十五 res, 他 会判断过去数据太多了,于是会立即重来一次抽烟和清理,进入一个贪婪的循环。 但是他也有一个止损的机制,为了防止主县城被卡死。哎,这个贪婪循环呢,他有个时间上限,就是默认的二十五毫秒。我们刚刚也看了原码,是不是一旦超时,就会强制退出循环, 将 cpu 的 使用权呢,交给正常读写的请求。但是,即使你有二十五毫秒的限制,定期删除,哎,他依然可能会引发生产的事故。 这就是著名的过期风暴。假设我们的业务代码中有一万个 k t t l 设置为同一时间过期,比如午夜的二十四点。当二十四点到来的时候,啊 register 每一轮抽样过期约都会超过百分之二十五,从而就会触发高频的贪婪循环。 虽然有二十五秒的时间限制,但高频的 cpu 占用依然会导致应用程序的响应时间出现了延迟和堵塞。这是这个点大家要注意的啊。 然后面试官他有可能就会追问,为什么我的主库内存是正常的,存库内存却爆了?这里就是因为啊,主存同步的机制与过期策略之间存在一个致命的盲区, 刚刚我们也看了原版,我们会发现存库哎,不会主动删除过期的 k 存库的多行删除啊,属于逻辑删除,它只返回了 l, 但不会释放内存,内存的释放它必须等到主库的 d l 迷你 这是不是就形成了主存延迟的一个 o m 的 风险点?如果主存网络延迟比较高的话,或者主库清理不及时,第二命令也没有及时同步,那存库是不是就会囤积大量的已过期的僵尸数据啊,最终导致存库的 o m。 那 如果我们的写入速度远远大于惰性删除和定期删除的清理速度,那锐志最后的防线就是内存淘汰策略。 这里有一个极其危险的默认配置,就是 nova casing, 它的意思是内存满了我死都不删,谁在写着我就给谁报错,直接返回 o m。 这个默认值在生产环境肯定是要避免的,我们一般会根据不同的业务场景选择合适的淘汰策略,这里有这么几种可以去考略。首先这种默认的策略是极其危险的,我们不要去考略 推荐的两种策略,其中啊,第一种就是 office l r u, 它是淘汰最近最少使用的数据,保证热点数据的命中率,我们推荐重缓存的场景去使用。 然后就是 what time l r u, 这种策略是只在设置了过期时间的 k 中进行淘汰,保护你的持久化数据不会被误删。它适合的是这种混合存储的场景,就是你同时需要持久化数据,又需要缓存数据的场景。 那最后我们来总结一下,如果遇到这道面试题,你可以这么回答,面试官,首先你告诉面试官啊, register 过期删除并不是准时的,而是惰性删除和定期删除配合完成的,而且定期删除它会运行在主县城哦。 然后你再去深入细节告诉面试官,定期删除它是概域抽样,它有时长限制是二十五毫秒,而且在主存架构下,存库被动等待主库同步的 dl 命令, 储藏延迟会导致存库内存的问题。最后啊,你可以告诉面试官,生产环境中,我们可以做三层防御,第一层就是在业务层,我们可以使用 ttl 加随机值打散过期,防止过期风暴。 在配置层,如果是重缓存,我们可以使用 or case l r u。 如果是混合存储,我们可以使用 welcome l r u。 如果面试官问你大概的场景,你可以告诉他,在 res 四之后啊,他有一个一步删除,我们可以避免主县城的卡顿。 关于这段面试题,大家还有什么疑问,可以评论区聊聊。通过这道面试题,我们其实可以意识到,技术没有玄学,全是权衡。 res 之所以这么设计过去策略, 他其实是在以下三者做了极致的妥协和权衡。第一就是 cpu 的 算力,他不为每个 k 创建定时器。第二就是内存空间,他必须允许少量过期的时间暂时的留存。第三呢,就是要考虑系统稳定性,要防止主线成长期堵塞。 理解了这些,你就真正懂得了 register 的 设计哲学。关于这道面试题完成的笔记,我已经整理好放到我的大厂高频面试题中了,有需要的同学可以自取。我是 fox, 关注我技术面试不迷路。

当面试官问到 readys 分 布式锁,别只说 set n x, 一 分钟讲三个高级优化,我项目里用它临时锁,一是支持重入,用哈希存锁, key 是 锁名, file 是 现成 id, value 是 重入次数,解锁时次数简易。 二是自动续期,开守护现成,快过期时刷新过期时间,比如三十秒锁,二十秒续一次。我把完整的实战题和场景题已经打包好了,包含了一系列的图文项目等放在粉丝群了,希望能够帮助到你。 三是防死锁加扩记时间加撸二原则,删锁加守护现成续期。我优化后,锁的可用性从百分之九十九点五升到百分之九十九点九九,再也没有出现过死锁或者误删锁避坑点。续期现成要和业务现成绑定,避免续期错锁。你优化过分布式锁吗?评论区说说。