Erlang LRU Cache

时间:2016-07-28 18:33:37

标签: caching erlang lru

如何使用Erlang实现LRU缓存?

LRU Cache Wiki

排名最高的Github项目是fogfish/cache,但是分段表不太适合我的数据。

barrel-db/erlang-lru正在使用List。经过测试,如果数据太多,那就太慢了。

我猜问题就在这里。

move_front(List, Key) -> [Key | lists:delete(Key, List)].

使用 Java ,更好的实施方法是使用 hashmap 链接列表 like this

我尝试做一个链表,然后意识到 Linkedlist对Erlang来说不是好主意like this thread

问题是如何使用Erlang进行LRU缓存?

2 个答案:

答案 0 :(得分:1)

THE CACHE的第一个实现基于具有两个索引的ETS。一个ets表是hold TTL -> Key关系,另一个ets表是Key -> Object。您可以在

中看到实施

https://github.com/fogfish/cache/commit/8cc50bffb4178ad9ad716703507c3290e1f94821

维护两个索引效率不高,因此分段缓存优于原始实现。我不建议使用Erlang数据结构实现每对象TTL,除非您可以在actor中建模数据并接受开销。有一个实现来解决它。它是每个对象概念的使用过程:

https://github.com/fogfish/pts

否则,您需要实施NIF

答案 1 :(得分:0)

我已经使用伪时间方法实现了LRU缓存(此处https://github.com/poroh/erl_lru中提供了完整的实现)

我有两个数据结构:

  1. 用于查找的无序映射:#{key() => {order(), value()}}
  2. 用于商品订购的订购地图:gb_tree(order(), key())

order()是伪时间:

  • 每次添加新元素或更新任何元素时,它都会递增
  • 属于LRU的每个元素都有自己的更新时间

操作:

由于使用gb_tree,因此所有操作的复杂度为O(log(N))。

添加元素(键,值):

  • 增加时间(结果为T)
  • 将键=> {T,Value}放置到无序地图
  • 将{T,Key}放入排序的地图
  • 检查溢出

更新元素(键):

  • 在无序映射中查找元素键=> {T0,值}
  • 增加时间(结果为T)
  • 从无序地图中删除元素键
  • 从有序地图中删除元素T0
  • 如上所述添加元素(键,值)

检查溢出:

  • 如果高速缓存中的元素数超过了可能的最大值
    • 采用有序映射(T,Key)中的最小(gb_tree:take_smallest)元素
    • 从有序地图中删除元素T
    • 从无序中删除元素键