Go 中的并发任务很有趣……直到重复的工作量开始压垮你的后端,这时。
我刚开始接触 Go 语言,多亏了 Pomerium 的超赞团队成员,通过参与实际项目代码,我学得很快。
最近我的队友Caleb的一个PR让我一下子明白了这一点。他向我推荐了singleflight
,这是一个非常实用的工具,可以用来避免在并发代码中重复执行任务。
calebdoxsey 于 2025年2月20号 发了一条帖子
摘要如果大量带有相同IdP令牌的请求涌入,我们会多次尝试验证这些令牌并创建会话。此PR更新了代码,将会话创建包裹在singleflight
中,以确保令牌只需验证一次。
- [x] 参考任何相关的问题或议题
- [ ] 更新单元测试
- [x] 添加适当的标签(如
enhancement
,bug
,breaking
,dependencies
,ci
等) - [x] 已准备好审核
点击这里查看 GitHub 上的内容
想象一下,有多个请求都带有同一个身份提供商(IdP)令牌。如果缺乏协调,每个请求都会单独验证并创建一个会话——浪费资源并给下游系统带来很大负担。
在拉取请求里,Caleb 通过将 session 创建过程用 singleflight
包裹起来解决了这个问题,使确保同一时间只运行一次验证,所有调用者共享验证结果。这比之前高效得多。
一开始,我以为这是记忆化,但singleflight
是专门用于并发去重操作,而不是长期缓存。
什么是 singleflight
?
singleflight
避免多个 goroutine 同时执行相同的请求时重复工作。
可以把它想象成短期的备忘录:只有并发的调用会被合并处理。一旦结果返回,结果就会消失 — 没有持久缓存。
它非常适合当你想,
(此处省略具体情境,实际翻译需根据具体情境补充完整)
- 避免请求风暴,例如对同一个令牌进行100次验证。
- 减少数据库或API的负担。
- 在并发高峰期保持结果的一致性。
- 使用相同键调用
Do()
的多个 Goroutine 中只会执行一个:使用相同键调用Do()
的多个 Goroutine 中只会执行一个。 - 所有调用者会得到相同的结果(包括错误):所有调用者会得到相同的结果(包括错误)。
- 完成后,相应的条目会被自动移除:完成后,相应的条目会被自动移除。
- 每个键独立工作:每个键独立工作。
在 Caleb 的 PR 里,singleflight
保证当大量使用相同 token 的请求同时到达时,只会创建一个 session 而不是创建多个 session。
res, err, _ := c.singleflight.Do(sessionID, func() (any, error) {
// 尝试获取现有会话
s, err := c.getSession(ctx, sessionID)
if err == nil {
return s, nil // 找到现有会话
} else if !storage.IsNotFound(err) {
return nil, err
}
// 没有找到现有会话 → 创建新会话
// 验证令牌并调用API接口...
err = c.putSessionAndUser(ctx, s, u)
if err != nil {
return nil, fmt.Errorf("http:// 保存会话和用户失败: %w", err)
}
return s, nil
})
全屏显示 退出全屏
不管有多少并发请求进来,只有一个是真的执行逻辑的。
为何使用singleflight
- 防止验证风暴:只需要一次验证,而不是几十次。
- 减少数据库和API的负载:无需执行冗余任务。
- 返回一致的结果:所有调用者看到的结果都相同。
singleflight
和 memoization 的区别
缓存结果时是跨时间保存的,而 singleflight
(单次执行)只是避免并发调用的重复。
缓存化 | singleflight (单次飞行模式) |
---|---|
长时间缓存 | 在并发调用时 |
需要缓存清理/过期时间 | 不需要设置过期时间 |
加快后续调用 | 避免当前重复执行 |
最终的想法
singleflight
是 Go 语言中的一个优雅工具,默默地解决了一个棘手的问题。当你面对并发问题时,又不想处理缓存或加锁的麻烦,它就是完美的解决方案。
我还在编程的初期,遇到这样的并发模式感觉很兴奋。如果你知道其他有用的并发技巧(尤其是对于从JS/C#/React背景过来的人来说),可以在评论区留言分享。我一直乐于学习新东西 🚀
如果你想保持联系,我的所有社媒账号都在nickyt.online。欢迎随时访问。
[MCP]、[LLM]、[RAG]、[SSE]
共同學(xué)習(xí),寫下你的評論
評論加載中...
作者其他優(yōu)質(zhì)文章