concurrentcache是什么
concurrentcache是golang版的内存缓存库,采用多Segment设计,支持不同Segment间并发写入,提高读写性能。
设想场景
内存缓存的实现,防止并发写冲突,都需要先获取写锁,再写入。如果只有一个存储空间,那么并发写入的时候只能有一个go程在操作,其他的都需要阻塞等待。为了提高并发写的性能,把存储空间切分成多个Segment,每个Segment拥有一把写锁,那样,分布在不同Segment上的写操作就可以并发执行了。concurrentcache设计就是切分多个Segment,提高些并发写的效率。
concurrentcache设计思路
|
|
写
从ConcurrentCache结构体可以看出,包含一个ConcurrentCacheSegment切片,sCount表示切片的长度,这个切片的长度,在初始化的时候就确定,不再改变。
ConcurrentCacheSegment内包含一个读写锁,写入时候根据key的hash值选取写入到哪一个Segment内,通过多Segment设计,来提高写并发效率。
读
为了提高读效率,尽可能多的减少读过程对内存缓存的修改,使用golang提供的原子操作来修改访问状态(visit、miss、hits等),遇到缓存过期的节点也不马上淘汰,因为读访问上的是读锁,要删除数据需要用到写互斥锁,这样会降低读的并发性,所以推迟删除过期的节点,当写数据,Segment的节点不够用的时候再去删除过期节点。
concurrentcache缓存淘汰方式
concurrentcache缓存淘汰方式采用随机选取3个节点,优先淘汰其中过期的一个节点(上一步说的推迟删除过期节点),如果没有过期节点就选取访问量最少(ConcurrentCacheNode结构体中的visit)的节点淘汰。这个思路是参考redis的缓存淘汰策略,redis并不是严格lru算法,采用的是随机选取样本的做法。这样做也是为了提高写性能。
concurrentcache & cache2go 性能对比
(MBP 16G版本)
concurrentcache和cache2go进行了并发下的压测对比,对比结果,concurrentcache无论是执行时间还是内存占比,都比cache2go优
concurrentcache
|
|
cache2go
|
|