LRU是Last Recent Used 缩写,做为一种缓存算法,将最近较少使用的缓存失效。memcache采用了该算法。如下采用了一种PHP的实现方式。该算法将每次新增的内容,放到缓存顶部,达到缓存极限时,将缓存底部的内容清除。可以通过如下PHP代码来模拟。
<?php class LRUCache { private $head; private $tail; private $capacity; private $hashmap; 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); } public function get($key) { if (!isset($this->hashmap[$key])) { return null; } $node = $this->hashmap[$key]; if (count($this->hashmap) == 1) { return $node->getData(); } // refresh the access $this->detach($node); $this->attach($this->head, $node); return $node->getData(); } public function put($key, $data) { if ($this->capacity <= 0) { return false; } if (isset($this->hashmap[$key]) && !empty($this->hashmap[$key])) { $node = $this->hashmap[$key]; // update data $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); // check if cache is full if (count($this->hashmap) > $this->capacity) { // we're full, remove the tail $nodeToRemove = $this->tail->getPrevious(); $this->detach($nodeToRemove); unset($this->hashmap[$nodeToRemove->getKey()]); } } return true; } private function attach($head, $node) { $node->setPrevious($head); $node->setNext($head->getNext()); $node->getNext()->setPrevious($node); $node->getPrevious()->setNext($node); } private function detach($node) { $node->getPrevious()->setNext($node->getNext()); $node->getNext()->setPrevious($node->getPrevious()); } } /** * Class that represents a node in a doubly linked list */ class Node { private $key; // the content of the node private $data; // the next node private $next; // the previous node private $previous; public function __construct($key, $data) { $this->key = $key; $this->data = $data; } public function setData($data) { $this->data = $data; } public function setNext($next) { $this->next = $next; } public function setPrevious($previous) { $this->previous = $previous; } public function getKey() { return $this->key; } public function getData() { return $this->data; } public function getNext() { return $this->next; } public function getPrevious() { return $this->previous; } }