題幹與適用場景
這道題考察後端 API、物件儲存和並發控制。AWS 的條件請求支援在 PutObject、CompleteMultipartUpload 和 CopyObject 上設定前置條件:建立時可要求目標鍵不存在,更新時可要求 ETag 仍未改變。問題核心是把「檢查」和「寫入」放進儲存服務的原子判斷,而不是讓用戶端自己先 HEAD 再 PUT。
面試官考察點
強回答會先區分建立與更新,再選擇 If-None-Match: * 或帶目前 etag-value 的 If-Match,把條件失敗映射為可重試或需重新合併的結果。還應涵蓋 multipart 完成、弱 ETag 不適用、網路逾時後的不確定狀態和稽核指標。只說「加鎖」無法解釋多用戶端、跨程序和故障場景。
回答前需要釐清的問題
寫入語意
是只允許第一個寫入者建立不可變物件,還是允許依已讀版本更新?前者使用不存在條件,後者需要版本 ETag。
衝突處理
衝突時是回傳 412 讓用戶端重新讀取合併,還是放棄本次寫入?若物件代表清單或登錄表,通常不能靜默覆蓋。
上傳路徑
小物件走 PutObject,大物件是否使用 multipart?確認條件要放在最終完成請求,並定義上傳中斷、重試和清理規則。
30 秒回答框架
「我先確定是建立還是依版本更新。建立用 If-None-Match: *,讓 S3 原子拒絕既有鍵;更新先讀取目前 ETag,再用 If-Match 提交,ETag 改變就回傳 412,讓用戶端重新讀取或合併。multipart 上傳要在 CompleteMultipartUpload 再套用條件。逾時不能直接重試未知狀態,應先查詢物件或用冪等鍵確認結果,並監控 412、孤兒分段和重試次數。」
分步驟深入解答
第一步:淘汰 check-then-act
「先 HEAD、再 PUT」存在競態:兩個用戶端都讀到不存在,隨後都寫入。把前置條件放進同一個寫入請求,才能讓儲存層依目前物件狀態判斷並拒絕衝突。
第二步:選擇條件
建立不可變物件時使用 If-None-Match: *;它只在沒有目前表示時成功。更新既有物件時使用強比較的 If-Match,只有 ETag 與讀取版本一致才寫入;不匹配回傳 412,保護較新的內容。
第三步:定義衝突協議
收到 412 後不要盲目覆蓋。用戶端重新 GET 目前物件,計算自己的變更能否合併;不能合併就提示人工處理或產生新鍵。重試應帶退避和上限,避免熱門鍵形成重試風暴。
第四步:涵蓋 multipart 與複製
大物件分段上傳期間,其他用戶端可能先建立同名物件;最終 CompleteMultipartUpload 仍需條件檢查。複製或替換流程同樣要帶 ETag 條件,清理失敗的 multipart 由生命週期規則兜底。
第五步:處理逾時和可觀測性
請求逾時不代表寫入失敗。先用 HEAD 或帶條件的讀取確認物件版本,再決定是否重試;建立操作使用用戶端命令 ID 記錄意圖。監控 412 比例、成功重試率、孤兒分段和物件版本漂移,驗證衝突確實被拒絕而非覆蓋。
高品質示範回答
我會把物件分成不可變資料檔和可更新登錄表。資料檔建立用 If-None-Match: *,同名寫入只有一個成功;登錄表讀取 ETag 後用 If-Match 更新,若回傳 412 就重新讀取並合併,而不是覆蓋別人的版本。大檔案在 CompleteMultipartUpload 再做條件檢查,失敗的上傳由清理工作回收。網路逾時後先查詢物件和 ETag,再決定重試。這樣 S3 負責原子衝突判斷,用戶端負責合併策略和冪等紀錄;監控 412、重試和孤兒分段來驗證流程。
常見錯誤
- 錯誤表現: 先 HEAD 判斷不存在,再 PUT。→ 失敗原因: 兩個用戶端可同時通過檢查。→ 修正方法: 在 PUT 上使用
If-None-Match: *。 - 錯誤表現: 更新時使用
If-None-Match。→ 失敗原因: 它表達「必須不存在」,無法保護已讀版本。→ 修正方法: 讀取強 ETag 後使用If-Match。 - 錯誤表現: 412 後無條件重試原請求。→ 失敗原因: 可能反覆覆蓋或製造重試風暴。→ 修正方法: 重新讀取、合併或明確放棄,並限制退避重試。
- 錯誤表現: 只在首個分段請求設定條件。→ 失敗原因: 最終完成時物件狀態可能已變化。→ 修正方法: 在
CompleteMultipartUpload重新套用條件。
追問及應對
追問一:ETag 能當內容雜湊嗎?
不能一概而論。題目需要的是版本驗證器;multipart 或加密場景下不要把 ETag 當成通用內容摘要,依服務文件選擇校驗欄位。
追問二:412 與 409 如何區分?
以 API 文件定義為準:412 表示請求前置條件不滿足,適合讓用戶端重新讀取;其他衝突狀態可能表示資源狀態或操作語意衝突,不能只憑狀態碼猜測。
追問三:用戶端合併失敗怎麼辦?
保留目前版本,產生衝突紀錄或新鍵,交給擁有業務脈絡的人處理;不要為了成功率靜默覆蓋。
追問四:如何測試並發正確性?
讓多個用戶端同時建立和更新同一鍵,注入逾時、重複完成 multipart 和清理失敗,驗證最多一個建立成功、舊版本不會覆蓋新版本,並核對稽核日誌。