常用的一些算法包括:FIFO、LFU、LRU、LRU2、ARC 等。
FIFO 就是先进先出,一种非常简单的算法,缓存数据达到上限的时候,最先进入缓存的数据会最先被踢出去。很多老员工看到这一条都义愤填膺,所以,这个算法注定是不被喜欢的,但是由于它简单直接,很多开发者喜欢。嗯,有些企业老板也比较喜欢。Second Chance 和 CLock 是基于 FIFO 的改进,算法更加先进合理,也更复杂,微信里写了也没人看,感兴趣的话,Google「缓存算法 CLock」等。
LFU 的全称是 Least Frequently Used,最少使用算法,系统会为每个对象计算使用频率,最不常用的缓存对象会被踢走,简单粗暴。缺点是,一个传统工业时代曾经被重用过的老员工,在互联网时代没用了,由于其前期使用频率很高,吃老本,所以数据会一直保存在缓存系统中,反而是后起之秀,往往会遭遇到误杀的不公正待遇。差评。
LRU 的全称是 Least Recently Used,也就是最近最少使用算法。基本思路是,如果一个数据最近一段时间被使用的频率很少,那将来被用到的可能性也会很低。看到这儿,那些近期没什么开发任务的童靴,你们要小心了。好评。
LRU2 和 ARC 都是基于 LRU 的改进,有兴趣的可以上网查查。
很多我们耳熟能详的缓存产品,比如 Memcached、Redis、Ehcache、OSCache 等,都参考了类似的算法,要么进行加强,要么进行简化,目标就是提升缓存的命中率,降低缓存成本。
Design and implement a data structure for Least Recently Used (LRU) cache. It should support the following operations: get and set.
get(key) - Get the value (will always be positive) of the key if the key exists in the cache,
otherwise return -1.
set(key, value) - Set or insert the value if the key is not already present. When the cache
reached its capacity, it should invalidate the least recently used item before inserting a new item.
class LRUCache{
struct NODE{
int key;
int val;
NODE* pre;
NODE* next;
NODE(int key,int value):key(key),val(value),pre(NULL),next(NULL){}
NODE():val(0),pre(NULL),next(NULL){}
};
private:
unordered_map<int,NODE*> m_mp;
int m_cap;
int m_size;
NODE* m_pHead;
NODE* m_pTail;
void putToHead(NODE* pNode)
{
pNode->pre=m_pHead;
pNode->next=m_pHead->next;
m_pHead->next->pre=pNode;
m_pHead->next=pNode;
}
public:
LRUCache(int capacity) {
m_cap=capacity;
m_size=0;
m_mp.clear();
m_pHead=new NODE;
m_pTail=new NODE;
m_pHead->next=m_pTail;
m_pTail->pre=m_pHead;
}
~LRUCache() {
//m_cap=capacity;
m_size=0;
m_mp.clear();
delete m_pHead;
delete m_pTail;
}
int get(int key) {
unordered_map<int,NODE*>::iterator iMp=m_mp.find(key);
if(iMp==m_mp.end())
return -1;
else
{
NODE* pCur=iMp->second;
NODE* pPre=pCur->pre;
NODE* pNext=pCur->next;
pPre->next=pNext;
pNext->pre=pPre;
putToHead(pCur);
return pCur->val;
}
}
void set(int key, int value) {
unordered_map<int,NODE*>::iterator iMp=m_mp.find(key);
if(iMp==m_mp.end())
{
NODE* p=new NODE(key,value);
putToHead(p);
m_mp[key]=p;
m_size++;
}
else
{
NODE* p=iMp->second;
p->val=value;
NODE* pPre=p->pre;
NODE* pNext=p->next;
pPre->next=pNext;
pNext->pre=pPre;
putToHead(p);
}
if(m_size>m_cap)
{
NODE* pCur=m_pTail->pre;
NODE* pPre=pCur->pre;
pPre->next=m_pTail;
m_pTail->pre=pPre;
m_mp.erase(m_mp.find(pCur->key));
delete pCur;
m_size--;
}
}
本文介绍了几种常见的缓存算法,包括FIFO、LFU、LRU及其变种,并通过生动的例子帮助理解每种算法的特点及应用场景。同时,还提供了一个LRU缓存实现的示例代码。
6702

被折叠的 条评论
为什么被折叠?



