在做实时计算的时候,往往需要计算某一个指标在一秒钟产生的数量。我不知道现在使用一些先进的计算工具是怎么做的。但是如果仅仅是使用普通的编程语言进行计算的话,瓶颈在于一秒钟是否可以计算完成。如果这个计算在一秒钟之内是完成不了的,那么就会造成下一秒的计算的丢失,甚至是下下秒。当然即使是在一秒钟之内能够完成的计算任务。计算本身也是会消耗一点时间,这样来说的话,最后的计算结果也是不正确的。理想的情况下:不考虑取数据需要花费的时间的话,那么模型应该是这样子的:每隔一秒钟取出数据,然后启动一个并行的进程,让这个进程去执行计算任务。这种情况下,可以保证每秒钟都会有数据,但是如果计算时间比较长的话,还是会造成最终的延迟,但是这已经是能够保证的最好的一种方式了。
为什么要使用Go呢,其实本来我是使用Python作为计算任务脚本的,大家知道要想在Python中启动并行计算,那么只能够是启动进程。后来发现Go语言在处理这种事情上,显得非常适合,首先创建一个定时器:
ticker := time.NewTicker(time.Second)
这就创建了一个定时为一秒的定时器,使用方法如下:
for t := range ticker.C {
//do something
}
创建一个通道:
channel := make(chan string, 1024)
在循环里面可以去读取数据并且写到一个通道中
data := readFromRedis()
channel <- data
在程序开始的时候启动多个协程,来读取通道中数据,并且执行计算任务:
for i := 0; i < 10; i ++ {
go func() {
data := <-channel
//do something calculate with data
}()
}
这样,程序启动的时候,就会有十个协程等待从通道里面读取数据,然后做计算。只要一个计算任务不会超过10秒钟,那么每次读取的数据都会被处理掉,而不会造成哪一秒丢失的问题。另外由于Go是编译型语言,在做一些计算密集型的任务的时候,也具有非常大得优势。
上面描述的其实只是其中的一种应用场景,而Go的这种类似于线程池的并发通信模型在很多的地方都可以用到。抽象来讲就是一端生产者不断生产出东西来,然后多个处理者处理这些原始数据。