作者:小傅哥
沉澱、分享、成長,讓自己和他人都能有所收穫!?
一、前言
你的程式碼出過事故嗎?
老人言:常在河邊走哪有不溼鞋。只要你在做著程式設計開發的工作就一定會遇到事故,或大或小而已。
當然可能有一部分研發同學,在相對傳統的行業或者做著使用者體量較小的業務等,很難遇到讓人出名的事故,多數都是一些線上的小bug,修復了也就沒人問了。
但如果你在較大型的網際網路公司,那麼你負責的開發的系統功能,可能面對的就是成百萬、上千萬級別使用者體量。哪怕你有一點小bug也會被迅速放大,造成大批量的客訴以及更嚴重的資金損失風險。就像:
- 拼多多“薅羊毛”事件,朋友圈瘋狂轉發。
- 淘寶昨現重大線上bug,S1級事故,疑似程式設計師故意埋雷。
您使用的程式是內測版本,將於當地時間 2020-03-28 到期,到期後將無法使用,請儘快下載最新版本。
- GitHub忘記續訂SSL證照導致網站排版混亂,部分網站不能正常開啟。
類似這樣事故的出現,可能是因為技術流程、方案實現、技術服務以及運營配置等等原因產生的。綜合可以概括為以下幾點:
- 功能流程設計類:通常指的是研發在設計產品邏輯功能實現流程中,錯誤的執行呼叫關係而造成的風險事故。
- 技術方案實現類:在研發設計好流程後,每一個功能點的實現方案會因人而異,也會由於理解偏差或不足,而導致實現過程中缺少了對程式碼在執行過程中健壯性的評估。
- 技術服務使用類:這一類說的是在研發使用資料庫服務、快取服務、大資料服務、配置中心服務以及釋出上線服務等時,對各項服務的配置以及使用上缺少一定的瞭解,而造成的事故。
- 後門違規操作類:這一類因公司對研發規範的執行強度不同,而是否會有此類風險。例如:有些研發同學會開發一些後門程式,比如可以在某個ERP頁面執行資料庫語句,臨時修改資料。這樣造成的風險,通常為後門違規操作,會有開除風險。
- 運營操作失誤類:在研發以為還有一部分公司內的夥伴會使用研發同學開發的運營系統,配置活動、變更使用者、執行流程等操作,但一般情況下這類系統缺少一定的強規則驗證,導致運營小白在操作過程中造成風險,從而引發事故。一般線上配置出錯誤卷,或者推錯簡訊給使用者等等,都是這樣發生的。
可以說,大多數比較蠢的事故主要是個人責任心問題。但那些有技術含量的事故,犯一次還是挺值得的。雖然公司很討厭你造成事故,因為會給公司帶來損失嘛!但這樣具有具有技術含量的事故,卻對你個人成長非常好的案例。不過禁酒雖好,可不能貪杯!
接下來,小傅哥就帶著你領略下各類事故的風采,看看在什麼場景、遇到什麼問題、怎麼解決的以及能學到什麼!
二、研發事故
1. 功能流程設計類
- 事故級別:P1
- 事故判責:相應的研發、測試總結覆盤,罰款50元給參加的會議的夥伴買棒棒糖以示警告。
- 事故名稱:抽獎積分支付流程不合理
- 事故現象:使用者積分多支付,造成批量客訴,當天緊急排查修復,並給使用者補充積分。
- 事故描述:這個產品功能的背景可能很大一部分研發都參與開發過,簡單說就是滿足使用者使用積分抽獎的一個需求。上圖左側就是研發最開始設計的流程,通過RPC介面扣減使用者積分,扣減成功後進行抽獎。但由於當天RPC服務不穩定,造成RPC實際呼叫成功,但返回超時失敗。而呼叫RPC介面的uuid是每次自動生成的,不具備呼叫冪等性。所以造成了使用者積分多支付現象。
- 事故處理:事故後修改抽獎流程,先生成待抽獎的抽獎單,由抽獎單ID呼叫RPC介面,保證介面冪等性。在RPC介面失敗時由定時任務補償的方式執行抽獎。流程整改後發現,補償任務每週發生1~3次,那麼也就是證明了RPC介面確實有可用率問題,同時也說明很久之前就有流程問題,但由於使用者客訴較少,所以沒有反饋。
- 學習總結: 呼叫的介面、傳送的MQ,並不一定會每次都成功。那麼一定要做好冪等性以及失敗後的補償,來把整個技術實現流程做的更加完善。就像小傅哥說的,擦屁屁的紙80%的面積其實都是保護手的!
網友事故分享:
事故名稱 | 事故描述 | 事故結果 |
---|---|---|
業務流程搞錯+程式碼頻繁開闢執行緒池 | 業務流程搞錯導致的問題就是改動特別大,有點類似重構程式碼了哎西,導致服務當機很久,客戶瘋狂反饋 | 瘋狂加班改業務,加了不知道多少個晚上,由於是菜狗子,寫的程式碼太垃圾了,被大佬給瘋狂叼 |
線上修改使用者收貨地址失敗(同事需要的問題,也可以借鑑下^v^) | 場景:客服反應使用者需要把收貨地址從河北省改為浙江省(因為疫情),公司要求修改線上資料需要提交工單,因此l到稽核平臺提交申請等一系列流程。 問題:工單顯示修改結果成功,但是資料沒有改過來,多為同事一起檢視sql發現sql編寫沒有問題。 解決過程:檢查sql是否正確,平臺是否修改成功,又檢查了資料是否正確,還檢查了修改時間是沒有問題的。 | 首先,忽略了一個問題,這個訂單資料是淘寶下單同步到我們訂單這邊的,資料修改的後,淘寶又同步也資料過來,把修改正確的資料又改為了河北的地址。然後就懷疑sql稽核平臺問題。到這裡故事已經講完了。結論:想告訴大家要相信程式碼,多檢查不確定的情況,不要鑽到死衚衕,老是懷疑稽核平臺問題,多檢查自身問題。 |
業務相關事故 | 剛加入一個新的團隊,沒有深入瞭解別人的程式碼就進行復用,沒有理解業務的場景就限制條件,類似的情況很多,只能說,再簡單的程式碼都要保持敬畏,因為你不知道哪裡會出問題 | 使用者投訴、領導批評 |
2. 技術方案實現類
- 事故級別:P0
- 事故判責:營銷活動推廣使用者較多,影響範圍較大,研發整改程式碼並做覆盤。
- 事故名稱:秒殺方案獨佔競態實現問題
- 事故現象:使用者看到可以購買,但只要一點下單就
活動太火爆,換個小手試試
。造成了大量客訴,緊急下線活動排查。 - 事故描述:這個一個商品活動秒殺的實現方案,最開始的設計是基於一個活動號ID進行鎖定,秒殺時鎖定這個ID,使用者購買完後就進行釋放。但在大量使用者搶購時,出現了秒殺分散式鎖後的業務邏輯處理中發生異常,釋放鎖失敗。導致所有的使用者都不能再拿到鎖,也就造成了有商品但不能下單的問題。
- 事故處理:優化獨佔競態為分段靜態,將活動ID+庫存編號作為動態鎖標識。當前秒殺的使用者如果發生鎖失敗那麼後面的使用者可以繼續秒殺不受影響。而失敗的鎖會有worker進行補償恢復,那麼最終會避免超賣以及不能售賣。
- 學習總結: 核心的技術實現需要經過大量的資料驗證以及壓測,否則各個場景下很難評估是否會有風險。當然這也不是唯一的實現方案,可以根據不同的場景有不同的實現處理。
網友事故分享:
事故名稱 | 事故描述 | 事故結果 |
---|---|---|
gc瘋狂回收 | 最近調整了自己業餘專案,跑一段時間就記憶體狂漲,還不能主動誘發 | dump記憶體中 |
重複扣入賬 | 併發數過多,資料庫連線滿,等待超時,session斷開。事務未提交,撈出繼續幹 | 500塊,深入併發程式設計,目前併發模型在我心中,歡迎battle |
資料覆蓋 | 迴圈更新資料時,開啟事務,持續時間過長,然後覆蓋掉了使用者在持續事務中提交的資料 | 沒影響,就是多加了幾天班 |
資料穿透 | 第三分使用指令碼海里請求併發造成資料穿透 | 削峰天谷, 使用佇列處理請求 |
這序列號咋重複了?? | 序列號應具有全域性的唯一,一條資料代表一條收入,序列號生成規則+程式碼bug導致序列號重複,影響了幾萬單收入核對 | 一級事故,回溯+通報 |
業務流程資料覆蓋 | 啟流程是一個公共類,各種交易都在這個裡面做,公共類一開始沒有經過設計,有一個方法返回了這個模板型別欄位,同時這個方法又是一個檢驗類,當時加了一個檢驗返回成錯誤碼了,導致所有的交易都啟不了流程。 | 挨批長記性。。。 |
simpledateformat的執行緒不安全導致多執行緒定時任務解析日期出錯 | 某定時任務執行時,需要做一些日期解析動作,就用了一個公共變數simpledateformat,來格式化,結果任務經常間歇性報錯,幾天報一次或者一兩週報一次,沒啥規律。看異常資訊才發現解析日期的字串很奇怪,經常出現很多奇奇怪怪的數字。 | 定時任務報錯,不過還好,定時任務只是為了做快取而已,不涉及到資料庫的更新,僅僅是查詢而已。 |
前端解析主鍵異常 | 由於Long型別最大19位而JavaScript最大接收數字為16位,固存在精度丟失問題 | 統一處理將id轉字串再返回前端 |
list遍歷刪除 | 遍歷刪除清空list陣列,為了節省計數器那小小一點記憶體,日了 | 報錯被叼了唄,為啥不用計數器?不香嗎? |
商品超賣 | 售賣一個兄弟部門的電子券商品,同步庫存的程式碼有問題,導致了超賣 對客戶造成了損失 | 罰款1000元 |
3. 技術服務使用類
- 事故級別:P2
- 事故判責:網友說被叼了一會,問題不大!
- 事故名稱:擴容時忽略了連線池梳理,導致連線池被打滿
- 事故現象:線上突然收到報警簡訊,開啟電腦一看,簡單的查詢介面超時到3分鐘才返回。
- 事故描述:幸好監控報警加的全,及時收到了報警簡訊,聯絡DBA檢查發現連線池被打滿了。為了快速解決線上報警,優先臨時擴容了連線池以及把服務重啟。觀察後連線池打滿消失了。
- 事故處理:檢查應用資料庫連線池配置,以及額外不經常上線的服務一併排查。經查詢發現所有的應用加起來連線池的最高配置超過資料庫分配的連線池數量。尤其是定時任務較長時間掃庫處理,是直接導致連線池打滿的重要原因。
- 學習總結: 研發不僅是程式碼開發搬磚人員,還要了解熟悉與之配套的服務。合理的使用、全面的考量才能避免一些看似不應該出現的事故問題。
網友事故分享:
事故名稱 | 事故描述 | 事故結果 |
---|---|---|
使用fastjson | 全身上下都是高危漏洞,一年不停升級版本打補丁 | 珍惜生命,遠離fastjson |
微信名儲存bug | 微信名的emj頭等存入mysql編碼是utf8的庫報錯 | 被懟了!改成utf8mb4編碼 |
磁碟不足 | 資料庫叢集磁碟空間不足,提前兩週提交擴容申請,甲方運維沒提交上去,最後某臺機器空間不足,導致整個叢集徹底不能工作,體驗一把某國產號稱可以方便橫向擴容的某idb的優越性 | 罰款,責任歸系統建設方 |
4. 後門違規操作類
- 事故級別:P0
- 事故判責:網友反饋,私自開發後門,執行sql錯誤,影響較大。開除!
- 事故名稱:通過後門程式修改線上資料
- 事故現象:這次修改影響範圍比想象的要小,只有部分資料因為快取失效了,才讀取資料庫的活動資訊。所有有少部分客訴說活動與名稱不符合。
- 事故描述:研發人員應運營要求修改線上配置錯誤的活動名稱,但任何郵件記錄以及負責人審批。所以只是研發私自通過後門程式提交sql語句修改,但忘記寫where條件,造成幾千條活動名稱被同時修改。
- 事故處理:事後聯絡DBA緊急通過binlog日誌進行資料修復。
- 學習總結: 研發人員應避免操作線上資料,尤其是變更資料類。也不要開發各類改資料、上線、傳配置檔案等後門。而應該嚴格遵守研發流程,緊急事情需要請求批准處理。
網友事故分享:
事故名稱 | 事故描述 | 事故結果 |
---|---|---|
刪除整個專案目錄檔案 | 測試區,測試刪除檔案時目錄寫錯,導致整個weblogic子專案目錄被刪 | 請專案中負責整合部署的公司幫忙重新部署,測試區癱瘓了兩天 |
誤更新生產訂單資料3萬多條 | 下班前,未帶核心過濾條件,導致誤更新3萬多條訂單資料,偷偷利用binlog恢復了,耗時3個小時 | 完美恢復資料 |
線上庫整庫誤刪除 | 應業務方要求要線上上環境建立線上聯調庫,使用了匯出資料庫DDL語句後,直接執行,導致執行了exists drop語句,刪除了線上庫所有資料,資料量大表均在千萬級,APP、網站全線癱瘓。 | 使用前一天的備份副本資料恢復,下載binlog日誌按操作避開事發時間點分割後編譯,匯入資料,然後再修復事故之後的資料,共計耗時48小時。 |
5. 運營操作失誤類
- 事故級別:P2
- 事故判責:網友說,金額太大沒發出去!被噴了一會!
- 事故名稱:運營把券配置成紅包
- 事故現象:線上使用者客訴,看到幾百億大的紅包,領不到!
- 事故描述:運營人員配置優惠券,但是型別選成了紅包,導致頁面展示出超大額的紅包金額待領取,都超出螢幕長度了!
- 事故處理:緊急下線活動,重新配置上線。同時產品設計需求,由研發人員實現對於此類配置提供明確、醒目的配置和完整的稽核流程。如果配置紅包、優惠券,會有校驗此券的是否存在以及紅包最大金額限制。
- 學習總結: 看上去是運營配置錯誤,但從某個角度看其實也可以說是研發在做功能實現時,太過於單一完成產品功能,而沒有加深考慮以及產品的易用性。有時候多問一句就少一個風險!
網友事故分享:
事故名稱 | 事故描述 | 事故結果 |
---|---|---|
業務漏洞 | 業務亂配優惠券,可以疊加,超級優惠,然後被薅羊毛 | 部門幫著查羊毛記錄,處理訂單,挽回損失。然後對外發公告宣稱是被部門的風控系統誤殺的。 |
貸款費率 | 運營配置T+1日結算貸款費率錯誤,導致使用者貸款金額發生錯誤。 | 上線新費率替換舊費率,已經產生的費率錯誤聯絡貸款使用者修復。 |
多活動互斥 | 三個部門的都做活動,但最後導致重複發獎。一個使用者邀請別人獎勵,變成了三份獎勵。 | 產品提供渠道和互斥功能,讓運營自己選擇是否可以並行發放獎勵。 |
三、總結
- 講道理,開發沒事故,不是沒使用者體量,就是沒使用者規模。否則只要是人就一定會出現事故,要不是小bug被你銷聲匿跡隱藏了,或者是大事故被噴了或者送飛機了。
- 而儘可能減少事故的方式是需要儘可能按照一定的研發流程來實現功能邏輯。就像:
設計評審,把控的是實現流程、程式碼評審,把控的是實現方案
,在配合上完善的監控和報警。只有這樣才能更少的減少不必要的事故。 - 關於研發在職場中的事故本文就講到這了,感謝粉絲分享出自己的遇到的事故,讓大家可以互相學習,減少離職扣工資的風險。?多關注小傅哥,一個寫有價值原創好文章的男人!
四、系列推薦
部落格:https://bugstack.cn
Github:https://github.com/fuzhengwei/CodeGuide/wiki