Redigo并发集提供数据竞争
我正在对我的redigo函数运行这个测试,看看它是否支持大规模并发写入,下面是代码 进口 github.com/gomodule/redigo/redis 日志 操作系统 //Redis连接池 var RedisPool*redis.Pool 函数初始化池{ RedisPool=&redis.Pool{ MaxIdle:80, MaxActive:12000, 拨号:func redis.Conn,错误{ conn,err:=redis.Dialtcp,127.0.0.1:6379 如果错误!=零{ log.PrintfERROR:初始化redis失败:%s,错误。错误 操作系统Exit1 } 返回控制,错误 }, } } func关闭池错误{ 返回池。关闭 } func Setkey字符串,val字符串错误{ //获取conn并在退出方法时放回 conn:=RedisPool.Get 延迟连接关闭 _,err:=conn.DoSET,key,val 如果错误!=零{ log.PrintfERROR:设置密钥%s失败,val%s,错误%s,密钥,val,错误。错误 返回错误 } 归零 } func TestManySetst*testing.T{ 初始化池 延迟关闭池 var wg sync.WaitGroup numOfOperations:=1000 对于i:=0;iRedigo并发集提供数据竞争,go,concurrency,redigo,data-race,Go,Concurrency,Redigo,Data Race,我正在对我的redigo函数运行这个测试,看看它是否支持大规模并发写入,下面是代码 进口 github.com/gomodule/redigo/redis 日志 操作系统 //Redis连接池 var RedisPool*redis.Pool 函数初始化池{ RedisPool=&redis.Pool{ MaxIdle:80, MaxActive:12000, 拨号:func redis.Conn,错误{ conn,err:=redis.Dialtcp,127.0.0.1:6379 如果错误!=
redis_test.go第47行是上面代码中的集合发生的地方。竞争是因为for循环正在更新i,而goroutines正在同时读取i。解决此问题的一种方法是将i传递到goroutine函数:
for i := 0; i < numOfOperations; i++ {
wg.Add(1)
go func(i int) { // <----------- CHANGE THIS
err := Set("key", strconv.Itoa(i))
if err != nil {
t.Errorf("error when setting key value: %s", err)
}
wg.Done()
}(i) // <----------- AND THIS
}
这样,您就不再有i上的闭包,goroutine函数中的i是一个独特的值,可以在没有外部干扰的情况下读取或写入
这还解决了另一个缺陷,即竞争检测器无法发现的缺陷:在for循环中,递增的变量被重新使用,这意味着您当前的版本实际上在许多情况下无意中使用了相同的i值,并且跳过了其他情况。有关详细信息,请参阅。您必须共享数据竞争检测输出,以便我们可以尝试进一步帮助您。当您获得数据竞争时,输出会准确地告诉您哪两个文件/行发生了竞争。从阅读开始。如果您需要帮助,请在问题中包含该输出。此代码段创建1000个执行redis SET命令的goroutine,因此您可以看到数据争用在此处发生err:=Setkey,strconv.Itoai。争用是因为for循环正在更新i,而您的goroutine正在同时读取i。如何转储i。。。我以为我用的redigo不正确,谢谢你!如果你仔细观察种族检测器的输出,它会告诉你正确的方向:阅读。。。redis_测试。go:48和上一次写入时间。。。redis_test.go:45这将其范围缩小到写在第45行、读在第48行的变量。符合该描述的唯一变量是 我