Redis LRU算法

article/2025/9/29 18:15:08

一、配置Redis内存淘汰策略

maxmemory 100mbmaxmemory-policy allkeys-lrumaxmemory-samples 5

注意:Redis的LRU算法并非完整的实现,而是近似LRU的算法,详细介绍点击这里

二、LRU实现原理

1、双向链表 + 哈希表

1、哈希表:查找快,但是哈希表的数据是乱序的。
2、链表:插入、删除都很快,但是查询慢。

在这里插入图片描述

  • 1.每次默认从链表头部添加元素,那么显然越靠近头部的元素就越是最近使用的。越靠近尾部的元素就是越久未使用的。
  • 2.对于某一个 key ,可以通过哈希表快速定位到链表中的节点,从而取得对应的 value。
  • 3.链表显然是支持在任意位置快速插入和删除的,修改指针就行。但是单链表无法按照索引快速访问某一个位置的元素,都是需要遍历链表的,所以这里借助哈希表,可以通过 key,快速的映射到任意一个链表节点,然后进行插入和删除。

1、为什么这里要用双链表呢,单链表为什么不行?
答:双链表删除元素除了自己本身的指针信息,前驱节点的指针和后驱节点的指针。单链表只有后驱节点的指针。
2、哈希表里面已经保存了 key ,那么链表中为什么还要存储 key 和 value 呢,只存入 value 不就行了?
答:删除哈希表中的数据需要通过双链表中的key,才能删除对应value。

三、PHP实现LRU

源码位置

/*** LRU算法* 构造一个双向链表(双向链表删除尾部节点的上一个元素时间复杂度为O(1))*/
class LRUCache
{//头部节点private $head;//尾部节点private $tail;//最大容量,大于淘汰尾部节点指向的上一个元素private $capacity;//存放key对应的节点 key => nodeprivate $hashmap;/*** 初始化头部尾部节点* LRUCache constructor.* @param $capacity*/public function __construct($capacity){$this->capacity = $capacity;$this->hashmap = array();$this->head = new Node(null, null);$this->tail = new Node(null, null);//头结点右指针指向尾结点$this->head->setNext($this->tail);//尾结点左指针指向头结点$this->tail->setPrevious($this->head);}/*** 获取元素* @param $key* @return null*/public function get($key){if (!isset($this->hashmap[$key])) {return null;}$node = $this->hashmap[$key];if (count($this->hashmap) == 1) {return $node->getData();}//先删除已经存在的结点$this->detach($node);//重新将新结点插入到头结点之后$this->attach($this->head, $node);return $node->getData();}/*** 设置key value* @param $key* @param $data* @return bool*/public function put($key, $data){if ($this->capacity <= 0) {return false;}if (isset($this->hashmap[$key]) && !empty($this->hashmap[$key])) {$node = $this->hashmap[$key];//重置结点到头结点之后$this->detach($node);$this->attach($this->head, $node);$node->setData($data);} else {$node = new Node($key, $data);$this->hashmap[$key] = $node;//添加节点到头部节点之后$this->attach($this->head, $node);//检测容量是否达到最大值if (count($this->hashmap) > $this->capacity) {//如果达到最大值 删除尾节点左指针指向的元素$nodeToRemove = $this->tail->getPrevious();$this->detach($nodeToRemove);unset($this->hashmap[$nodeToRemove->getKey()]);}}return true;}/*** 删除key* @param $key* @return bool*/public function remove($key){if (!isset($this->hashmap[$key])) {return false;}$nodeToRemove = $this->hashmap[$key];$this->detach($nodeToRemove);unset($this->hashmap[$nodeToRemove->getKey()]);return true;}/*** 添加新结点到头结点之后* @param $head* @param $node*/private function attach($head, $node){//双向链表插入一个元素到头结点之后$node->setPrevious($head);$node->setNext($head->getNext());$node->getNext()->setPrevious($node);$node->getPrevious()->setNext($node);}/*** 删除结点* @param $node*/private function detach($node){$node->getPrevious()->setNext($node->getNext());$node->getNext()->setPrevious($node->getPrevious());}}/*** 结点数据结构*/
class Node
{private $key;//key对应的内容private $data;//结点右指针private $next;//结点左指针private $previous;/*** Node constructor.* @param $key* @param $data*/public function __construct($key, $data){$this->key = $key;$this->data = $data;}/*** 设置节点数据的新值* Sets a new value for the node data* @param string the new content of the node*/public function setData($data){$this->data = $data;}/*** 将节点设置为下一个节点* Sets a node as the next node* @param Node $next the next node*/public function setNext($next){$this->next = $next;}/*** 将节点设置为前一个节点* Sets a node as the previous node* @param Node $previous the previous node*/public function setPrevious($previous){$this->previous = $previous;}/*** 返回节点键* Returns the node key* @return string the key of the node*/public function getKey(){return $this->key;}/*** 返回节点数据* Returns the node data* @return mixed the content of the node*/public function getData(){return $this->data;}/*** 返回下一个节点, 该节点的下一个节点* Returns the next node* @return Node the next node of the node*/public function getNext(){return $this->next;}/*** 返回上一个节点, 该节点的上一个节点* Returns the previous node* @return Node the previous node of the node*/public function getPrevious(){return $this->previous;}}$lru = new LRUCache(4);
$lru->put(1, 1111);
$lru->put(2, 2222);
$lru->put(3, 3333);
//$lru->put(3, 3333);
//$lru->put(4, 4444);
//var_dump($lru->get(2));
//var_dump($lru->get(1));

学习地址


http://chatgpt.dhexx.cn/article/0DXJ8Sj2.shtml

相关文章

LRU链表介绍

文章目录 1. 简介2. LRU 组织 2.1 LRU 链表2.2 LRU Cache2.3 LRU 移动操作 2.3.1 page 加入 LRU2.3.2 其他 LRU 移动操作3. LRU 回收 3.1 LRU 更新3.2 Swappiness3.3 反向映射3.4 代码实现 3.4.1 struct scan_control3.4.2 shrink_node()3.4.3 shrink_list()3.4.4 shrink_acti…

LRU页面回收

内存回收算法总是会在一定的时间将一些内存回收&#xff0c; 内存回收算法是通过LRU链表对page页面进行管理的&#xff0c;对于那些新的页面会将其插入到LRU链表头&#xff0c;回收时将返回LRU链表末尾的元素&#xff0c;代表老化程度最高的页面 基本数据结构 typedef struct…

利用数组实现lru

LRU主要包含两个函数&#xff0c;第一个插入一个页面&#xff0c;第二个获得一个页面 主要思路如下&#xff0c;当插入页面的时候&#xff0c;所有的页面向后移动一个单位&#xff08;若果多出来一个元素舍弃掉&#xff09;&#xff0c;然后把这个页面放到数组首元素 当获得一…

什么是LRU(最近最少使用)算法?

一、什么是LRU&#xff1f; LRU&#xff08;Least Recently Used&#xff09;&#xff0c;最近最少使用。 是一种【内存管理】算法。 LRU算法基于一种假设&#xff1a; 长期不被使用的数据&#xff0c;在未来被用到的几率也不大。因此&#xff0c;当数据所占内存达到一定阈值时…

什么是LRU算法

什么是LRU LRU 英文全称&#xff08;Least recently used&#xff0c;最近最少使用&#xff09;属于典型的内存管理算法。 内存管理的一种页面置换算法&#xff0c;对于在内存中但又不用的数据块&#xff08;内存块&#xff09;叫做LRU&#xff0c;操作系统会根据哪些数据属于…

LRU缓存实现与原理

概念 LRU是 Least Recently Used 的缩写&#xff0c;即最近最少使用页面置换算法&#xff0c;是为虚拟页式存储管理服务的&#xff0c;是根据页面调入内存后的使用情况进行决策了。由于无法预测各页面将来的使用情况&#xff0c;只能利用“最近的过去”作为“最近的将来”的近似…

LRU算法的详细介绍与实现

1.背景 LRU&#xff08;least recently used-最近最少使用算法&#xff09;&#xff0c;是一种内存数据淘汰策略&#xff0c;使用常见是当内存不足时&#xff0c;需要淘汰最近最少使用的数据。LRU常用语缓存系统的淘汰策略。 2.LRU原理 LRU最早实在操作系统接触到这个算法的…

LRU原来如此简单

文章目录 前言一、LRU是什么&#xff1f;二、LFU是什么&#xff1f;三、LRU和LFU的比较四、LFU代码实现&#xff08;看懂LFU就自然懂了LRU了&#xff09;1、LFU类2、Node类3、测试 写在最后&#xff0c;感谢点赞关注收藏转发 前言 现在缓存技术在项目中随处可见&#xff0c;但…

LRU算法详解

概念理解 1.LRU是Least Recently Used的缩写&#xff0c;即最近最少使用页面置换算法&#xff0c;是为虚拟页式存储管理服务的&#xff0c;是根据页面调入内存后的使用情况进行决策了。由于无法预测各页面将来的使用情况&#xff0c;只能利用“最近的过去”作为“最近的将来”的…

LRU算法

1.什么是LRU算法 LRU算法又称最近最少使用算法&#xff0c;它的基本思想是长期不被使用的数据&#xff0c;在未来被用到的几率也不大&#xff0c;所以当新的数据进来时我们可以优先把这些数据替换掉。 在LRU算法中&#xff0c;使用了一种有趣的数据结构&#xff0c;称为哈希链…

巧用 NGINX 实现大规模分布式集群的高可用性

原文作者&#xff1a;陶辉 原文链接&#xff1a;巧用 NGINX 实现大规模分布式集群的高可用性 - NGINX开源社区 转载来源&#xff1a;NGINX开源社区 本文是我对2019年GOPS深圳站演讲的文字整理。这里我希望带给各位读者的是&#xff0c;如何站在整个互联网背景下系统化地理解Ngi…

朱邦复

朱邦复 求助编辑百科名片 朱邦复&#xff0c;仓颉输入法的发明人&#xff0c;现任香港上市公司文化传信集团的副主席。湖北省黄冈县人。为中文终端机、仓颉输入法、汉卡的发明人。由于其对中文电脑发展的众多贡献&#xff0c;台湾及香港地区的华人誉其为“中文电脑之父”、“中…

TCP/IP的底层队列实现原理

个人博客请访问 http://www.x0100.top 自从上次学习了TCP/IP的拥塞控制算法后&#xff0c;我越发想要更加深入的了解TCP/IP的一些底层原理&#xff0c;搜索了很多网络上的资料&#xff0c;看到了陶辉大神关于高性能网络编程的专栏&#xff0c;收益颇多。今天就总结一下&#…

从码农到工程师:看一下这6点!

作者&#xff1a;陶辉笔记来源&#xff1a;http://www.taohui.pub 许多程序员自称码农&#xff0c;因为每天事情总也做不完&#xff0c;而这些工作也没有给自己带来职业上的提升&#xff0c;总在原地打转&#xff0c;自己的工作似乎随时可被新人替换&#xff0c;可有可无。于是…

Nginx五大类变量详解

Nginx变量详解 文章目录 Nginx变量详解一、HTTP请求相关的变量二、TCP连接相关的变量三、Nginx处理请求过程中产生的变量四、发送HTTP响应时相关的变量五、Nginx系统变量 为了方便记忆呢&#xff0c;我把nginx的全部变量分为5种&#xff0c;详情见下图 本文内容取自极客时间陶辉…

开复博士见面会

CSDN的CTO俱乐部成立一年多来&#xff0c;做过很多次活动了。我只参加了两次&#xff0c;第二次就是开复博士的创新工厂介绍会。我对创新工厂兴趣并不大&#xff0c;但很想近距离接触一下这位声名远播的演讲者和布道者。 曾经和一个&#xff36;&#xff30;的会议上&#xff…

Nginx核心知识100讲学习笔记(陶辉)Nginx架构基础(一)

(转载&#xff0c;非常不错的文章) 一、Nginx的请求处理流程进程结构 1、Nginx的请求处理流程 2、Nginx的进程结构 3、进程作用 1、Master进程 1、是进行work进程的监控管理的2、看看work进程是否正常工作需不需要进行热部署、需不需要重新载入配置文件 2、Cache manager …

在这里,NGINX 创始人 Igor Sysoev 将亲述 NGINX 的诞生史

2020 年 5 月 20 日&#xff0c;一场 NGINX 在国内的盛会、一个所有 NGINX 用户 & 爱好者朝圣的最佳场所&#xff0c;F5 线上技术峰会 – NGINX 专场将以线上直播的形式面向所有开发者召开。届时各位 NGINX 开发者心目中的偶像 NGINX 创始人 Igor Sysoev 以及国内 NGINX 技…

如何用NGINX实现UDP四层反向代理?

原文作者&#xff1a;陶辉 原文链接&#xff1a;如何用NGINX实现UDP四层反向代理&#xff1f;- NGINX开源社区 转载来源&#xff1a;NGINX开源社区 在实时性要求较高的特殊场景下&#xff0c;简单的UDP协议仍然是我们的主要手段。 UDP协议没有重传机制&#xff0c;还适用于同时…

Nginx深度剖析,真是被大牛讲透了

开篇 Nginx是一款非常出色的服务器软件&#xff0c;从开始工作到现在&#xff0c;周围所有的公司都在使用Nginx。在多年的使用过程中&#xff0c;逐渐对Nginx的源码产生了浓厚的兴趣&#xff0c;我不满足于仅仅会使用&#xff0c;我想更加深入的理解它的内部工作原理。只有深入…