Day 4:分析缓存——已经跑过的不重跑
今天做什么
每天跑一次全量文档分析?浪费。加缓存——文档内容没变的,直接用缓存结果。
代码
go
package main
import (
"context"
"crypto/md5"
"fmt"
"sync"
)
// ===== 带缓存的文档分析器 =====
type CachedAnalyzer struct {
analyzer *DocAnalyzer
cache sync.Map // map[hash]AnalysisResult
}
func NewCachedAnalyzer(maxWorkers int) *CachedAnalyzer {
return &CachedAnalyzer{
analyzer: NewAnalyzer(maxWorkers),
}
}
func (a *CachedAnalyzer) AnalyzeWithCache(ctx context.Context,
doc string) (AnalysisResult, bool, error) {
// 计算文档指纹
hash := fmt.Sprintf("%x", md5.Sum([]byte(doc)))
// 命中缓存,直接返回
if cached, ok := a.cache.Load(hash); ok {
return cached.(AnalysisResult), true, nil
}
// 未命中,实际分析
result, err := a.analyzer.chain.Analyze(ctx, doc)
if err != nil {
return AnalysisResult{}, false, err
}
// 存入缓存
a.cache.Store(hash, result)
return result, false, nil
}
// ===== 批量分析 + 缓存 =====
func (a *CachedAnalyzer) AnalyzeBatchCached(ctx context.Context,
docs []string) ([]AnalysisResult, int, error) {
var results []AnalysisResult
cacheHits := 0
for _, doc := range docs {
result, hit, err := a.AnalyzeWithCache(ctx, doc)
if err != nil {
return nil, 0, err
}
if hit {
cacheHits++
}
results = append(results, result)
}
return results, cacheHits, nil
}
func main() {
ctx := context.Background()
analyzer := NewCachedAnalyzer(5)
docs := []string{
"财报Q1...不变的内容",
"财报Q1...不变的内容", // 和上面一样,命中缓存
"财报Q2...新的内容", // 新内容,重新分析
}
results, hits, _ := analyzer.AnalyzeBatchCached(ctx, docs)
fmt.Printf("完成 %d 份,缓存命中 %d 次\n", len(results), hits)
}运行
bash
go run main.go
# 第一次:3份全分析
# 第二次:如果文档没变,3次全部命中缓存缓存策略总结
| 策略 | 做法 | 适用场景 |
|---|---|---|
| MD5 指纹 | 文档内容不变=缓存有效 | 定期分析同一批文档 |
| TTL 过期 | 缓存N分钟后自动失效 | 文档可能频繁更新 |
| 增量分析 | 只分析新增/修改的文档 | 海量文档库 |
Day 4 完成。缓存让重复分析几乎零成本。

