业务场景:

任务体系越来越受到活动的青睐,例如最近的淘宝和京东双十一活动,都是采用任务类型的活动,我司近几个月的活动也多采用类似的任务体系,分享、关注、点赞、投币、投稿等,既然是活动,就限制了活动的范围是活动稿件或指定稿件上的点赞/投币行为,因此Job监听用户点赞、投币时,需要查询点赞或者投币的是否是活动稿件。

在数据库中,稿件业务方有单独的表,但是如果是活动稿件,也会进入活动单独的活动稿件表,因此,每当有一条点赞/投币的消息到来时,需要判断该条信息的稿件id是否属于活动稿件,就需要查询活动稿件表。当数据量不多时,直接查db是没有问题的,但是数据量大的时候,很容易把数据库打爆,然后限流。。。

原始查询:

"SELECT `id` From likes WHERE sid = ? and wid = ? and `state` != -1"

优化一:既然直接查数据库不可以,可以改走内存哇。先把该活动下的稿件拉出来,每几分钟拉一次,放在一个协程里,然后设置一个内存变量map,稿件id为map的键,值为空结构体就好struct{}{}。每次来消息时候,就判断是否存在即可:

if _, ok := s.XXmap[m.ID]; ok {
	xxx
}

sql查询如下:

SELECT wid FROM xxx WHERE state=1 AND sid=? ORDER BY type

思考:

走内存是没问题的,但是这么查,如果稿件量特别大,还是容易出问题,因此,考虑分段查询,使用limit

优化二:

sql查询如下:

SELECT wid FROM xxx WHERE state= 1 AND sid = ? ORDER BY id LIMIT ?,?

这样可以先查询一个总量,然后使用for循环,分批次100个100个的查,上面的sql填充limit offset,limit

for i := 0; i < count; i += 100 {
    //查询
}

思考:

limit ?,?会有深度分页问题,因尽量少这么使用,因此考虑更好的分批次查询方式。

优化三:

SELECT id,wid FROM xxx WHERE sid=? and `state`!=-1 and id > ? ORDER BY id ASC LIMIT ?

如上,同样是使用limit,但是在前面,加了一个id > ?的判断,不加这个判断依旧是查所有的数据,加了之后,第一次传0,第二次传第一次查出来的最后一个id,这样就能比较好的分批次查询了。整个协程代码如下:

func (s *Service) loadXXXArc(sid int64) (data map[int64]struct{}, err error) {
	var (
		i   int64
		tmp = make(map[int64]struct{})
		res []*l.XXX
	)
	for {
		time.Sleep(100 * time.Millisecond)
		res, err = s.loadList(context.Background(), sid, i, _objectPieceSize, _retryTimes) //封装的查询方法,i对应sql中的id>?,_objectPieceSize常量对应limit?
		if err != nil {
			log.Error("loadXXXArc Err %v", err)
			break
		}
		if len(res) == 0 {
			log.Warn("loadXXXArc load data finish")
			break
		}
		for key, val := range res {
			tmp[val.Wid] = struct{}{}
			if key == len(res)-1 {
				i = val.ID   //取上一次查询的最后一个id赋值
			}
		}
	}
	data = tmp
	return
}

func (s *Service) loadArc() {
	data, err := s.loadXXXArc(s.c.Eleven.ElevenSid)
	if err != nil {
		return
	}
	s.Arc = data
}

func (s *Service) loadArcproc() {
	for {
		time.Sleep(5 * time.Minute)
		s.loadArc()
	}
}

//最后,在service层的New()中调用即可
s.loadArc()
go s.loadArcproc()

 

Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐