增加不同记录中的字段值,避免Golang中的竞争条件

时间:2014-06-23 08:53:14

标签: go

我的Golang代码使用goroutines从数据库中获取不同的记录,并在记录中的确定字段中增加该值。

我可以避免竞争条件如果我使用Mutex或Channels,但我有一个瓶颈,因为每次访问数据库都会等到上一次访问完成。

我认为我应该为每个不同的记录执行类似于一个Mutex的操作,而不是只为所有记录执行Mutex。

我怎么能这样做?

感谢您的回复。

2 个答案:

答案 0 :(得分:1)

在评论中,您说您正在使用Couchbase。如果您要更新的记录仅包含整数,则可以使用Bucket.Incr内置的原子增量功能。

如果值是较大文档的一部分,则可以使用数据库的"Check and Set"功能。实质上,您希望创建一个执行以下操作的循环:

  1. 使用Bucket.Gets
  2. 检索要更新的记录及其CAS值
  3. 根据需要修改(1)返回的文档。
  4. 使用Bucket.Cas存储修改后的文档,并传递在(1)中检索到的CAS值。
  5. 如果(4)成功,则跳出循环。否则,请从(1)处重新开始。
  6. 请注意,每次循环检索文档都很重要。如果由于CAS值不正确而导致更新失败,则表示文档在读取和写入之间进行了更新。

答案 1 :(得分:0)

如果数据库有办法处理(即内置的原子计数器),你应该使用它。 如果没有,或者如果你想在go中执行此操作,则可以使用缓冲通道。除非缓冲区已满,否则插入缓冲通道不会阻塞。

然后,要一次一个地处理增量,在goroutine中你可以有类似的东西

for{
    select{
        value, _ := <-CounterChan
        incrementCounterBy(value)
    }
}