关于Goroutine使用的一些疑问

来源:5-1 goroutine

burningx

2021-10-14 19:51:14

老师好,在学习go以前我是用PHP做开发的,接触go和goroutine后让我产生了一个疑问。
获取商品列表接口为例:

以前我实现这个接口的方法是,先获取商品的ID列表,然后通过ID列表循环获取商品详情(这样方便给详情做缓存),例如:

ids := s.Mysql.GetGoodIDList()
var goodsList []*goodDetail
for _,id := range ids {
	detail := s.Mysql.GetGoodDetail(c, id)
	goodsList = append(goodsList, detail)
}
return goodsList,nil

现在的想法是,获取商品的ID列表后,通过goroutine并发去获取商品详情,例如:

ids := s.Mysql.GetGoodIDList()
var goodsList []*goodDetail
ch := make(chan *goodDetail)
for _,id := range ids {
	go func(id int32) {
		detail := s.Mysql.GetGoodDetail(c, id)
		ch<- detail
	}(id)
}
for range ids {
	goodsList = append(goodsList, <-ch)
}
return goodsList,nil

先不考虑排序问题
线上项目以第二种方法来实现合理吗?如果其他类似的接口也以这种方法来实现,会不会造成goroutine的资源浪费?还有就是这类功能在开发角度来说有没有必要开启goroutine去获取详情呢?

我测试了两种方法的获取速度,第二种方法比第一种快了很多,但是我看了其他go的开源项目,获取列表不会用第二种方法来实现功能的。

写回答

1回答

ccmouse

2021-10-20

这是典型的N+1查询的问题,可以参考这篇文章:https://cloud.tencent.com/developer/article/1526830


这里解决的方法不是通过语言层面,而是从数据库本身,我们把所有的good id作为一个集合,作为查询的参数,用一句语句把所有的数据都拿到(这句sql可能会比较复杂,但一定要这么做)。然后再在go语言中用for语句去遍历结果集。这就是同学说的其他go开源项目不会用“第二种”方法来实现。


那么说回go,这个问题采用goroutine的确能够提升性能。是一个实在没有办法的办法。goroutine资源不高,不过qps是多少,每个请求预期的结果集数量是多少,这两个数据如果乘出来很大(10万/百万)那也吃不消。

1
hurningx
hp dir="ltr">非常感谢CC老师的解答,每次都能让我受益匪浅。

h021-10-20
共1条回复

0 学习 · 1399 问题

查看课程