searchusermenu
  • 发布文章
  • 消息中心
点赞
收藏
评论
分享
原创

Ceph中LRU设计分析

2023-07-19 01:26:12
31
0

1.LRU简介

最近最少使用(LRU,Least Recently Used)算法用于简单的缓存淘汰策略。如果最近访问了某个元素,且这个元素在缓存队列中,就将这个元素提升至队列头部;否则就将其加入到队列中,处于队列末尾的元素将被淘汰。

读写和更新的效率需要达到O(1),可以使用HashMap+双向链表实现。Ceph里使用双向链表实现,并记录链表头和尾部。

2.LRU数据结构

LRU至少需要双向链表list和LRU算法的封装即LRUImpl。

  • Ceph中使用xlist类做为双向链表,链表中的元素用item类表示。
  • Ceph中使用LRU类实现LRU算法。
  • Ceph中使用LRUObject类做为LRU算法处理的对象类型。
  • Ceph中如果想让某个class具备LRU算法的功能,就继承LRUObject。

需要注意的是,通常设置midpoint,用于划分两个队列,前者为top,后者为bottom,midpoint指明了top和bottom长度的比例。Ceph中设置midpoint为0.6,即top占总长度的60%,bottom占40%。

3.LRU的实现

  • 双向链表的实现

template<typename T>

class xlist {

public:

class item {

private:

friend xlist;

T _item;

item *_prev = nullptr, *_next = nullptr;

xlist *_list = nullptr;

};

...

private:

item *_front, *_back;

size_t _size;

};

  • LRU算法的实现

class LRU {

public:

LRU() : num_pinned(0), midpoint(0.6) {}

uint64_t lru_get_size() const {

return lru_get_top()+lru_get_bot()+lru_get_pintail(); }

uint64_t lru_get_top() const { return top.size(); }

uint64_t lru_get_bot() const{ return bottom.size(); }

uint64_t lru_get_pintail() const { return pintail.size(); }

uint64_t lru_get_num_pinned() const { return num_pinned; }

void lru_insert_top(LRUObject *o);

void lru_insert_mid(LRUObject *o);

void lru_insert_bot(LRUObject *o);

...

private:

typedef xlist<LRUObject *> LRUList;

LRUList top, bottom, pintail;

}

  • LRU中对象的实现

class LRUObject {

public:

LRUObject() : lru(), lru_link(this), lru_pinned(false) { }

~LRUObject();

// pin/unpin item in cache

void lru_pin();

void lru_unpin();

bool lru_is_expireable() const { return !lru_pinned; }

friend class LRU;

private:

class LRU *lru;

xlist<LRUObject *>::item lru_link;

bool lru_pinned;

};

  • 通过继承具备LRU功能

class BufferHead : public LRUObject{...}

class Object : public LRUObject{...}

0条评论
0 / 1000
1****m
3文章数
0粉丝数
1****m
3 文章 | 0 粉丝
1****m
3文章数
0粉丝数
1****m
3 文章 | 0 粉丝
原创

Ceph中LRU设计分析

2023-07-19 01:26:12
31
0

1.LRU简介

最近最少使用(LRU,Least Recently Used)算法用于简单的缓存淘汰策略。如果最近访问了某个元素,且这个元素在缓存队列中,就将这个元素提升至队列头部;否则就将其加入到队列中,处于队列末尾的元素将被淘汰。

读写和更新的效率需要达到O(1),可以使用HashMap+双向链表实现。Ceph里使用双向链表实现,并记录链表头和尾部。

2.LRU数据结构

LRU至少需要双向链表list和LRU算法的封装即LRUImpl。

  • Ceph中使用xlist类做为双向链表,链表中的元素用item类表示。
  • Ceph中使用LRU类实现LRU算法。
  • Ceph中使用LRUObject类做为LRU算法处理的对象类型。
  • Ceph中如果想让某个class具备LRU算法的功能,就继承LRUObject。

需要注意的是,通常设置midpoint,用于划分两个队列,前者为top,后者为bottom,midpoint指明了top和bottom长度的比例。Ceph中设置midpoint为0.6,即top占总长度的60%,bottom占40%。

3.LRU的实现

  • 双向链表的实现

template<typename T>

class xlist {

public:

class item {

private:

friend xlist;

T _item;

item *_prev = nullptr, *_next = nullptr;

xlist *_list = nullptr;

};

...

private:

item *_front, *_back;

size_t _size;

};

  • LRU算法的实现

class LRU {

public:

LRU() : num_pinned(0), midpoint(0.6) {}

uint64_t lru_get_size() const {

return lru_get_top()+lru_get_bot()+lru_get_pintail(); }

uint64_t lru_get_top() const { return top.size(); }

uint64_t lru_get_bot() const{ return bottom.size(); }

uint64_t lru_get_pintail() const { return pintail.size(); }

uint64_t lru_get_num_pinned() const { return num_pinned; }

void lru_insert_top(LRUObject *o);

void lru_insert_mid(LRUObject *o);

void lru_insert_bot(LRUObject *o);

...

private:

typedef xlist<LRUObject *> LRUList;

LRUList top, bottom, pintail;

}

  • LRU中对象的实现

class LRUObject {

public:

LRUObject() : lru(), lru_link(this), lru_pinned(false) { }

~LRUObject();

// pin/unpin item in cache

void lru_pin();

void lru_unpin();

bool lru_is_expireable() const { return !lru_pinned; }

friend class LRU;

private:

class LRU *lru;

xlist<LRUObject *>::item lru_link;

bool lru_pinned;

};

  • 通过继承具备LRU功能

class BufferHead : public LRUObject{...}

class Object : public LRUObject{...}

文章来自个人专栏
Keep Moving
3 文章 | 1 订阅
0条评论
0 / 1000
请输入你的评论
0
0