睿文小說 > 兵法程式設計師:從小白到CTO > 第4章 錯誤的漣漪

第4章 錯誤的漣漪

⬅ 上一章 📋 目錄 ⚠ 報錯 下一章 ➡
⭐ 加入書籤
推薦閱讀: 花都風流第一兵王 代嫁寵妻是替身 天鋒戰神 穿越古代賺錢養娃 我覺醒了神龍血脈 我的老婆國色天香 隱婚嬌妻別想跑 遲遲也歡喜 全職獵人之佔蔔師

監控螢幕的綠光映在李工臉上,像某種不祥的預兆。

“錯誤型別分佈調出來了。”他敲了幾下鍵盤,螢幕上跳出密密麻麻的圖表,“你看,主要是兩種:資料庫連線超時和唯一約束衝突。”

林夕盯著“唯一約束衝突”那幾個字。會員兌換記錄表裏,每個兌換訂單應該有唯一的業務流水號。衝突意味著——有重複的流水號試圖插入。

“衝突數量?”

“從下午兩點到現在,37次。”李工放大時間軸,“分佈很均勻,大概每小時10次。”

每小時10次衝突,在每天數十萬兌換請求的總量裏,確實微不足道。但就像精密儀器裏混進的一粒沙,它不應該出現。

“能查到具體是哪些請求衝突嗎?”林夕問。

李工搖搖頭:“生產資料庫的binlog(二進製日誌)隻保留七天,而且查這種細節需要DBA(資料庫管理員)許可權,我沒有。”他頓了頓,“不過我可以看慢查詢日誌,至少知道是哪些SQL語句出問題了。”

慢查詢日誌開啟,一行行記錄滾動過去。林夕很快捕捉到了規律——出問題的都是同一個INSERT語句,向兌換記錄表插入資料。衝突的欄位是`order_no`訂單號。

“訂單號怎麽生成的?”他問。

“前端生成,UUID(通用唯一識別碼),應該不會重複啊。”李工也覺得奇怪,“除非……”

兩人對視一眼,同時想到了那個可能性:同一個訂單號,被用了兩次。

“有沒有可能,”林夕慢慢地說,“是前端生成了訂單號,發起請求,但因為網路問題沒收到響應,於是前端又用同一個訂單號重試了?”

“但防重複提交機製應該阻止這種重試。”李工說完,自己停住了,“除非那個機製失效了。”

他們一起看向監控螢幕上那個微小的錯誤率波動曲線。0.05%的錯誤率,如果換算成具體數字,大概每2000次請求會有一次失敗。而兌換介麵今天的請求量是……林夕快速心算,大約80萬次。

也就是說,大概有400次異常。

“37次唯一約束衝突,隻是冰山露出水麵的部分。”林夕低聲說,“更多請求可能根本就沒到資料庫這層,在前端或閘道器就被攔截了。”

李工沉默了幾秒:“我去申請更高許可權,查binlog。但這事兒得先跟周凱說一聲。”

“他讓我私下查,不要聲張。”林夕想起蘇晴的叮囑。

“那也得說。萬一真是係統問題,瞞不住的。”李工已經起身,“我去找他,你繼續分析。”

林夕回到工位時,已經晚上八點。開放式辦公區空了大半,隻有幾個加班的程式設計師戴著耳機,沉浸在程式碼世界裏。他的螢幕還停留在技術優化方案的檔案頁麵,遊標在“建議將防重複提交時間視窗從60秒調整為5秒”這句話後麵閃爍。

他刪掉了這句話,重新寫:“建議重新評估防重複提交機製在高並發場景下的有效性,並考慮引入分散式鎖方案。”

剛寫完,周凱的微信訊息跳出來:“來小會議室。”

小會議室裏隻有周凱一個人。他麵前的膝上型電腦開著,螢幕上正是兌換介麵的錯誤率監控。

“坐。”周凱的表情很平靜,“李工跟我說了。你覺得問題出在哪?”

林夕沒有立刻回答。他在觀察——周凱的語氣、神態、手指在觸控板上的無意識滑動。這是《孫子兵法》裏最基本的“知彼”:先瞭解對方的狀態,再決定如何應對。

“從現有資料看,可能是防重複提交機製在某些邊界情況下失效了。”林夕選擇用中性的描述,“加上今天上線的彈窗功能增加了使用者等待時間,讓一些原本不會重試的請求發生了重試。”

“你是說,我們上線了一個有問題的功能?”周凱問。

“功能本身沒問題,但它暴露了係統原有的潛在問題。”林夕糾正道,“就像一麵鏡子,照出了牆上原本就有的裂縫。”

周凱笑了笑,這個笑容裏有些林夕看不懂的東西:“很形象的比喻。那你覺得該怎麽修?”

“短期,可以先把時間視窗調回5秒,減少重試視窗。中期,需要引入更可靠的冪等機製,比如讓後端生成訂單號。長期——”林夕停頓了一下,“可能需要重構整個兌換流程的並發控製。”

“很好的思路。”周凱點頭,“但你想過沒有,為什麽三年前陳啟明設的是5秒,而我後來要改成60秒?”

林夕當然想過,但他沒說話,等待下文。

“因為使用者體驗。”周凱身體前傾,雙手交叉放在桌上,“5秒太短了。使用者點完兌換,如果頁麵卡一下,超過5秒,他再點就會報‘操作過於頻繁’。使用者看不懂技術錯誤,隻會覺得我們係統爛。所以我改成了60秒——給使用者足夠的耐心。”

“但在高並發下……”

“在高並發下,我們需要平衡。”周凱打斷他,“平衡技術完美和業務需求。小林,你技術很好,也很細心,這是優點。但你要學會從更高的角度看問題。偶爾幾十個訂單衝突,對比我們每天處理的百萬級訂單,影響微乎其微。而如果我們為了追求技術上的‘零錯誤’,讓使用者體驗變差,那纔是真正的損失。”

這番話說得滴水不漏,甚至很有道理。林夕幾乎要被說服了。

但資料在說話。那些隱藏在水麵下的異常請求,那些可能已經發生的重複扣款——對係統來說也許是百萬分之一,但對每一個遇到問題的使用者來說,就是百分之百。

“我明白了。”林夕說,“那接下來怎麽處理?”

“兩個方案。”周凱豎起兩根手指,“第一,保守方案:我們把時間視窗調回5秒,明天白天就改。這樣最安全,但可能引來一些使用者投訴。第二,激進一點:我們加強監控,觀察兩天,如果錯誤率不再上升,就維持現狀。同時你繼續寫優化方案,我們下個版本徹底解決。”

“您傾向於哪個?”林夕問。

周凱沒有直接回答:“你是這個功能的負責人,你覺得呢?”

一個溫柔的陷阱。無論林夕選哪個,後果都要自己承擔——選第一個,如果引發使用者投訴,是“不考慮使用者體驗”;選第二個,如果問題擴大,是“判斷失誤”。

林夕沉默了幾秒,然後說:“我需要更多資料來做判斷。能不能給我更高許可權,讓我查一下具體的衝突訂單,看看影響範圍到底有多大?”

周凱臉上的笑容淡了些:“生產資料許可權很敏感,需要層層審批。這樣吧,我給你開個臨時許可權,但隻能查今天的資料,而且不能匯出。可以嗎?”

“可以,謝謝凱哥。”

許可權在十分鍾後開通。林夕回到工位,開始查詢。

查詢結果讓他倒吸一口涼氣。

37次唯一約束衝突,對應的使用者有31人。其中4個使用者遇到了兩次衝突,2個使用者遇到了三次。這些衝突訂單的時間分佈很集中——都在下午兩點到四點之間,也就是彈窗功能上線後的第一個高峰期。

更關鍵的是,通過關聯查詢,他發現這31個使用者中,有19人隨後又發起了新的、成功的兌換請求。這意味著什麽?

意味著他們在第一次兌換“看似失敗”後,又重新操作,並且成功了。而第一次的請求,可能已經在後台處理成功,隻是前端沒收到響應。

林夕快速計算了一下:如果這19個使用者都被重複扣了積分,那每個人損失幾百到幾千積分不等,按兌換比例換算成現金,大概……

他的計算被手機震動打斷。是蘇晴打來的。

“林夕,你在公司嗎?”她的聲音有些急促,“客服那邊收到集中反饋了,有十幾個使用者都說積分兌換出了問題。有的說扣了積分沒收到商品,有的說被扣了兩次。客服已經轉過來五個工單了。”

“什麽時候開始的?”

“就這半小時。我們剛剛在內部群裏同步了情況。”蘇晴停頓了一下,“周凱說讓你先別動,他馬上組織會議。”

會議室裏很快坐滿了人。產品、技術、測試、客服的代表都在。氣氛凝重。

周凱主持會議,語氣依然沉穩:“情況大家都知道了。目前收到11個使用者反饋,問題集中在積分兌換。蘇晴,你把工單情況說一下。”

蘇晴開啟投影,列出了工單概要:使用者反饋的問題確實如她所說,集中在重複扣款和兌換失敗上。時間都在下午。

“技術側初步分析,”周凱繼續說,“可能是今天上線的彈窗功能,與係統原有的防重複提交機製有相容性問題。小林,你給大家同步一下你的發現。”

林夕站起來,走到投影前。他沒有直接說“時間視窗”的曆史,而是展示了那37次資料庫衝突的資料,以及關聯分析出的19個可能重複扣款的使用者。

“所以,問題根源可能是防重複提交機製在高並發下的失效。”他總結道,“彈窗延長了使用者等待時間,放大了這個問題。”

“解決方案呢?”一個產品經理問。

“短期,可以立刻把防重複提交的時間視窗從60秒調整為5秒,減少重試機會。同時後端增加對重複訂單的攔截和告警。”林夕說,“長期,需要重構整個並發控製。”

會議室裏議論紛紛。

“改回5秒,使用者投訴怎麽辦?”有人問。

“比現在使用者被重複扣款的投訴要好。”蘇晴冷靜地說,“我是產品,我必須站在使用者這邊。技術問題可以優化,但使用者信任一旦丟了,很難挽回。”

周凱抬手示意安靜:“這樣,我們分兩步走。第一,立刻回滾彈窗功能——這個改動最小,風險最低。第二,技術側評估,是否需要在今晚就調整時間視窗引數。”

“彈窗功能是市場部的緊急需求。”有人提醒。

“出了問題,再緊急的需求也得讓路。”周凱果斷地說,“小林,你負責回滾。李工,你準備調整引數,但先別執行,等我通知。”

會議在九點半結束。林夕回到工位,開始回滾程式碼。這個過程很簡單,隻需要撤銷今天的提交,重新發布。

十點,回滾完成。監控顯示,兌換介麵的錯誤率開始下降,從0.05%降到了0.03%。

但使用者反饋沒有停止。十點半,客服工單增加到了23個。

周凱的辦公室燈還亮著。林夕走過去時,門虛掩著。他聽到周凱在打電話:

“……我知道,但現在是穩定第一。彈窗已經回滾了,引數調整……再觀察一下。對,使用者反饋我們正在處理,會做好補償……”

語氣裏有種林夕從未聽過的疲憊。

他敲了敲門。

周凱結束通話電話,揉了揉眉心:“進來。回滾好了?”

“好了。錯誤率在下降,但沒完全恢複到之前水平。”林夕說,“我覺得,引數可能還是得調。”

周凱看著他,沉默了很久。窗外,城市的霓虹在夜色中流動,映在他鏡片上,讓人看不清眼神。

“小林,”他緩緩開口,“你知道三年前那場事故,最後賠了多少錢嗎?”

林夕搖頭。

“一百七十萬。”周凱說,“不是現金賠償,是等額的積分、優惠券、會員權益。陳啟明當時堅持要立刻修複資料庫主從問題,但我建議先做使用者安撫,等技術方案成熟再說。我們吵了一架。最後他妥協了,但心也涼了。”

他頓了頓:“我後來改那個時間引數,也是想避免再次走到那一步——既要技術完美,又要業務不受影響,哪有那麽容易?”

這話裏有真切的無奈,也有某種自我辯護。

“但如果現在不調,問題可能會擴大。”林夕堅持道。

周凱站起身,走到窗邊,背對著林夕:“你知道嗎,有時候做技術決策,不能隻看資料。還要看時機,看人心,看代價。”

他轉過身,臉上是林夕完全看不懂的表情:“引數可以調。但不是現在。等今晚淩晨三點,資料庫做主從重建的時候,一起改。那時候流量最低,影響最小。”

“那使用者的損失……”

“客服會處理,該補償的補償。”周凱說,“這件事我會負責。你回去休息吧,今天辛苦了。”

林夕走出辦公室時,總覺得哪裏不對。周凱的態度轉變太突然了——從堅持“使用者體驗”,到同意深夜修改關鍵引數。

回到工位,他看了一眼監控。錯誤率還在緩慢下降,但速度越來越慢。0.03%,0.029%,0.028%……

像一根被輕輕拉住的繩子,不知道什麽時候會突然繃緊。

他開啟資料庫查詢界麵,想做最後一次檢查。但臨時許可權已經過期了——周凱給的許可權隻有幾個小時。

在頁麵關閉前的最後一秒,林夕瞥見查詢曆史裏的一條記錄。不是他查的。

查詢語句是:“SELECT COUNT() FROM exchange_log WHERE create_time > u00272023-07-13 14:00:00u0027 AND error_code u003d u0027DUPLICATE_ORDER”

查詢時間:晚上九點零五分。

那時候,周凱正在主持會議。

而查詢結果,顯示在曆史記錄的最後一行:

327

不是37。

是327。

林夕盯著那個數字,後背一陣發涼。

有人在九點零五分就知道了真實的資料規模,但在會議上,所有人都以為隻有37次衝突。

誤差不是十倍。

是十倍。

夜色如墨,吞噬了窗外最後一點天光。遠處的城市燈光依然璀璨,但林夕知道,就在這片璀璨之下,有些東西已經開始失控了。

而那個真正知道失控規模的人,選擇了沉默。

為什麽?

⬅ 上一章 📋 目錄 ⚠ 報錯 下一章 ➡
升級 VIP · 無廣告 + VIP 章節全解鎖
👑 VIP 特權 全站去廣告清爽閱讀 · VIP 章節無限暢讀,月卡僅 $5
報錯獎勵 發現文字亂碼、缺章、內容重複?點上方「章節報錯」回報,審核通過立獲 3天VIP
書單獎勵 前往 個人中心 投稿你的私藏書單,審核通過立獲 7天VIP
⭐ 立即升級 VIP · 月卡僅 $5
還沒有帳號? 免費註冊 | 登入後購買