golang rand.Int,rand.Seed 踩坑记录
https://blog.csdn.net/mingzhehaolove/article/details/77305832
情景描述:
30台服务器负载均衡,初始化建立rpc连接池,在rpc连接异常时,会进行重试,重试过程需要进行rand.Int 获取随机数,读取一台连接,但是一开始没有设定随机种子导致,每一台第一次获取的都是同一个机器,这样所有的流量都打到一台,导致机器挂了。影响其它服务。
后来添加了随机种子,但是有一次量上来的比较大,单个机器的内存飙升,接连影响其它机器的rpc连接,导致goroutinue达到250万,pprof分析,是rand.Seed导致,查看文档发现,官方给出这么一句
- // Seed uses the provided seed value to initialize the generator to a deterministic state.
- // Seed should not be called concurrently with any other Rand method.
因为我们的获取机器方法,每次都需要seed,所以导致了这个问题,后续把rand.Seed 提到初始化方法,实现一次,这个问题就规避了。
使用rand.Int 获取随机数,不加随机种子,每次遍历获取都是重复的一些数据
- package main
- import (
- "fmt"
- "math/rand"
- "sync"
- )
- func main() {
- num := 10
- for j := 0; j < num; j++ {
- res := getRand(num)
- fmt.Println(res)
- }
- }
- func getRand(num int) int {
- var mu sync.Mutex
- mu.Lock()
- v := rand.Intn(num)
- mu.Unlock()
- return v
- }
- 结果:
- 1
- 7
- 7
- 9
- 1
- 8
- 5
- 0
- 6
- 0
添加随机种子 rand.Seed(time.Now().UnixNano()) 保证每次都是随机的
- package main
- import (
- "fmt"
- "math/rand"
- "sync"
- "time"
- )
- func main() {
- num := 10
- for j := 0; j < num; j++ {
- res := getRand(num)
- fmt.Println(res)
- }
- }
- func getRand(num int) int {
- rand.Seed(time.Now().UnixNano())
- var mu sync.Mutex
- mu.Lock()
- v := rand.Intn(num)
- mu.Unlock()
- return v
- }
- 结果:
- 1
- 5
- 4
- 8
- 3
- 1
- 4
- 4
- 3
- 0
正常情况,做一些小的开发,这些无所谓,但是当开发一些高并发的处理时,rand.Seed就会发生问题,官方不建议在高并发情况下,使用rand.Seed,之所以我会遇到这种问题,也是因为,当时线上出了一个大问题,为了快速解决,就使用了rand.Seed. 为了得到随机的线上机器,进行rpc调用。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 周边上新:园子的第一款马克杯温暖上架