在做raft 2A实验时,遇到一个奇怪的bug,经常会选不出leader,然后想打印日志查看原因发现又能够选出来了,进入了出问题我想看日志,看日志又没问题的奇怪循环中。后来在过整个代码时发现在我重启选举计时器时,又重置了随机种子,而我把这个删去只在初始化过程中重置一次的随机种子,发现整个流程就跑通了。后来查询资料寻找原因主要原因是以下几点:
- go中的rand函数是一个伪随机生成,如果随机种子相同那么生成的随机数是一样的。
- math.rand提供一个全局的globalRand变量,多个goroutine调用rand()函数时访问的是同一个globarand。(为了并发安全,go还用了一把互斥锁来访问这个globalrand,所以如果将原本单goroutine使用rand改为多线程并发使用rand,可能会因为竞争锁导致性能下降。参考博客)</