Redis LRU算法
一、配置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));
学习地址
Redis LRU算法相关推荐
- 十二、Redis LRU算法详述(Least Recently Used - 最近最少使用)
简介 Redis是基于内存存储的 key-value 数据库.我们都知道,内存虽然快但空间大小有限,当物理内存达到上限时,系统就会跑的很慢,这是因为 swap 机制会将部分内存的数据转移到swap分区 ...
- java 最少使用(lru)置换算法_「Redis源码分析」Redis中的LRU算法实现
如果对我的文章感兴趣.希望阅读完可以得到你的一个[三连],这将是对我最大的鼓励和支持. LRU是什么 LRU(least recently used)是一种缓存置换算法.即在缓存有限的情况下,如果有新 ...
- Redis LRU 淘汰原理
思考(作业):基于一个数据结构做缓存,怎么实现LRU--最长时间不被访问的元素在超过容量时删除? 问题:如果基于传统LRU 算法实现Redis LRU 会有什么问题? 需要额外的数据结构存储,消耗内存 ...
- lru算法实现 redis_Redis中的lru算法实现
lru是什么 lru(least recently used)是一种缓存置换算法.即在缓存有限的情况下,如果有新的数据需要加载进缓存,则需要将最不可能被继续访问的缓存剔除掉.因为缓存是否可能被访问到没 ...
- Redis的LRU算法
2019独角兽企业重金招聘Python工程师标准>>> 整理自官方文档:将redis当做使用LRU算法的缓存来使用 当Redis被当做缓存来使用,当你新增数据时,让它自动地回收旧数据 ...
- 将redis当做使用LRU算法的缓存来使用
当Redis被当做缓存来使用,当你新增数据时,让它自动地回收旧数据是件很方便的事情.这个行为在开发者社区非常有名,因为它是流行的memcached系统的默认行为. LRU是Redis唯一支持的回收方法 ...
- redis——Redis中的LRU算法改进
redis通常使用缓存,是使用一种固定最大内存的使用.当数据达到可使用的最大固定内存时,我们需要通过移除老数据来获取空间.redis作为缓存是否有效的重要标志是如何寻找一种好的策略:删除即将需要使用的 ...
- Redis[5] key的过期时间删除策略、实现lru算法、持久化配置
文章目录 Redis[5] key的过期时间删除策略.持久化配置 **Redis6的key过期时间删除策略** Redis服务器实际使用的是惰性删除和定期删除两种策略:通过配合使用这两种删除策略,服务 ...
- redis的lru原理_Redis的LRU算法
Redis的LRU算法 LRU算法背后的的思想在计算机科学中无处不在,它与程序的"局部性原理"很相似.在生产环境中,虽然有Redis内存使用告警,但是了解一下Redis的缓存使用策 ...
最新文章
- oracle查看联机日志,oracle联机日志和归档日志
- 人眼中亮斑的检测、定位和去除(2)
- iShow UI for React 最佳实践
- boost::errinfo_errno的用法测试程序
- Nslookup-查dns
- AtCoder Regular Contest 125
- Linux下将mysql数据导入与导出
- python2处理耗时任务_RabbitMQ Go客户端教程2——任务队列/工作队列
- 大话设计模式-策略模式与简单工厂模式
- 『震惊』秘密报告披露转基因食品危害
- 【今日CS 视觉论文速览】Thu, 13 Dec 2018
- 【Oracle】查询当前SCN
- 速进,双十一内购通道!
- ISA2000资料大全(详细)
- 计算机与英语相关工作,计算机行业岗位英语单词整合
- 配置计算机老是重启,电脑无缘无故重启是什么原因_电脑老是无故自动重启如何解决-win7之家...
- 使用RDO Packstack在CentOS 8上安装版本为Victoria的openstack
- 计算机专业黑板报迎新,新学期迎新黑板报
- Flink 实时数仓伪分布虚拟机 (所有组件部署完成)
- 百度AI的2020:新基建铺路,硬实力出圈