项目中我们提高性能或者吞吐经常使用的是 batch 化,比如说获取帐号信息,我们1条1条查询可能不如我们一次查询100条性能高。
有的时候想这样是为什么呢?因为单个请求中间有网络往返、网络延迟等原因会更加频繁,或者是被请求的服务方MySQL 因为各种原因抖了一下或者什么的,都有可能。
有一次在楼下等电梯的时候,我们有6个电梯,如果一个电梯可以容纳10个人,楼层高度为10楼,那么我们的吞吐量就是 10 * 10 =100 人。
如果每个电梯一个人,那么这个时候一次往返就是6个人。
因为我们的电梯只有6个,所以在一定时间内每个电梯容纳的人多一点会增加我们系统的吞吐量。
早晨的时候物业会有一个工作人员,会在电梯那边,打开一个电梯,尽量让人多一点,然后这个电梯才会上去。我们系统中也可以借鉴,比如我们10s中一个窗口并且size = 100,如果 =100直接请求出去,如果10s中size没有到达100也会将请求发出去。
package main
import (
"fmt"
"time"
)
const _sizeNum = 10
func main() {
getCurrentTime("main start")
var timer = time.NewTicker(10 * time.Second)
for {
currentSize := getCurrentSize()
flag := false
if currentSize >= _sizeNum {
getCurrentTime("size enough")
flag = true
biz()
}
select {
case <-timer.C:
fmt.Println("timer")
if !flag {
fmt.Println("size not enough,timer send")
biz()
}
}
}
timer.Stop()
}
func getCurrentSize() int {
return 10
}
func biz() {
getCurrentTime("biz start")
time.Sleep(40 * time.Second)
getCurrentTime("biz end")
}
func getCurrentTime(str string) {
fmt.Println(str + time.Now().Format("2006-01-02 15:04:05"))
}
写了一个简单的demo,里面没有涉及到电梯数量的限制,也就是如果涉及电梯数量的限制,可以去开多个 go routine 去处理,需要判断go routine 的数量
demo中修改 currentSize 的值可以设置是否满足 batch 的条件
有一些临界资源,涉及到并发的话,需要考虑使用锁去解决