Go语言进阶freecache源码分析

发布时间:2023-05-08 14:58:01 作者:iii
来源:亿速云 阅读:171

这篇文章主要介绍“Go语言进阶freecache源码分析”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“Go语言进阶freecache源码分析”文章能帮助大家解决问题。

00. 什么是 freecache?

freecache 是一个用 go 语言实现的本地缓存系统(类似于 lru)。

它有几个特性值得注意:

这几个优秀特性使得他非常适合用在生产环境中作为本地缓存。

01. 简单用法

cacheSize := 100 * 1024 * 1024
cache := freecache.NewCache(cacheSize)
debug.SetGCPercent(20)
key := []byte("abc")
val := []byte("def")
expire := 60 // expire in 60 seconds
cache.Set(key, val, expire)
got, err := cache.Get(key)
if err != nil {
    fmt.Println(err)
} else {
    fmt.Println(string(got))
}
affected := cache.Del(key)
fmt.Println("deleted key ", affected)
fmt.Println("entry count ", cache.EntryCount())

02. 功能概览

本文计划先以自然语言描述下列功能的实现方式,再接下来的章节中深入源码,扒出其具体实现

03. 如何做到 0 GC?

这个库之所以做到了 0 gc,是因为设定了很巧妙的数据结构,这个数据结构有以下的特点:

04. 数据结构

Go语言进阶freecache源码分析

可以将这个数据结构大体上抽象成一个哈希表。即你会看到哈希函数以及对应的数组空间。但是他和传统的哈希表是有区别的,主要有以下几点:

05. 动态索引

通过上面对数据结构的分析,我们知道他和传统的哈希表的实现方式大相径庭。它实际上是使用了一种叫“插槽”的数据结构,专门负责通过 key 索引到数据空间中的某个位置。他的实现比较有意思。它的底层是一个结构体指针数组。他是可以动态扩容的。每个插槽有一个 id,叫 slotId,范围是 0~255。当遇到哈希冲突的时候,比如出现了2个 slotId 为 100 的 slot,他就会检测当前的最大重复 slotID 数量 n。如果这个 2 大于 n,他就会扩容到 2n。

// slot 的数据结构
type entryPtr struct {
	offset   int64  // 记录了当前 slot 在环形数组中的偏移量
	hash26   uint16 // 一个 hash 值,用于在 segment 中定位到具体的 slot
	keyLen   uint16 // used to compare a key
	reserved uint32
}
// 每个分片的数据结构
type segment struct {
	rb            RingBuf // 环形数组
	segId         int
	hitCount      int64
	missCount     int64
	entryCount    int64
	totalCount    int64      // 之后计算 lru 的时候会用到,用于衡量一个数据是否是热点数据
	totalTime     int64      // 之后计算 lru 的时候会用到,用于衡量一个数据是否是热点数据
	totalEvacuate int64      // used for debug
	totalExpired  int64      // used for debug
	overwrites    int64      // used for debug
	vacuumLen     int64      // 环形数组可用容量,主要用于环形数组首尾相接的算法
	slotLens      [256]int32 // 每个 slotId 的长度的数组
	slotCap       int32      // 每个 slotId 的容量
	slotsData     []entryPtr // 存储 slots 的切片,根据 hash26 进行顺序排列。相同的 hash26 拥有相同的 slotId
}

06. 缓存失效

缓存失效主要包括两种:

这两种失效都有缺陷。

首先它是一种被动失效,而不是通过一个额外的线程定期check。而是每次 set 新的值的时候,如果发现空间不够用了,他才会尝试从环形数组的头端进行check。如果发现当前check的数据过期了,或者使用频率过低,就会将记录有效数据的头指针进行偏移,即相当于“失效”。如果检查多次都没能找到需要失效的数据,那么他会将这些检查过的数据转移到尾部,并强制当前的头部的数据失效。

这种失效是不可靠的。比如一个数据,如果在环形数组的中间,那么即便它过期了,也很难被 check 到。并且存在一定的失误概率,即将一个热点数据给失效了。

关于“Go语言进阶freecache源码分析”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识,可以关注亿速云行业资讯频道,小编每天都会为大家更新不同的知识点。

推荐阅读:
  1. go使用mysql测试的示例
  2. go语言能够算是动态语言吗

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

go语言 freecache

上一篇:docker的常用命令怎么使用

下一篇:nginx中状态统计如何实现

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》