秒殺特點及思路?
短時間內(nèi),大量用戶涌入,集中讀和寫有限的庫存。
盡量將請求攔截在系統(tǒng)上游(越上游越好);讀多寫少的多使用緩存(緩存抗讀壓力);
從分層角度理解?
層層攔截,將請求盡量攔截在系統(tǒng)上游,避免將鎖沖落到數(shù)據(jù)庫上。
第一層:客戶端優(yōu)化
產(chǎn)品層面,用戶點擊“查詢”或者“購票”后,按鈕置灰,禁止用戶重復提交請求;JS層面,限制用戶在x秒之內(nèi)只能提交一次請求,比如微信搖一搖搶紅包?;究梢詳r截80%的請求。
第二層:站點層面的請求攔截(nginx層,寫流控模塊)
怎么防止程序員寫for循環(huán)調(diào)用,有去重依據(jù)么? IP? cookie-id? …想復雜了,這類業(yè)務都需要登錄,用uid即可。在站點層面,對uid進行請求計數(shù)和去重,甚至不需要統(tǒng)一存儲計數(shù),直接站點層內(nèi)存存儲(這樣計數(shù)會不準,但最簡單,比如guava本地緩存)。一個uid,5秒只準透過1個請求,這樣又能攔住99%的for循環(huán)請求。對于5s內(nèi)的無效請求,統(tǒng)一返回錯誤提示或錯誤頁面。
這個方式攔住了寫for循環(huán)發(fā)HTTP請求的程序員,有些高端程序員(黑客)控制了10w個肉雞,手里有10w個uid,同時發(fā)請求(先不考慮實名制的問題,小米搶手機不需要實名制),這下怎么辦,站點層按照uid限流攔不住了。
第三層:服務層攔截
方案一:寫請求放到隊列中,每次只透有限的寫請求到數(shù)據(jù)層,如果成功了再放下一批,直到庫存不夠,隊列里的寫請求全部返回“已售完”。
方案二:或采用漏斗機制,只放一倍的流量進來,多余的返回“已售完”,把寫壓力轉(zhuǎn)換成讀壓力。讀請求,用cache,redis單機可以抗10W QPS,用異步線程定時更新緩存里的庫存值。 、
還有提示“模糊化”,比如火車余票查詢,票剩了58張,還是26張,你真的關注么,其實我們只關心有票和無票。
第四層:數(shù)據(jù)庫層
瀏覽器攔截了80%,站點層攔截了99.9%并做了頁面緩存,服務層又做了寫請求隊列與數(shù)據(jù)緩存,每次透到數(shù)據(jù)庫層的請求都是可控的。 db基本就沒什么壓力了,通過自身鎖機制來控制,避免出現(xiàn)超賣。
從架構角度理解?
高性能
動靜分離 秒殺過程中你是不需要刷新整個頁面的,只有時間在不停跳動。這是因為一般都會對大流量的秒殺系統(tǒng)做系統(tǒng)的靜態(tài)化改造,即數(shù)據(jù)意義上的動靜分離。動靜分離三步走:
數(shù)據(jù)拆分;靜態(tài)緩存;數(shù)據(jù)整合。
熱點優(yōu)化 數(shù)據(jù)的熱點優(yōu)化與動靜分離是不一樣的,熱點優(yōu)化是基于二八原則對數(shù)據(jù)進行了縱向拆分,以便進行針對性地處理。熱點識別和隔離不僅對“秒殺”這個場景有意義,對其他的高性能分布式系統(tǒng)也非常有參考價值。
系統(tǒng)優(yōu)化
減少序列化:減少 Java 中的序列化操作可以很好的提升系統(tǒng)性能。序列化大部分是在 RPC 階段發(fā)生,因此應該盡量減少 RPC 調(diào)用,一種可行的方案是將多個關聯(lián)性較強的應用進行 “合并部署”,從而減少不同應用之間的 RPC 調(diào)用(微服務設計規(guī)范)
直接輸出流數(shù)據(jù):只要涉及字符串的I/O操作,無論是磁盤 I/O 還是網(wǎng)絡 I/O,都比較耗費 CPU 資源,因為字符需要轉(zhuǎn)換成字節(jié),而這個轉(zhuǎn)換又必須查表編碼。所以對于常用數(shù)據(jù),比如靜態(tài)字符串,推薦提前編碼成字節(jié)并緩存,具體到代碼層面就是通過 OutputStream() 類函數(shù)從而減少數(shù)據(jù)的編碼轉(zhuǎn)換;另外,熱點方法toString()不要直接調(diào)用ReflectionToString實現(xiàn),推薦直接硬編碼,并且只打印DO的基礎要素和核心要素
裁剪日志異常堆棧:無論是外部系統(tǒng)異常還是應用本身異常,都會有堆棧打出,超大流量下,頻繁的輸出完整堆棧,只會加劇系統(tǒng)當前負載??梢酝ㄟ^日志配置文件控制異常堆棧輸出的深度
去組件框架:極致優(yōu)化要求下,可以去掉一些組件框架,比如去掉傳統(tǒng)的 MVC 框架,直接使用 Servlet 處理請求。這樣可以繞過一大堆復雜且用處不大的處理邏輯,節(jié)省毫秒級的時間,當然,需要合理評估你對框架的依賴程度
高可用
流量削峰
答題:答題目前已經(jīng)使用的非常普遍了,本質(zhì)是通過在入口層削減流量,從而讓系統(tǒng)更好地支撐瞬時峰值。MQ: 最為常見的削峰方案是使用消息隊列,通過把同步的直接調(diào)用轉(zhuǎn)換成異步的間接推送緩沖瞬時流量。過濾
Plan B: 為了保證系統(tǒng)的高可用,必須設計一個 Plan B 方案來進行兜底