在GCS中向同一目标对象执行compose操作是否会出现竞态条件?
问题
两个进程同时运行,各自创建临时文件后,尝试通过GCS的compose操作追加内容到共享目标文件:
- 进程1:创建
my_file1.txt,执行compose(shared_file.txt, my_file1.txt) -> shared_file.txt - 进程2:创建
my_file2.txt,执行compose(shared_file.txt, my_file2.txt) -> shared_file.txt
我们期望shared_file.txt最终包含两个临时文件的内容,有以下几个疑问:
- 是否可能最终
shared_file.txt仅包含其中一个临时文件的内容? - GCS有没有一致性检查机制,能避免
compose操作在目标文件被修改期间覆盖内容? - 如果GCS在
compose期间会锁定目标文件或者线性执行请求,是不是结果肯定会包含两个文件内容(只是顺序不确定)?如果不是的话,是不是必须用Generation Matching+请求重试才能确保两个追加都成功?
解答
确实有可能仅保留一个文件的内容
如果两个compose请求同时发起且无并发控制,会出现「丢失更新」问题:两个进程都读取了同一个版本的shared_file.txt,各自完成compose后先后写入GCS,后写入的结果会直接覆盖先写入的,最终只有后写入的临时文件内容被保留。GCS原生
compose没有自动的并发冲突检查
GCS的compose操作本身不会主动检测目标文件在请求执行过程中是否被其他请求修改。它只会基于你请求时指定的源文件版本(未指定则用最新版本)生成新文件,然后直接覆盖目标文件。GCS不会锁定目标文件或保证请求线性执行,必须用版本匹配+重试确保结果
GCS处理compose请求时,不会对目标文件加锁,也不保证多个请求的执行顺序是线性的,默认情况下无法确保两个文件内容都被追加。
要解决这个问题,必须采用Generation Matching(版本匹配)+ 请求重试的方案:- 执行
compose前,先获取目标文件当前的generation(版本号) - 在
compose请求中指定这个generation作为匹配条件,只有当目标文件当前版本与该值一致时,请求才会执行 - 如果请求返回
412 Precondition Failed(说明目标文件已被其他进程修改),则重试整个流程:重新获取最新generation,再发起带版本匹配的compose请求
- 执行
通过这种方式,每次compose都是基于最新的目标文件版本执行,最终两个临时文件的内容都会被追加,仅内容顺序取决于请求成功的先后。
内容的提问来源于stack exchange,提问作者Brayden
相关产品推荐
相关产品推荐

