针对 Google 照片 API 的竞争条件

Race condition against Google Photos API

我正在开发 this CLI to upload images to Google Photos. The CLI creates several go routines to upload files in parallel 1. Once it's uploaded, the same routine adds it to an Album. These albums are created if they didn't exist before 2

由于并发性以及 Google 照片 API 允许创建两个 Albums 同名 ,我我想避免使用重复的专辑名称。

GetOrCreateAlbumByName() 3 不能确保 Album 是唯一的。它基本上询问是否存在同名专辑,如果不存在,它将创建一个新专辑。但是可以并行调用此函数,因此可以创建两个具有相同名称的 Album。除了实现互斥锁,我还在观察重复项。

你建议如何处理?

  1. 创建一个处理相册创建的 Worker(如微服务)。在创建相册之前,每个 go routine 都会被阻塞。它将删除 Album 创建部分的并发。
  2. 维护一个相册缓存并用它来检查相册是否已经创建。在那种情况下,竞争条件也可能发生,但概率较小。
  3. 同时使用 1 和 2。
  4. 其他,请说明。

我担心 1、2 和 3...这就是为什么我想知道您将如何处理它。

提前致谢

您使用 Client.GetOrCreateAlbumByName() 获取或创建相册。此方法对于并发使用是安全的,并且它在内部使用互斥体来序列化调用,从而确保不会创建重复项。

但是,您正在创建和使用多个客户端 here,这意味着对所有客户端的并发调用没有序列化,只有对单个客户端的并发调用。

所以解决方案要么使用单个客户端,然后所有调用都将被序列化,或者如果这不可能,您必须序列化对所有客户端的调用,例如使用单个互斥锁或其他方式。

如何使用互斥量序列化对所有客户端的调用的示例:

var mu sync.Mutex

func GetOrCreateAlbumByName(c *gphotos.Client, name string) (*photoslibrary.Album, error) {
    mu.Lock()
    defer mu.Unlock()
    return c.GetOrCreateAlbumByName(name)
}

无论你在哪里使用 client.GetOrCreateAlbumByName(name),请将其替换为调用:

GetOrCreateAlbumByName(client, name)