Redis(Remote Dictionary Server ),即远程字典服务,是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库。是我们研发人员的查询存储临时数据的利器,虽然它速度快,支持高并发,多种业务都会融合到缓存,但要用好它,可不是那么简单的事情。下面我们就跟随卢卡的视角来去寻找一下Redis内存淘汰背后的故事。
背景
第一次提到一个内存淘汰,是因为业务中很多过期数据,已经将缓存的速度拖的很慢,而且一直在库中的数据留存下去,额,虽然说已经没有实际意义了,但是至少证明它之前存在过,数据的心声,作为Redis的管理员conf大佬, 就给他们上课了,将数据整理好,确定好标签,给他们找寻数据最后的归属。
数据听了顿时留下了眼泪,踌躇满志的想要重新来过,等啊等啊。就是到了过期时间, 它还是没有被0号库的皇帝召见,看来等待它的就只能默默的离开了。逐渐地,数据感觉自己被冷落了,皇帝也不喜欢我了,说着就开始给淘汰机制的警察诉苦,当时是他给我标注的,说好会一直待我好,现在呢,就不爱了,渣男,呸。
作为淘汰警察的内存掌控者,每天这样的事情也已经习惯了, 谁让是缓存呢,对吧,好的东西就是比较稀有,人家就是有特权选择你们这些单纯的数据,淘汰警察说的话一次次的牵动着数据的心, 看来只有哭诉,才可以让以后的生活成长起来。经历过缓存的丢弃,渣男的抛弃,数据在一次在淘汰警察的鼓励下,站了起来,我以后要跟你混。
淘汰警察耐心的告诫数据,以后的路要自己好好走,我这里可是很复杂的,你有信心去走向远方吗?
数据,直接坚定的说了一句, YES ,SIR,(话说给淘汰警察整的不会了)
那你要是有兴趣,就先留下来吧,说着,数据眼角留下了热泪,温柔的笑了起来。
迎接你新的生活吧,淘汰警察慢吞吞的说到!
备注:其实conf大佬是Redis的配置文件
数据缓存第一集(被缓存警察上课一天)
数据跟淘汰警察历险记
第二天,一大早数据就被,淘汰警察喊醒了,告诉你今天第一个任务,获取最新的内存情况
也就是将你一样,被0号库皇帝管理的韭菜数据,他们要获取一下他们现在的总体情况,你先去交接一下 memory大哥,把这个info的令牌带着, 先去找你command妹妹,告诉他要查一下 内存情况;
实例情况:
缓存Redis的内存情况,用命令 info memory,可以获取到;
看到最新的内存情况的,数据很是高兴, 刚要回家,就看到淘汰警察给的任务卡上还有任务, 既然有挑战,那我就要完成,数据已经决定了,开始向着下个任务驶入;
任务一:
缓存Redis内存如何配置,生产环境中一般配置多少?
数据一看,这个配置,只能去寻找conf大哥了, 屁颠屁颠的去找了conf大哥让他查查内存配置,正好看见数据是新手,就给他指明一条路;
如果默认没有配置Redis的内存,64位操作环境下,一般不限制内存大小;
但是conf大哥,细心的告诉数据, 想要配置内存,也是有技巧的;
数据认真的听了起来
生产环境缓存内存配置:
生产环境,公司一般会配置 当前主内存的四分之三,(Redis底层用hash算法,负载因子是0.75)
如何设置Redis的内存:
方法1:可以通过conf来设置
maxmemory <bytes>
单位是字节: 1024字节-1kb
1048576是1MB=1024*1024
比如:
maxmemory 1048576000 //代表1000MB
方法2:使用命令来配置
对于命令一般存储在config中
启动redis , redis -cli
config get maxmemory
config set maxmemory 104857600
任务二:
当Redis的内存满了,会发生什么情况?
数据一看这个任务,感觉要起义的感觉,内存总有一天要被我们数据占据,到时候看看鹿死谁手,
实例情况:
我将最大内存设置为1字节,
127.0.0.1:6379> config set maxmemory 1
OK
127.0.0.1:6379> set key1 hello
(error) OOM command not allowed when used memory > 'maxmemory'.
Redis内存已满
任务三:
Redis数据满了之后,如何淘汰数据?
数据一看,这不就是我之后的生活吗,我得好好表现,
这个还得从conf大哥那边找找灵感,说着就跑去找conf大哥了,
默认的Redis conf文件中,对于淘汰数据;
maxmemory-policy noeviction(不会驱逐数据的一种数据策略)
如果内存够,基本都可以保存下来;
面试题:
在内存中,当前一个键值对(key-value)是过期的,数据是否会立刻被删除呢?
set k1 hello ex 10 10秒失效
答案:当一个key过期,标识不可用之后,不会立刻删除
因为会有过期键值对的策略在起作用
卢卡寄语
数据在淘汰警察的任务下,逐渐了解了内存的细节情况, 对于内存中最大数据,配置,以及过期保存都有了一定的了解,接下来会是对Redis,key值中过期策略的制定, 果然: 淘汰警察说,数据你还有很远的路要走。
数据缓存第二集(被过期键经理上了一课)
背景
上回说到,数据已经完成了基本的三个任务,获取了conf大哥赏识,其中淘汰警察也对它评价很高,这次淘汰警察就给数据出了个挑战,题目为,一个过期数据,在内存中是如何被淘汰的,会经历什么?
带着这个问题,我们从小数据的视角开始冒险吧。
任务一:数据过期后会遇到什么?
起初,数据经过过期时间后,会在内存中晃荡,不会立马删除,数据会慢慢的遇见第一个经理,名为过期键的删除策略
这个经理可不得了,手里有三大利器;
分别是:
①定时删除
②惰性删除:
③ 定期删除:
这个三把利器,可以让过期键策略,在数据淘汰中,占据大半江山, 基本上可以处理一半的数据,而且效率也不错;说着就让数据自己选一个 ,经理不想亲自动手,
可萌可萌的数据这时候却糊涂了起来, 慢通通的说,这三种利器有啥区别啊,到底有什么厉害之处啊, (数据心里有点不服气,就算是死了,也要死得其所)
既然你这么诚心的份上,那我就给你讲讲我的宝贝,果然是初生牛犊不怕虎,过期键经理心里默念道,感情是要给我上课的,不行,让你装到我还以后怎么在淘汰数据界中混,今天高低也要把你办了?
数据可要小心了, 过期键经理可不是说说而已
说着就端起了,第一件珍宝:
定时删除
本质上:
最大程度保持数据的新鲜度, 但是每次都有挂载一个定时任务去扫描,是否临界过期时间, 产生大量的性能消耗
对CPU造成额外的压力, (用时间换取空间)
细节分析:
Redis不可能时时刻刻遍历所有被设置了生存时间的key,来检测数据是否已经到达过期时间,然后对它进行删除
立即删除能保证内存中数据的最大新鲜度,因为它保证过期键值会在过期后马上被删除,其所占用的内存也会随之释放。但是立即删除对cpu是最不友好的。因为删除操作会占用cpu的时间,如果刚好碰上了cpu很忙的时候,比如正在做交集或排序等计算的时候,就会给cpu造成额外的压力,让CPU心累,时时需要删除,忙死。。。。。..
这会产生大量的性能消耗,同时也会影响数据的读取操作
惰性删除
本质上:
当前访问数据,发现数据过期,不会马上删除
等下次,访问,数据过期,会加载删除
redis中过期,但是没有删除,内存中存储大量的过期数据, 对内存不友好,对于CPU友好,
数据到达过期时间,不做处理,等下次访问该数据
如果未过期,就返回数据
发现已经过期,删除,返回不存在
考虑的问题?
如果一个键key已经过期,而这个键又仍然保留在数据库中,那么只要这个过期键不被删除,它所占用的内存就不会释放。
在使用惰性删除策略时,如果数据库中有非常多的过期键,而这些过期键又恰好没有被访问到的话,那么它们也许永远也不会被删除(除非用户手动执行FLUSHDB),我们甚至可以将这种情况看作是一种内存泄漏-无用的垃圾数据占用了大量的内存,而服务器却不会自己去释放它们,这对于运行状态非常依赖于内存的Redis服务器来说,肯定不是一个好消息
定期删除:
对内存和时间CPU进行两者中和;
本质上:
每隔一段时间执行一次删除过期键的操作,并通过 限制删除操作的时长和频率来减少对CPU时间的影响
过期键经理的总结
虽然我这三大法宝,功能都是删除数据的,但是用的比较多的,对于时间空间,内存CPU影响比较小的方式,选择 “定期删除”,因为有很大的优势:
周期性比较强:
特点一: CPU可以自定义检测频率时长
特点2: 内存压力减少, 长期过期数据会被持续清理
随机抽查,
好处是:大大提高我们内存删除的效率,但是因为是随机抽查的,所以,会存在漏网之鱼
面试官在线:
面试官: 不错不错,这三种策略但是还是不能完全解决redis内存的问题, 如果说定期删除从来没有被抽查到呢,
惰性删除时,过期键值,但是没有被访问到, 持续如此,redis中存在大量的key, 你可以说说你的思路吗?
答案是:那我们有大招, 缓存淘汰策略
过期键的删除策略,不能保证内存, 这就要使用大招, 内存淘汰策略了:
数据内心独白
原来,我们之前的兄弟数据,都是被定时删除,不定时的惰性删除,和定期删除解决掉了, 看来这些淘汰警察的手段很硬,硬钢划不来,我要继续做卧底,看看他们是如何将我淘汰掉,
卢卡寄语
数据经过对于过期键经理的折磨, 冒死送出了一份淘汰警察的数据处理过程, 目前是 经过了第二关,听说还有缓存淘汰策略BOSS在等着他, 数据也算是厉害,
明天数据,要开始LRU、LFU,TTL,和RANDOM的淘汰策略中去,基于两个维度,四个方面,八条策略,全方位的展示 淘汰警察的手段,期待数据的带来的好消息了
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。