欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 房产 > 建筑 > go-文件缓存与锁

go-文件缓存与锁

2025/3/15 3:54:15 来源:https://blog.csdn.net/weixin_44059224/article/details/146158401  浏览:    关键词:go-文件缓存与锁

语言:golang

在抓取网站前,可能会多次读取文件中的cookie。频繁读取文件,性能不佳,故在go包中创建了一个map全局变量存储文件内容,只有键不存在时才去读取文件。
因为对go并不熟悉,才发现,不同请求读取到的是同一个变量(地址)。对于性能来说,这其实是好的。但出现一个问题:文件更新后,该变量的值依然是文件更新之前的内容,需要重新运行go包,而cookie随时可能失效而去更新,频繁重启这显然不现实。

解决方法
依旧采用map存储文件内容,但map的值为:1、文件的内容,2、文件的修改时间。
每次读取加读锁,并检查实际文件的修改时间,若与map中的值一致,则直接返回map中文件内容。
若不一致,则加写锁,再次检查修改时间,防止获取到写锁之前,文件已经修改。随后读取文件,获取文件中的内容,并更新内容和当前时间到map中。

type cacheEntry struct {content []stringmodTime time.Time
}var (fileCache = make(map[string]cacheEntry)mu        sync.RWMutexgroup     singleflight.Group
)func getFileModTime(path string) (time.Time, error) {fileInfo, err := os.Stat(path)if err != nil {return time.Time{}, err}return fileInfo.ModTime(), nil
}
func GetFile(file string) string {//合并请求result, err, _ := group.Do(file, func() (interface{}, error) {mu.RLock()entry, ok := fileCache[file]mu.RUnlock()path := GetFullPath(file)if ok {currentModTime, err := getFileModTime(path)if err != nil {return nil, err}if currentModTime.Equal(entry.modTime) {return entry.content, nil // 缓存有效}}mu.Lock()defer mu.Unlock()//再次检查,避免在获取到写锁的前一刻已经更新entry, ok = fileCache[file]if ok {currentModTime, err := getFileModTime(path)if err != nil {return nil, err}if currentModTime.Equal(entry.modTime) {return entry.content, nil // 缓存有效}}//读取文件并缓存content, err := os.ReadFile(path)if err != nil || len(content) == 0 {return nil, errors.New("文件不存在或为空")}//可选,按行分割内容lines := strings.Split(string(content), "\n")var branchContent []stringfor _, line := range lines {if line != "" {line = strings.TrimSpace(line)branchContent = append(branchContent, line)}}fileCache[file] = cacheEntry{content: branchContent,modTime: time.Now(),}return branchContent, nil})
}

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词