我正在尝试将数据存储区用作分布式锁。根据文档,我预计以下代码在datastore: concurrent transaction
上会失败,但它只失败了<5%的时间。使用的数据库处于乐观并发模式。
我怎样才能让它锁定该实体并使任何并发读/写操作失败?
这段代码取自官方文档,在事务读写之间添加了一个Put
。
ctx := context.Background()
client, err := datastore.NewClientWithDatabase(ctx, "project-id", "database-id")
if err != nil {
panic(err)
}
type Counter struct {
Count int
}
var count int
key := datastore.NameKey("Counter", "singleton", nil)
if _, err = client.RunInTransaction(ctx, func(tx *datastore.Transaction) error {
var x Counter
if err := tx.Get(key, &x); err != nil && err != datastore.ErrNoSuchEntity {
return err
}
y := x
y.Count = 10
if _, err = client.Put(ctx, key, &y); err != nil {
return err
}
x.Count++
if _, err = tx.Put(key, &x); err != nil {
return err
}
count = x.Count
return nil
}); err != nil {
panic(err)
}
if err = client.Delete(ctx, key); err != nil {
panic(err)
}
fmt.Println("COUNT:", count)
1条答案
按热度按时间xdnvmnnf1#
只是为了确保我们在同一页上,你的数据库是在
OPTIMISTIC
模式,还是OPTIMISTIC_WITH_ENTITY_GROUPS
模式?https://cloud.google.com/datastore/docs/concepts/transactions#view_concurrency_mode
假设它使用
OPTIMISTIC
并发,启动事务并通过tx.Get(key, &x)
执行读取不会阻止另一个写入者修改同一文档。但是,假设client.Put(ctx, key, &y)
是一个阻塞操作,在RunInTransaction主体完成执行之前完成,则整个RunInTransaction操作应始终失败。在
PESSIMISTIC
模式下,可以使用在一个事务中获得的写锁来延迟其他事务写入器的完成,直到锁被释放:https://cloud.google.com/datastore/docs/concepts/transactions#concurrency_modes