| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> 大数据 -> Redis内存淘汰策略LRU、LFU详解 -> 正文阅读 |
|
[大数据]Redis内存淘汰策略LRU、LFU详解 |
Redis内存淘汰原因Redis是一种内存数据库,redis的容量往往有限,无法存放所有的数据。当内存满了的时候,并且这个时候还需要往Redis中放入新的数据,就需要将Redis中的一部分数据淘汰了,把新的数据放进入。 Redis内存淘汰策略一个Redis中存储了很多的数据,应该选取哪部分数据进行置换呢? Redis提供了多种淘汰策略,大概分为以下五类: 1、lru通过lru,least recently used,也就是最近最久使用算法,也就是淘汰使用时间最旧的数据。 redis中的每个数据的key和value都对应着一个redisObj对象。
redisObj中有一个属性 lru,lru是一个24位的数字,保存了一个时间戳,代表着一个对象最新被使用的时间。 redisServer中维护了一个lruclock属性来表示当前系统的时间戳,每隔100ms就会调用updateLRUClock()来更新server.lruclock的值。
当新建key或者访问key的时候,会将对应的redisObj.lru = server.lruclock。 用server.lruclock的值减去redisObj.lru的值就可以得到对应key的空闲时间了 但是当server.unixtime也就是当前系统时间大于REDIS_LRU_CLOCK_MAX的时候,会将server.lruclock从0开始计数,这就会出现redisObj.lru大于server.lruclock的情况,这种情况下如何算对应的空闲时间呢?
LRU工作流程一般的LRU的做法如下: 从上述流程可以看出,基于链表和哈希表的LRU需要设置prev指针、next指针、以及hash表中的key和value的指针,这是一个很大的内存开销。 Redis并没有采用这样的做法,而是采用了随机抽取的做法、 Redis在每次进行内存的替换的时候,会随机抽取出若干个key,默认是5个,然后获取其对应的lru时间信息,淘汰lru最小的那个数据,也就是最久未被使用的数据。 lru升级 2、当每次要淘汰key的时候,会随机抽取若干个key,计算其空闲时间,如果Pool还没有满或者比Pool中的最小空闲时间Key大的话,就将空闲时间小的Key从Pool中移除,将Key加入到Pool中。 3、当要淘汰key的时候,将Pool中的空闲时间最大的key对应的数据移除内存。 其中根据抽取key的数据来源不同,将lru分为了两类: 如果不知道redisDb.expires和redisDb.dict是什么意思的话,可以看一下我之前写的关于redis中存储模型的文章Redis存储模型详解 不论是3.0之前还是3.0之后,每次抽取的key次数越多,越能体现LRU的特性,但是对应耗费的CPU资源就越大,很多时候计算机系统就是这样,鱼和熊掌不能得兼。 2、ttlttl是time to live的简称,也就是生存时间的意思,在redis中体现的就是过期时间。 volatile-ttl 3、randomrandom就是随机的意思,分为两种: 2、allkeys-random 4、lfulfu的全称是 leastly frequently used,最近最少使用,也就是挑选出最近使用次数最少的key。 使用次数也是通过redisObject中的lru字段记录的。 我们之前说过lru有24位,其中前16位用于记录最近访问时间time,单位是分钟、后8位用于记录访问次数counter。 增长 你可能会奇怪8位最多只能记录255,这不是在开玩笑吗?其实每次访问不会一定将counter++,而是通过一定的概率来判断是否将counter++。
从上述代码看出,增长概率与 server.lfu_log_factor和counter有关,server.lfu_log_factor和counter越大,增加概率越小。 但是所有的key都是共用一个server.lfu_log_factor,如果server_lfu_log_factor改变,所有key都会收到相同的影响。 而counter是每个key都对应着一个值,所以说随着key的不断访问,counter越来越大,增长速率是越来越慢的。 下图是随着factor和访问次数对counter的影响 衰减 所以redis提供了一个衰减机制。 衰减机制 与 key的空闲时间有关, key空闲时间越长,对应的counter就减少的越多。
从上述代码看出,如果一个Key在N分钟没有被访问,当衰减检查的时候,就会将其counter - N。 lfu工作过程: 当访问对应的key的时候,会更新其redisObj中的lru中的时间戳和counter信息。 和lru一样,lfu也会维护一个Pool,只不过Pool中的排序依据是counter,如果counter一致,就按照时间戳排序。 每次需要内存替换的时候,就随机抽取出若干个key,如果Pool不满,或者counter小于Pool中的最小值的话,就将key加入进去,然后选出Pool中counter值最小的那个Key,将其对应的数据从内存中移除。 volatile-lfu: allkeys-lfu: 5、no-eviction当内存不足的时候,不做任何操作。这种情形适用于某种特定的场景,比如redis中事先导入存放了非常热点的数据,但是系统偶尔会查询一些冷数据,这种情形就是适合用no-eviction。 |
|
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/24 0:48:36- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |