話接上回,上篇闡述了什麼是熱點帳戶,基本財務帳戶如何設計,冪等健和鏈式設計!本篇將針對熱點帳戶在實踐中引起的問題,梳理和拆解業務流,分析問題點,提出七種經常使用解決方案。
上線初期數據量較小,運行正常!
一次大促後,帳戶流水的總數目接近億級別,初現性能問題:系統總體的qps也就10+,但熱點帳戶寫入失敗率偏高,而且隨數據量增長失敗率逐步升高;整個帳戶系統全靠上游有redo標識位不斷重試,才能保證最終寫入成功!
web
哈哈,做爲一名擁有三年工做經驗的老碼農,面對問題,要作的第一件事,就是靜
,抽根菸靜靜,準備開搞!算法
拿到問題,抽根菸靜一下以後,分析問題須要三步:梳理數據流,拆解過程,定位問題點。先對財務帳戶更新的數據流進行拆解sql
鏈式鎖後的基本帳戶操做過程,分爲以下五階段數據庫
梳理數據流後,接下來分析每一個階段可能引起的問題。按照優先級,先分析業務問題區域(讀取階段,計算階段,寫入階段)
,一般問題會出如今業務階段;以後,再分析框架問題區域(請求階段和回調階段)
,該區域出現問題的狀況偏小,可是一旦出現問題,就是比較有意思^_^!架構
讀取階段,計算階段,寫入階段三個階段是具體的業務操做,從併發和耗時兩個角度來分析下可能的問題點併發
耗時分爲三塊框架
查詢未中primary,但命中索引,業務數據體並未徹底在索引中,所以訪問數據走index match;數據主鍵聚簇,惟一健索引查詢獲取數據,page極難命中cache,也不會命中磁盤電梯算法優化!結合實際狀況,查詢耗時在10-100ms級別
從總體上看,預估該階段的耗時在10-100+ms,從實際失敗率來看也基本一致!異步
按照上面分析,在瞬時QPS達到10+的狀況下,熱點帳戶總體延時在10-100+ms,因爲DB在寫入uniq_key保證鏈點惟一,因此出現併發寫入失敗也在情理之中
;而且隨着數據量的提高,讀取延時增長,寫入失敗率會繼續增長。高併發
請求階段作爲入口,通常也分爲三個小階段性能
請求階段核心耗時通常存在於框架加載和路由,高併發場景webserver和upstream之間的調用也是一個可能出問題點!當時財務系統,採用歡總封裝的go-thrift,而且其餘模塊並未出現請求階段問題,因此並未對這個階段的latency和併發作一個衡量,重點分析了業務模塊!
經過上面分析,目前問題的痛點是併發讀取熱點帳戶數據高延時引起寫入失敗
,提高讀性能成爲了關鍵
讀性能提高有兩個基本思路: 讀的時效快和讀的次數少
針對上面兩個基本思路,結合財務帳戶狀況提出了五種提高讀性能的解決方案
缺點是要保證持久化信息的準確性,引入事務寫。
缺點是跨時間讀不友好,開發量也不小
實現相對簡單,跨時間讀也比較友好,隨着數據量的提高,也是必需要作
,以後會詳細介紹歸檔方案和選型。五種解決方案各有千秋,做爲一個初期的財務系統推薦採用持久化last record和數據歸檔來保證寫入讀性能和總體讀的數據量。若是系統發展到了中期,推薦按照時間分庫分表。若是發展到了雙11或者春晚某些極端場景,犧牲掉部分準確性,採用階段快照也是能夠的。
存在計算階段形成的最大影響也就是引發了兩次數據傳輸,一般是不可避免的,可是若是真的是要進行提高有一種方案通用方案
經過存儲計算,轉嫁計算成本給DB,減小一次鏈路請求。
但不太推薦,複雜的sql每每有坑,insert computer from select 還會形成大面積的數據隔離,很容易引發死鎖。請求階段通常有三種形式:同步調用,異步調用和僞同步調用!
前兩種調用很是常見:同步爆池的狀況,通常採用限流來降壓,採用漏桶,令牌桶等等策略;異步調用一般採用消息隊列來削峯填谷;這裏重點闡述對於支付和財務系統在請求階段常常採用的僞同步的方式
僞同步流量較早出如今innodb,leveldb等存儲引擎爲了利用追加寫提高寫入性能,採用類WAL日誌來持久化數據。一般僞同步方案採用三件套:WAL日誌+校驗位+廣播消息
來完成一次完整的請求!流程圖通常以下
經過讀取wal日誌的核心數據,進行復瑣事務處理,若是成功進入下一階段;若是失敗,沒問題,經過外部trigger來觸發redo操做!若是屢次redo依然失敗,那麼經過undo來回滾數據
。在僞同步的模式下指標衡量:
對於資金處理過程,大量採用僞同步的請求方式來保證快速寫入和最終一致性。
總的來講,歸結了七種優化方式(哈哈,上篇寫的八種優化,當時總結的,如今愣是想不到還有啥了^_^)。其中請求和回調的僞同步方式,是在架構層面優化,這個在多數的財務系統和財務系統的內部數據流中都會用到;而讀寫和計算階段的優化,能夠跟進實際業務狀況進行選型處理。
面對各類優化方案,須要結合實際狀況作出取捨,有的是長期方案,有的是快速方案,但必定須要想清楚了再開搞
,過程當中有一個對小拽以後影響很大的事故,引覺得戒。
翻車過程:當時覺的讀->計算->寫這個過程,兩次讀DB操做,下沉計算過程到DB後,經過DB計算,能夠減小一次數據庫請求
。因而合併了一個大SQL,也就是所謂的insert ( field computer from select)
,覺的寫了個狂賺酷炫吊炸天的SQL,一上線,庫鎖死了!幸虧有前置的redo flag,全量redo數據恢復,要否則估計直接祭天了!
對於這個複雜大SQL事故,小拽總結了三個方面
莫炫技:沒啥好說的,解決問題的成就感要遠大於炫技! 簡單設計:簡單的設計一般意味着可依賴;複雜的設計要儘量的拆解,想清楚,隊友都理解不了的設計,那就別上線了,可能真的須要再思考拆解下 尊重線上:核心服務基本上線流程必定要遵照,測試,監控和回滾方案缺一不可
本篇主要針對熱點帳戶問題提出了七種經常使用的解決方案,下篇將繼續引伸探索下,各類解決方案在不規則高併發場景,例如雙十一,微博熱點事件中如何套用
預知後事如何,下回再聊!
【轉載請註明:熱點帳戶問題和經常使用解決方案【中】 | 靠譜崔小拽 】