golang rand.Int,rand.Seed 踩坑记录
转载声明:
本文为摘录自“博客园”,版权归原作者所有。
温馨提示:
为了更好的体验,请点击原文链接进行浏览
摘录时间:
2020-04-13 11:01:57
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调用。