LRU算法在后端工程师面试中,是一个比较常出现的题目,这篇文章带大家一起,理解LRU算法,并最终用Python轻松实现一个基于LRU算法的缓存。
LRU是什么
LRU是一种缓存淘汰算法(在OS中也叫内存换页算法),由于缓存空间是有限的,所以要淘汰缓存中不常用的数据,留下常用的数据,达到缓存效率的最大化。LRU就是这样一种决定“淘汰谁留下谁”的算法,LRU是Least recently used的缩写,从字面意思“最近最少使用”,我们就可以理解LRU的淘汰规则。
我们用一张图来描述LRU的淘汰逻辑,图中的缓存是一个列表结构,上面是头结点下面是尾节点,缓存容量为8(8个小格子):
- 有新数据(意味着数据之前没有被缓存过)时,加入到列表头
- 缓存到达最大容量时,需要淘汰数据多出来的数据,此时淘汰列表尾部的数据
- 当缓存中有数据被命中,则将数据移动到列表头部(相当于新加入缓存)
按上面的逻辑我们可以看到,一个数据如果经常被访问就会不断地被移动到列表头部,不会被淘汰出缓存,而越不经常访问的数据,越容易被挤出缓存。
20行Python代码实践LRU
#!/usr/bin/env python
# -*- coding:utf-8 -*-
from icecream import ic
class LRUCache:
def __init__(self, capacity=18):
self.capacity = capacity
self.data = {} # py>3.6后字典有序 否则 from collections import OrderedDict
def get(self, key):
res = self.data.get(key)
if res:
self.data.pop(key)
self.data[key] = res
return res
return -1
def put(self, key, value):
res = self.data.get(key)
if res:
self.data.pop(key)
elif self.capacity == len(self.data):
self.data.pop(list(self.data.keys())[0])
self.data[key] = value
def __repr__(self):
return str(self.data)
lru_cache = LRUCache()
g1 = lru_cache.get(11)
ic(g1) # ic| g1: -1
ic(lru_cache.put(1, 2)) # ic| lru_cache.put(1, 2): None
ic(lru_cache) # ic| lru_cache: {1: 2}
ic(lru_cache.put(3, 4)) # ic| lru_cache.put(3, 4): None
ic(lru_cache) # ic| lru_cache: {1: 2, 3: 4}
ic(lru_cache.get(3)) # ic| lru_cache.get(3): 4