golang rand.Int,rand.Seed 踩坑记录

来源:博客园 分类: 文章浏览史 发布时间:2020-04-13 11:01:57 最后更新:2020-04-13 浏览:511
转载声明:
本文为摘录自“博客园”,版权归原作者所有。
温馨提示:
为了更好的体验,请点击原文链接进行浏览
摘录时间:
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导致,查看文档发现,官方给出这么一句

[php] view plain copy
 
  1. // Seed uses the provided seed value to initialize the generator to a deterministic state.  
  2. // Seed should not be called concurrently with any other Rand method.  

因为我们的获取机器方法,每次都需要seed,所以导致了这个问题,后续把rand.Seed 提到初始化方法,实现一次,这个问题就规避了。

 

使用rand.Int 获取随机数,不加随机种子,每次遍历获取都是重复的一些数据

[php] view plain copy
 
  1. package main  
  2.   
  3. import (  
  4.     "fmt"  
  5.     "math/rand"  
  6.     "sync"  
  7. )  
  8.   
  9. func main() {  
  10.     num := 10  
  11.     for j := 0; j < num; j++ {  
  12.         res := getRand(num)  
  13.         fmt.Println(res)  
  14.     }  
  15. }  
  16.   
  17. func getRand(num int) int {  
  18.     var mu sync.Mutex  
  19.     mu.Lock()  
  20.     v := rand.Intn(num)  
  21.     mu.Unlock()  
  22.     return v  
  23. }  
  24.   
  25. 结果:  
  26. 1  
  27. 7  
  28. 7  
  29. 9  
  30. 1  
  31. 8  
  32. 5  
  33. 0  
  34. 6  
  35. 0   

 添加随机种子 rand.Seed(time.Now().UnixNano())  保证每次都是随机的

[php] view plain copy
 
  1. package main  
  2.   
  3. import (  
  4.     "fmt"  
  5.     "math/rand"  
  6.     "sync"  
  7.     "time"  
  8. )  
  9.   
  10. func main() {  
  11.     num := 10  
  12.     for j := 0; j < num; j++ {  
  13.         res := getRand(num)  
  14.         fmt.Println(res)  
  15.     }  
  16. }  
  17.   
  18. func getRand(num int) int {  
  19.     rand.Seed(time.Now().UnixNano())  
  20.     var mu sync.Mutex  
  21.     mu.Lock()  
  22.     v := rand.Intn(num)  
  23.     mu.Unlock()  
  24.     return v  
  25. }  
  26. 结果:  
  27. 1  
  28. 5  
  29. 4  
  30. 8  
  31. 3  
  32. 1  
  33. 4  
  34. 4  
  35. 3  
  36. 0  

正常情况,做一些小的开发,这些无所谓,但是当开发一些高并发的处理时,rand.Seed就会发生问题,官方不建议在高并发情况下,使用rand.Seed,之所以我会遇到这种问题,也是因为,当时线上出了一个大问题,为了快速解决,就使用了rand.Seed. 为了得到随机的线上机器,进行rpc调用。

php技术微信