1. 程式人生 > >系統架構中,對於熱點資料的處理

系統架構中,對於熱點資料的處理

一 背景     某個業務線 商品開放開使用者申請免費試用,當某個商品特別吸引人時,比如iPhone6 。肯定有一大波人為了少賣一個腎 瘋狂去搶申請資格。有甚者利用機器人申請註冊,於是簡單的申請操作變成了秒殺行為. 大量請求同時更新資料庫中的同一個商品的申請次數,update 操作給表加上行鎖,導致後面的請求全部排隊等待前面一個update完成,釋放行鎖後才能處理下一個請求。大量後來請求等待,佔用了資料庫的連線。一旦資料庫連線數被佔滿,就會導致後來的全部請求因拿不到連線而超時,業務請求出現無法及時處理的情況,資料庫系統的RT會異常飆高,業務層由於等待出現超時,app 層的連線耗盡,一系列的雪崩效應!
二 解決方案     從上面的背景分析,解決熱點資料併發更新需要注意核心問題: 減少直接對db層資料熱點的併發更新,本文從業務和資料庫的設計層面來規劃.同時也希望大家提更好的解決思路。1 前端層面   前端是整個流量的入口, 正常業務訪問時系統表現平穩,但是當有人惡意請求時,需要加上流控措施,比如常見的   a 需要使用者回答問題,填寫驗證碼,移動影象等等,防止或者減少有機器人來惡意請求。    b 頁面上採用防止機器人的判斷 兩秒以內的成功請求一律拒絕。   c 通過設定nginx ,對同一個ip源的請求次數做限制,防止機器人來申請。   優點 有效減少或者防止有人利用機器人惡意請求  缺點 存在一定的誤殺率,錯殺了正常的請求。
2 應用層    應用程式接收前端前端請求,進行一系列的資料庫操作,在我們規避了惡意請求之後如果還是有大量的資料庫寫訪問請求,我們需要    a 對業務做降級
限制介面的呼叫次數,降低對資料庫的請求壓力。
選擇不更新請求次數,弱化該商品申請次數的展現。類似於閱讀次數,申請次數 ,與金額,庫存無關的功能點。
    b 通過非同步更新來避免直接寫資料庫 。      應用使用分散式快取(比如tair)來儲存某項商品的申請次數或者某人的申請次數,以商品id/user_id 或者將where 條件作為key,申請試用人數為value/符合某項具體條件的 count結果為value, 有使用者申請成功則更新申請試用人數。不需要查詢和實時寫資料庫,每隔一定時間/次數將結果寫入資料庫。
      優點:該方法完全依賴於快取,讀寫速度快,不需要實時更新資料庫,減輕資料庫併發寫的壓力;      缺點:快取不是100%穩定,很容易丟,即使採用持久化的快取,在高併發下有時也可能會出現異常,穿透快取到db ,導致前端業務展現問題。3 資料庫層    a 將熱點資料拆分,分在不同的庫不同的表中,分散熱點資料,減輕資料庫併發更新熱點帶來的RT升高和應用連線等待時能保證業務能夠正常訪問其他商品表,損失區域性可用性。     優點:實時讀寫資料庫,前端展示資料的準確性。    缺點:業務邏輯稍顯複雜。   b 限流補丁     針對某些特定的sql語句 從MySQL 層面加以限制,當系統thread_running達到一定值或者某個sql執行時間超過一定閾值則拒絕該sql的執行。(阿里內部已經實現限流版本)