ecodeclub / ecache

统一缓存 API
Apache License 2.0
12 stars 15 forks source link

基于 Go 实验特性 Arena 的缓存实现。 #12

Open flycash opened 1 year ago

flycash commented 1 year ago

仅限中文

使用场景

即便是使用 sync.Poll 来缓存对象,依旧会加重 GO 的垃圾回收负担。所以一种想法是在 GO 垃圾回收之外设计一个缓存机制,这也就是说我们可以考虑使用 Arena 来设计一个缓存。

这个设计可以分成两部分,缓存本身的结构就直接用 GO 来定义,本身也归属于 GO 垃圾回收管理。

但是缓存的键值对中的值就被 Arena 管理。

在这种理念下,我们可以认为,缓存本身的开销,以及键值对中的键的开销,是可以容忍的,但是值的开销是不能容忍,所以需要放到堆外。

行业分析

在 ekit 里面有一个 Arena Pool,作为一个使用 Arena 的对象池,可以考虑借鉴。

可行方案

// memory/arena/cache.go
// 文件头加上这个编译标签
//go:build goexperiment.arenas
type Cache struct {
    vals map[string]*arena.Arena // 也可能映射过去了一个结构体,然后结构体有一个 Arena 字段,还有一些过期时间等的设置。
}

最基本的定义,当然为了维系缓存自身,你还是需要引入其它字段。

当缓存过期,或者被删除的时候,需要调用 arena 上的 Free 方法释放内存。

junwense commented 1 year ago

我看了ekit.arena的设计,是要把obj进行包装,然后在cache的get set update remove方法进行处理arena么。

flycash commented 1 year ago

大概是这么个思路。

但是缓存用起来有另外一个问题,比如说我取走了 A,但是我一直在用。这个时候缓存里面的 A 过期了,这时候你并不能删除 A(调用 Arena 的 Free),而是要等我用完了 A。目前的难点就是,你不知道我究竟有没有在用 A。

这里,你可以认为,用户在 Get 的时候,是真的把数据都取走了。也就是 GET 接近一种 DelAndGet 的语义。后面我们再来考虑怎么解决这个问题。