LRU算法原理,图片来自https://mp.weixin.qq.com/s/h_Ns5HY27NmL_odCYLgx_Q:
1.假设我们使用哈希链表来缓存用户信息,目前缓存了4个用户,这4个用户是按照时间顺序依次从链表右端插入的
2.此时,业务方访问用户5,由于哈希链表中没有用户5的数据,我们从数据库中读取出来,插入到缓存当中。这时候,链表中最右端是最新访问到的用户5,最左端是最近最少访问的用户1。
3.接下来,业务方访问用户2,哈希链表中存在用户2的数据,我们怎么做呢?我们把用户2从它的前驱节点和后继节点之间移除,重新插入到链表最右端。这时候,链表中最右端变成了最新访问到的用户2,最左端仍然是最近最少访问的用户1
4.接下来,业务方请求修改用户4的信息。同样道理,我们把用户4从原来的位置移动到链表最右侧,并把用户信息的值更新。这时候,链表中最右端是最新访问到的用户4,最左端仍然是最近最少访问的用户1。
5.后来业务方换口味了,访问用户6,用户6在缓存里没有,需要插入到哈希链表。假设这时候缓存容量已经达到上限,必须先删除最近最少访问的数据,那么位于哈希链表最左端的用户1就会被删除掉,然后再把用户6插入到最右端。
GO程序实现:
/*
@Time : 18-11-5 上午10:41
@Author : xbx
@File : lru
@Software: GoLand
*/
package main
import "fmt"
type Node struct {
Key string
Value string
pre *Node
next *Node
}
func (n *Node)Init(key string, value string){
n.Key = key
n.Value = value
}
var head *Node
var end *Node
var limit int
type LRUCache struct {
limit int
HashMap map[string]*Node
}
func GetLRUCache(limit int) *LRUCache{
lruCache := LRUCache{limit:limit}
lruCache.HashMap = make(map[string]*Node, limit)
return &lruCache
}
func (l *LRUCache)get(key string) string{
if v,ok:= l.HashMap[key];ok {
l.refreshNode(v)
return v.Value
}else {
return ""
}
}
func (l *LRUCache)put(key , value string) {
if v,ok := l.HashMap[key];!ok{
if(len(l.HashMap) >= l.limit){
oldKey := l.removeNode(head)
delete(l.HashMap, oldKey)
}
node := Node{Key:key, Value:value}
l.addNode(&node)
l.HashMap[key] = &node
}else {
v.Value = value
l.refreshNode(v)
}
}
func (l *LRUCache) refreshNode(node *Node){
if (node == end) {
return
}
l.removeNode(node)
l.addNode(node)
}
func (l *LRUCache) removeNode(node *Node) string{
if (node == end ) {
end = end.pre
}else if(node == head){
head = head.next
}else {
node.pre.next = node.next
node.next.pre = node.pre
}
return node.Key
}
func (l *LRUCache) addNode(node *Node){
if (end != nil){
end.next = node
node.pre = end
node.next = nil
}
end = node
if (head == nil) {
head = node
}
}
func main(){
lruCache := GetLRUCache(5)
lruCache.put("001", "用户1信息")
lruCache.put("002", "用户1信息")
lruCache.put("003", "用户1信息")
lruCache.put("004", "用户1信息")
lruCache.put("005", "用户1信息")
lruCache.get("002")
lruCache.put("004", "用户2信息更新")
lruCache.put("006", "用户6信息更新")
fmt.Println(lruCache.get("001"))
fmt.Println(lruCache.get("006"))
fmt.Print(lruCache.HashMap)
}
|
请发表评论