1 回答
TA贡献1773条经验 获得超3个赞
Go 有一个非常酷的模式,在多个通道上使用for / select 。这允许您使用超时和最大记录大小来批量写入距离。使用这种模式需要使用通道。
首先是将您的距离建模为通道:
distances := make(chan Delta)
然后你跟踪当前批次
var deltas []Delta
然后
ticker := time.NewTicker(time.Second * 5)
var deltas []Delta
for {
select {
case <-ticker.C:
// 5 seconds up flush to db
// reset deltas
case d := <-distances:
deltas = append(deltas, d)
if len(deltas) >= maxDeltasPerFlush {
// flush
// reset deltas
}
}
}
我不知道如何确保距离,所以当我在另一个例程中添加它时,我在其他地方阅读它,一切都很好!(问题是我想使用 go 频道并且不知道该怎么做)
如果您打算保留地图并共享内存,则需要使用互斥(互斥)来保护它,以同步 go 例程之间的访问。使用通道允许您将副本发送到通道,从而无需跨 Delta 对象进行同步。根据您的架构,您还可以创建由通道连接的 go 例程管道,这可以使其只有一个 go 例程(monitor goroutine)正在访问Delta,也无需同步。
对于这个问题,我如何安排任务?
使用通道作为传递Deltas给不同 go 例程的原语 :)
可能我会添加一个 redis 来存储所有在线设备,这样我就可以更快地进行选择查询并更新实际的数据库。还为 redis 添加过期时间,因此如果设备在一段时间内没有发送和数据,它就会消失!我应该把这段代码放在哪里?
这取决于您完成的架构。您可以为 select 操作编写一个装饰器,它会先检查 redis,然后再访问数据库。此功能的客户端不必知道这一点。写操作可以以相同的方式完成:写入持久存储,然后使用缓存值和过期时间写回 redis。使用装饰器,客户端不需要知道这一点,他们只需执行读取和写入,缓存逻辑将在装饰器内部实现。有很多方法可以做到这一点,这在很大程度上取决于您的实现在哪里解决。
- 1 回答
- 0 关注
- 159 浏览
添加回答
举报