golang数据聚合的优雅操作

golang数据聚合的优雅操作

场景:

需要将上传的数据进行特性分组之后再进行数据库批量插入或流向下一个处理方法。

痛点:

由于数据不确定性做聚合操作之后会有多组数据需要缓存,如果多协程进行操作需要将缓存数据进行加锁,容易造成数据死锁。

解决:

通过管道和select进行数据传递,同时在select中做缓存的所有操作,在给定条件流向下一个处理方法时通过channel传递过去同时清空对应缓存,
这样操作都在select中不会有竞争发生。

具体方法:

1.创建缓存
2.创建select处理缓存数据流过来的通道
3.在select中缓存数据同时聚合数据,之后判断是否流向下一通道
4.创建worker处理聚合后数据

样例

package main

import (
	"fmt"
	"math/rand"
	"time"
)

type Data struct {
	Id    int
	Value interface{}
}

func main() {
	execCacheCount := 50
	workerCount := 10
	c := make(chan Data)
	stream := make(chan map[int][]Data)
	go func() {
		cache := map[int][]Data{}
		for {
			select {
			case data := <-c:
				cacheData, exist := cache[data.Id]
				if exist {
					cacheData = append(cacheData, data)
				} else {
					cacheData = []Data{data}
				}
				cache[data.Id] = cacheData
				if len(cacheData) >= execCacheCount {
					stream <- cache
					cache = map[int][]Data{}
				}
			}
		}
	}()

	for i := 0; i < workerCount; i++ {
		go func() {
			for {
				select {
				case data := <-stream:
					for key, value := range data {
						fmt.Println("key:", key, "values:", value)
					}
				}
			}
		}()
	}
	for {
		r := rand.New(rand.NewSource(time.Now().UnixNano()))
		data := Data{
			Id:    r.Intn(10),
			Value: r.Intn(20),
		}
		c <- data
		time.Sleep(20 * time.Millisecond)
	}
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值