Search code examples
google-cloud-storagegoogle-hadoop

GCS - Global Consistency with delete + rename


My issue may be a result of my misunderstanding with global consistency in google storage, but since I have not experienced this issue until just recently (mid November) and now it seems easily reproducible, I wanted some clarification. The issue started happening in a piece of spark code running on compute engine using bdutil but I can reproduce from the command line with gsutil.

My code is deleting a destination path and then immediately renaming a source path as the destination path. With global consistency I would expect since the destination path no longer exists, the src would be renamed to the destination, but instead the src is being nested inside destination as if the destination still exists and that is not consistent.

The hadoop code to reproduce looks like:

fs.delete(new Path(dest), true)
fs.rename(new Path(src), new Path(dest))

From command line I can reproduce with:

gsutil -m rm -r gs://mybucket/dest
gsutil -m cp -r gs://mybucket/src gs://mybucket/dest

If the reason is because list operations are eventually consistent and the FileSystem implementation is using list operations to determine if the destination still exists, then I understand, and then is there a recommended solution to ensure the destination no longer exists before renaming?

Thanks, Luke


Solution

  • Read-after-write (including delete) operations are strongly consistent, so for example, if you did:

    gsutil -m rm -r gs://mybucket/dest
    # Command output shows it removed gs://mybucket/dest/file1
    gsutil cp gs://mybucket/dest/file1 my_local_dir/file1
    

    That would always fail.

    However, to determine if a "directory" exists, gsutil must perform an eventually-consistent listing operation to find out if any object in Google Cloud Storage's flat name space has a prefix with the name of that "directory". This can lead to the problem you described, and I expect that the hadoop code behaves similarly.

    There isn't a strongly consistent workaround for this problem because there's no way to check for the existence of a prefix in a strongly-consistent way.