自己经常使用 map 加上互斥锁来处理缓存, 很久之前就在 github 上发现 go-cache 这个项目,今天重新看到它,发现它已经 2000+star 了。 扫了一下代码,发现代码量很少,就 clone 下来看看。
go-cache 实际代码就两个文件–cache.go 和 shared.go,其中 shared.go 是作者打算在大缓存数据下使用 hash 算法提升缓存的读写速度的,实际上也未对外 export,创建 sharedCache 的函数名也是小写的。
cache 很简单,只有 map[string]Item 和锁。其中 Item 的结构为
1 | type Item struct { |
Object 存储数据,Expiration 存储数据过期时间。创建 cache 的时候会创建一个清理器来清理过期的数据
1 | func newCacheWithJanitor(de time.Duration, ci time.Duration, m map[string]Item) *Cache { |
注意 runtime.SetFinalizer()这个函数,之前没用过。这是是在 程序垃圾回收(garbage collection)时执行指定函数。
shared.go 是创建一个 shardedCache, 包含多个 cache,通过 hash 算法(djb33)选择 cache 存取数据.
1 | type shardedCache struct { |
sharedCache 没有使用 go 的”hash/fnv”中的 hash.Hash 函数,使用的是自己写的 hash 算法,并称自己的 hash 算法 djb33 比 fnv 的快 5 倍 。
1 | // djb2 with better shuffling. 5x faster than FNV with the hash.Hash overhead. |
注意,创建 seed 代码
1 |
|
引入的包是”crypto/rand” 和 insecurerand “math/rand”。 记得以后使用”crypto/rand” 来 构造随机数,安全些。