ReplyBot

客服整合重複收到事件怎麼辦?設計去重鍵與重試紀錄

從事件識別鍵、重送判斷、保存期限到重試監看,整理 webhook 去重與冪等處理流程,並用假設事件序列演練如何避免重複建案。

主題情境插畫:客服整合重複收到事件怎麼辦?設計去重鍵與重試紀錄

外部 webhook 有時會因網路逾時或回覆遺失而再次送達。若接收端已完成操作,卻把下一次投遞當成新通知,就可能重複建案、重複留言,或讓客服誤判處理量。設計去重時,應把事件身分、每次投遞與實際業務副作用分開記錄,而不是只比對顧客或訊息文字。

本文整理一般外部事件消費流程可採用的做法,不綁定特定平台欄位;實際重送行為仍須依發送端文件與遮蔽樣本確認。文中的事件序列是假設情境,供技術團隊演練資料紀錄、案件數量與復原方式。

實作步驟:哪個欄位可當事件識別;重送與新事件怎麼分;已處理事件保存多久;重複事件如何安全略過;失敗重試由誰監看;如何驗證不會重複建案

哪個欄位可當事件識別

先把「事件」定義成來源系統一次可辨識的通知,而不是一位顧客、一段對話或一張客服案件。第一順位是發送端提供且在重送時保持不變的事件識別碼;將來源名稱、租戶或帳號範圍與該識別碼組成唯一鍵,例如「source-shop-7|evt-81」。這樣不同來源剛好都發出 evt-81 時,不會互相誤判;若來源明確保證識別碼全域唯一,仍可保留來源欄位,方便追查與切換。不要拿顧客編號、訊息文字或案件編號單獨當鍵,因為同一顧客會有多則新訊息,內容相同也可能是兩次真實提問,而案件編號通常是在處理後才產生。

若樣本沒有穩定事件碼,先找來源文件或請提供端確認哪些欄位在重送時不變,再考慮由來源物件編號、事件種類及來源版本號組成複合鍵。版本號必須代表一次更新,不能拿易變的狀態欄位替代;單用時間戳也可能遇到精度不足或同時事件。可以把正規化後的欄位串接再雜湊,減少長鍵與格式差異,但雜湊只縮短表示,不能補救不穩定的輸入。保留原始來源識別欄位與鍵的版本,方便日後排查。

實作前挑選幾筆實際樣本,對照首次送達與重送內容,確認識別碼是否相同、作用範圍是否涵蓋帳號,以及欄位何時會變。把「缺鍵」當成待處理狀態,不要臨時改用整段 JSON 雜湊;來源若不能提供穩定鍵,就明確定義業務複合鍵與碰撞處理規則,並記下需要人工核對的情況。最後用資料庫唯一限制保護鍵,讓兩個同時到達的請求也只能有一筆事件紀錄。若來源版本改變,也要保留鍵規則的版本號,避免新舊程式對同一事件算出不同身份。

重送與新事件怎麼分

判斷重送,先比較相同來源範圍內的事件鍵,再看送達次數或時間。相同鍵通常表示同一個通知再次抵達;「第幾次嘗試」是傳輸資訊,不是新事件身分,因此要記錄在投遞紀錄,不能拼進去重鍵。不同鍵則先視為不同通知,再由業務規則判斷是否各自代表一個新動作。客服流程尤其不能只用顧客、文字或短時間窗口去重:顧客可能連續追問相同問題,也可能因送出按鈕而產生內容相同的兩則訊息,錯誤合併會讓團隊漏看需求。

可用兩層識別避免混淆:來源事件鍵回答「這個通知是否已收過」,業務動作鍵回答「這次副作用是否已執行」。例如同一筆訂單的狀態更新可能有不同事件碼但指向同一版本;是否更新同一案件,要依明確的版本或狀態轉移規則決定。若事件鍵相同、內容卻不同,不要用新內容覆寫舊資料,也不要把它默默當成新事件;保留差異摘要並暫停該筆或告警,請負責人核對來源是否重用了識別碼、欄位是否被正規化錯誤。

演練時記下首次收件時間、來源事件鍵、來源提供的嘗試次數、處理結果與副作用識別碼。第一次收到 evt-81 建立一筆事件;第二次仍是 evt-81,即使間隔幾分鐘也應走重送路徑;後來收到 evt-82,即使文字相同,也要按新通知規則處理。若來源沒有嘗試次數欄位,接收端可自行累計收件次數,但不要把自家計數誤寫成來源送達次數。將新事件和重送分開統計,才能看出真正的流量與重試狀況。把這條判準寫進事件契約,並用新事件與重送各一筆樣本確認沒有把不同訊息合併。

已處理事件保存多久

保存期限要跟「最晚仍可能再次送達或被人工重播的時間」對齊,而不是只看資料表清理方便。先查來源的重送政策與團隊允許手動重播的範圍,列出最長佇列延遲、故障排除時間和補送流程,再定義事件鍵至少保留到哪個作業邊界;若目前無法確認來源上限,先把未確認事項列給系統負責人,不要自行編造固定天數。超過保存期才收到舊事件時,鍵已刪除就可能再建一次案件,所以期限也要考量晚到通知的業務影響。

事件本文常包含訊息或顧客資料,保存需要和去重紀錄分開設計。可在處理完成後依內部資料政策刪除或縮短本文,只留下來源範圍、事件鍵、完成狀態、處理時間與副作用參照;這種精簡的去重墓碑仍能辨認晚到重送,但應限制查閱並避免放入不必要的個資。若客服案件需要保留內容,讓案件系統依其管理規則保存,接收紀錄不要無目的複製全部本文。

期限設定後,寫下清理時點、例外與重新處理程序,並檢查部署或人工重播是否會繞過原期限。需要重新演練舊事件時,採用有權限的操作流程,明確標記重播批次,不要先刪除去重鍵來「讓它再跑一次」。若確實必須重新執行,另建可追蹤的重播識別並要求負責人確認副作用策略。定期比較仍可重送的最舊事件與已清除鍵的範圍;保存不足就調整期限或保留更精簡的鍵,不要以保留所有原始資料代替期限設計。期限也應納入例行檢視,來源政策或人工補送方式改變時,重新估算可接受的晚到範圍。

重複事件如何安全略過

安全略過的前提是先把事件持久化,並讓唯一鍵與實際副作用一起受控制。若收件與建案都在同一資料庫,可在一筆交易中新增事件紀錄、建立案件,再標成完成;交易失敗就整筆回復,重送才有機會重新處理。若採非同步方式,先把已驗證的事件寫入耐久收件匣,再回覆來源已收妥,由內部工作者處理;此時要確保佇列和收件紀錄能恢復,不能只回覆成功卻把通知留在記憶體。

收件表以來源範圍和事件鍵設唯一限制。首次插入成功就取得處理權;若鍵已存在且狀態完成,回覆符合來源協定的成功結果,不再建立案件;若另一個工作者仍在處理,透過交易鎖、租約或原子狀態轉換避免兩邊同時執行。若既有狀態是可重試失敗,依錯誤類型與退避政策重新排程;若是內容不一致或永久錯誤,轉人工檢查。不要先將事件標成完成再建立案件,否則中途崩潰會讓重送被略過,案件卻不存在。

案件建立若在另一個服務或系統,資料庫交易不能替兩邊保證原子性。可用待送出的外送工作紀錄,讓重試沿用同一業務冪等鍵;若對方不支援冪等,則先查詢副作用參照、設計補償或人工對帳流程,不可假設網路逾時代表對方沒有建立案件。完成條件要明確:案件參照已保存、事件狀態已更新,或失敗原因已進入可追蹤佇列。每條分支都要留下可搜尋的事件鍵與結果,方便客服人員知道為何未新增案件。把完成、略過、等待及永久失敗定義成不同結果,避免所有非新增案件都被記成成功。

失敗重試由誰監看

重試監看要有明確負責人:每個來源整合指定一位主要維護者、一位代理人與交接方式,並列出值班期間誰接告警。監控應看待處理數量、最舊事件年齡、重試次數、永久失敗數,以及已收妥但沒有完成結果的事件;重複通知本身不一定是故障,重點是它有沒有被安全辨識、是否造成佇列累積。警戒門檻依團隊可接受的客服延遲與來源限制制定,先在演練中量出正常基線,再設定告警,不直接照搬別人的秒數或次數。

每筆重試紀錄至少要能回答:事件鍵為何、第一次和最近一次何時收到、目前狀態、嘗試次數、下次重試時間、上次錯誤分類、是否已建立案件及其參照。日誌避免複製不必要的訊息本文或個資;同一事件可用關聯識別串起接收、工作者及建案紀錄。把暫時性錯誤和永久錯誤分開,例如短暫連線問題可延後重試,格式不符則停止自動循環並送人工檢查。設定退避、上限與抖動時,也要尊重來源的速率限制及客服的時效需求。

值班流程要能執行:告警後先確認來源是否持續送達、收件佇列是否成長、錯誤是否集中在某類事件,再決定修復程式、調整設定或聯絡來源。超出自動重試上限的事件移入待查清單,附上去除敏感資料的錯誤摘要與重播步驟;人工重播前先確認原案件狀態,避免把修復當成重建。處理完記錄原因、影響範圍和恢復時間,並觀察佇列是否回到可接受水位。告警訊息要附上可搜尋鍵與責任人,不要把完整顧客對話貼進通知或一般聊天頻道。

如何驗證不會重複建案

驗證時把「送達了幾次」和「產生幾個業務結果」分開計數,並在隔離環境用合成事件演練,不使用真實客服資料。先測相同鍵順序送達兩次,再測兩個工作者同時收到相同鍵,接著模擬案件已建立但回覆逾時、工作者在完成標記前中斷,以及同一顧客送出內容相同但鍵不同的新訊息。每個場景都記錄收件列、處理狀態、案件參照和回覆結果;完成後核對唯一鍵沒有重複、真正的新事件沒有被誤合併,錯誤事件能進入人工檢查路徑。

以下是假設序列,數字只用來說明計數。09:00 收到 evt-A,第一次建案成功,但回覆在網路中遺失;資料庫保留 evt-A 已完成及案件 C-101。09:02 發送端再次送 evt-A,嘗試次數為二;系統查到完成紀錄,回覆成功,不新增案件。09:04 收到 evt-B,雖然屬於同一顧客且文字相同,但識別碼不同,依規則建立 C-102。09:04 另一個工作者同時收到 evt-B;第一個工作者完成後,另一個因唯一限制讀到完成結果而略過。總計四次投遞、兩個不同事件鍵、兩個案件;投遞四次不能被報成四筆新需求。

演練完檢查每個鍵只有一個完成結果,兩個新事件各有一個案件參照;再查重送是否得到來源可接受的回覆,失敗與並行紀錄是否可追蹤。若案件建立在外部系統,額外核對外部案件清單,不能只憑接收端日誌判定成功。保存演練輸入、預期結果與實際差異,修正鍵定義或交易邊界後重跑相關情境。下一步請技術團隊挑一筆已遮蔽識別資料的樣本,填上事件鍵、重試狀態、保存政策與預期案件數,再依這份假設序列逐項演練。若想查看 ReplyBot 的公開介紹,請前往 ReplyBot 官網。