高性能高并發(fā)系統(tǒng)的穩(wěn)定性保障
作者:肖飛,于2011年8月份加入京東,曾親身參與到京東的應(yīng)用性能監(jiān)控、統(tǒng)一日志、流式計(jì)算、內(nèi)存緩存、四層防攻擊等一些基礎(chǔ)技術(shù)平臺(tái)的研發(fā)和搭建工作,經(jīng)歷了京東的技術(shù)系統(tǒng)從簡單粗放向復(fù)雜精細(xì)化的演變過程。目前主要工作為多中心交易項(xiàng)目中的數(shù)據(jù)復(fù)制中間件JingoBUS的研發(fā)。平時(shí)也會(huì)開發(fā)一些公共的平臺(tái)和工具,關(guān)注分布式系統(tǒng)的實(shí)現(xiàn)、程序設(shè)計(jì)、性能優(yōu)化、開發(fā)語言等。
本文是2015年肖飛在內(nèi)部分享的《高性能高并發(fā)系統(tǒng)的穩(wěn)定性保障》PPT內(nèi)容。
性能、并發(fā)、穩(wěn)定性三者關(guān)系
- 高性能:高吞吐量、低延時(shí)
- 公式:吞吐量(并發(fā))=單位時(shí)間/平均延時(shí)
- N-th% Latency:TP99, TP999
- 穩(wěn)定性:低延時(shí)的穩(wěn)定性標(biāo)準(zhǔn)為TP99/TP999是隱含的必要條件;系統(tǒng)的穩(wěn)定性標(biāo)準(zhǔn):高+可用;用戶標(biāo)準(zhǔn)
吞吐量:QPS, TPS,OPS等等,并發(fā)。并不是越高越好,需要考慮TP99。用戶角度:系統(tǒng)是個(gè)黑盒,復(fù)雜系統(tǒng)中的任何一環(huán)到會(huì)導(dǎo)致穩(wěn)定性問題。SLA:在某種吞吐量下能提供TP99為n毫秒的服務(wù)能力。降低延時(shí),會(huì)提高吞吐量,但是延時(shí)的考核是TP99這樣的穩(wěn)定的延時(shí)。
如何改善延時(shí)
你應(yīng)該知道如下表格
原文:http://www.eecs.berkeley.edu/~rcs/research/interactive_latency.html
- JeffDean
- Disk random read IOPS:
- IOPS = 1000 / (4 + 60000/7200/2) = 122
- IOPS = 1000 / (4 + 60000/10000/2) = 142
- IOPS = 1000 / (4 + 60000/15000/2) = 166
- SSD random read IOPS:
- IOPS = 1000000/16=62500
數(shù)字的啟示
- 高速緩存的威力;
- 線程切換代價(jià)cache miss
- 順序?qū)憙?yōu)于隨機(jī)寫
- 局域網(wǎng)絡(luò)快于本地HDD
- 大塊讀優(yōu)于小塊讀
- SSD解決隨機(jī)讀寫
- 跨地域IDC網(wǎng)絡(luò)是最大的延時(shí)
策略
- 關(guān)鍵路徑:“28原則”(20%的代碼影響了80%的性能問題,抓重點(diǎn))、“過早優(yōu)化是萬惡之源”。不同解讀;
- 優(yōu)化代碼:空間換時(shí)間:各級(jí)緩存;時(shí)間換空間:比如傳輸壓縮,解決網(wǎng)絡(luò)傳輸?shù)钠款i;多核并行:減少鎖競爭;lesscode;各類語言、框架、庫的trick;算法+數(shù)據(jù)結(jié)構(gòu),保持代碼的清晰、可讀、可維護(hù)和擴(kuò)展;
- 通過性能測試和監(jiān)控找出瓶頸
metric
原文:http://www.vpsee.com/2014/09/linux-performance-tools/
通過性能測試和監(jiān)控:
- 單系統(tǒng)operf/jprofiler etc;
- Java的一系列工具:jstat, jstack, jmap, jvisualvm,HeapAnalyzer, mat
- 分布式跟蹤系統(tǒng):Dapper,鷹眼等
benchmark
原文:http://www.vpsee.com/2014/09/linux-performance-tools/
微觀
- 內(nèi)存分配
吞吐量和利用率的權(quán)衡
顯式分配器:jemalloc/tcmalloc代替默認(rèn)的ptmalloc
隱式分配器:JVM GC的各種調(diào)優(yōu)
是否使用hugepagen預(yù)分配和重用:Netty的Pooled ByteBuf
減少拷貝:new ArrayList(int), new StringBuilder(int)
內(nèi)存分配器利用率:減少內(nèi)部或外部碎片;Page Table(頁表), TLB(頁表寄存器緩沖),減少TLB miss,pin cache。增加COW的開銷, 與內(nèi)存分配器的實(shí)現(xiàn)沖突。JVM的GC調(diào)優(yōu)是很多Java應(yīng)用的關(guān)注重點(diǎn)。
- 減少系統(tǒng)調(diào)用
批處理: buffer io,pipeline
使用用戶態(tài)的等價(jià)函數(shù): gettimeofday ->clock_gettime
減少鎖競爭
RWMutex
CAS
Thread local
最小化鎖范圍
最小化狀態(tài),不變類
批處理增加了內(nèi)存拷貝的開銷,但是減少了系統(tǒng)調(diào)用開銷,減少了上下文切換的影響。bufferio的例子:日志、網(wǎng)絡(luò)讀寫。pipeline的例子:redis。
- 減少上下文切換
觸發(fā):中斷、系統(tǒng)調(diào)用、時(shí)間片耗盡、IO阻塞等
危害:L1/L2 Cache Missing,上下文保存/恢復(fù)
單線程:基于狀態(tài)機(jī)redis和Master/Worker的nginx
CPU親和性綁定
ThreadPool的配置,不同任務(wù)類型不同的ThreadPool
幾個(gè)例子:1、docker中線程池大小的核數(shù)自動(dòng)設(shè)定;2、CPU節(jié)能模式;3、CENTOS-7.1內(nèi)核BUG。
- 網(wǎng)絡(luò)
內(nèi)核TCP Tuning參數(shù)和SocketOption:net.ipv4.tcp_*
TCP Socket連接池
網(wǎng)絡(luò)I/O模型
傳輸壓縮
編解碼效率
超時(shí)、心跳和重試機(jī)制
網(wǎng)卡:多隊(duì)列中斷CPU綁定;增加帶寬:萬兆、Bonding;Offload特性:ethtool -k eth0;UIO Driver: DPDK
連接池:減少握手、減少服務(wù)端session創(chuàng)建消耗。網(wǎng)絡(luò)I/O模型:BIO、Non-Blocking IO、AIO;select/poll、epoll/kqueue、aio;netty使用nativetransport。Offload特性:ethtool-k eth0。 將數(shù)據(jù)包分組、重組、chksum等從內(nèi)核層放到硬件層做。
如何提高吞吐量
改善和降低單機(jī)的延時(shí),一般就能提高我們的吞吐量。從集群化上講,因素就比較多。
宏觀
- 提升系統(tǒng)擴(kuò)展能力
- 應(yīng)用的無狀態(tài)架構(gòu)
- 緩存/存儲(chǔ)的集群架構(gòu):冗余復(fù)制(負(fù)載均衡、異構(gòu)解除系統(tǒng)依賴);分布式(數(shù)據(jù)sharding , 副本,路由,數(shù)據(jù)一致性);切換
- 微服務(wù)/SOA
- 擴(kuò)容
- 異步化
- 緩存
復(fù)制
- 通過復(fù)制提高讀吞吐量、容災(zāi)、異構(gòu)
- 通過數(shù)據(jù)分片,提高寫吞吐量
- 程序雙寫:一致性難以控制,邏輯復(fù)雜,冪等性要求。完全把控復(fù)制和切換時(shí)機(jī)。異構(gòu)系統(tǒng)唯一選擇。 同步雙寫(數(shù)據(jù)一致性高,影響性能,不適合多個(gè)復(fù)制集); 異步雙寫(數(shù)據(jù)一致性差,性能高,適合多個(gè)復(fù)制集);CDC[Change Data Capture](canal,databus等)
- 底層存儲(chǔ)復(fù)制機(jī)制:一致性由底層控制,對應(yīng)用端透明。程序和底層存儲(chǔ)配合切換
擴(kuò)容
- 每年大促前的核心工作:該擴(kuò)容了嗎?現(xiàn)狀分析;擴(kuò)容規(guī)劃(關(guān)鍵系統(tǒng)峰值20倍吞吐量);擴(kuò)容依據(jù)(架構(gòu)梳理、線上壓測);
- 擴(kuò)容checklist:前(部署、DB授權(quán)....);后(配置更新、LB更新、接入日志、接入監(jiān)控....)
- 應(yīng)用擴(kuò)容、數(shù)據(jù)擴(kuò)容、寫擴(kuò)容、讀擴(kuò)容
- 垂直擴(kuò)容:加內(nèi)存、升級(jí)SSD、更換硬件。數(shù)據(jù)復(fù)制、切換
- 水平擴(kuò)容:數(shù)據(jù)遷移或初始化
現(xiàn)狀分析:去年雙十一到目前,峰值時(shí)的性能數(shù)據(jù);軟硬件性能指標(biāo);數(shù)據(jù)存儲(chǔ)容量。
擴(kuò)容規(guī)劃;流量規(guī)劃:核心系統(tǒng)20倍吞吐量;數(shù)據(jù)增長量規(guī)劃;擴(kuò)容依據(jù);架構(gòu)梳理;線上壓測。
讀擴(kuò)容比寫擴(kuò)容難;讀寫分離。
異步化
- 解耦利器
- 削峰填谷
- 頁面異步化
- 系統(tǒng)異步化
- JMQ
- 狀態(tài)機(jī)(worker)+DB
- 本地隊(duì)列
- 集中式緩存隊(duì)列
本地內(nèi)存隊(duì)列:實(shí)時(shí)價(jià)格回源服務(wù)響應(yīng)之后,通過BlockingQueue異步更新前端緩存。本地日志隊(duì)列:庫存預(yù)占。集中式緩存隊(duì)列:商品變更任務(wù)下發(fā)系統(tǒng)。
異步化的一些例子:
1、操作系統(tǒng)內(nèi)核的高速緩存隊(duì)列,磁盤延遲刷盤;
2、mysql數(shù)據(jù)庫復(fù)制、redis復(fù)制;
異步化需要注意的是:
1、任務(wù)要落地;
2、不可避免的重復(fù)執(zhí)行,需要冪等;
3、是否需要保證順序、如何保證順序。
緩存
- 久經(jīng)考驗(yàn)的局部性原理
- 多級(jí)緩存:瀏覽器browser cache、cdn、nginx本地redis緩存、本地JVM緩存、集中式緩存...
- 緩存前置:2/8原則、單品頁、實(shí)時(shí)價(jià)格、庫存狀態(tài)
- 一致性、延遲權(quán)衡
- 緩存主節(jié)點(diǎn)負(fù)責(zé)寫,和最重要的校驗(yàn)
- 通過CDC監(jiān)聽數(shù)據(jù)庫binlog主動(dòng)更新緩存
- CPU不是瓶頸,網(wǎng)絡(luò)才是
- 優(yōu)化編碼,減少尺寸
- 優(yōu)化操作
- 優(yōu)化拓?fù)?/li>
如何保障穩(wěn)定性
宏觀
- 提高可用性
- 分組和隔離
- 限流
- 降級(jí)
- 監(jiān)控和故障切換
可用性
- 可用性衡量指標(biāo):幾個(gè)9
- 可用性度量:A = MTBF / (MTBF + MTTR)
- 減少故障、加長可用時(shí)間
- 減少故障修復(fù)時(shí)間(發(fā)現(xiàn)、定位、解決)
- 冗余復(fù)制、災(zāi)備切換,高可用的不二法門
- 如何快速切換?
- 切換的影響
- 監(jiān)控、ThoubleShooting、軟件質(zhì)量的影響
可行性指標(biāo):999,一周10分鐘;9999,一周1分鐘不可用??捎眯裕簭目蛻艚嵌取?捎眯远攘浚篈 = MTBF / (MTBF + MTTR) ,其中MTBF表示mean time betweenfailures,而MTTR表示maximum time to repair or resolve。
高可用行性的成本和收益,好鋼用在刀刃上。
如何快速切換:有可以切換的?可以不重啟應(yīng)用么? 操作快捷么?演練過么?
切換的影響:切換目標(biāo)資源能否承受新增的壓力;切換是否影響狀態(tài)(數(shù)據(jù)的一致性、丟失問題)。
監(jiān)控到位、即時(shí),減少故障發(fā)現(xiàn)時(shí)間;監(jiān)控全面,增加故障分析時(shí)可以參考的數(shù)據(jù)。
troubleshooting的能力,踩坑的精力, COE,問題本質(zhì)、根源的追查。
軟件質(zhì)量:編碼是否健壯、(異常處理、防御性、2/8原則)超時(shí)處理、日志是否全面合理、線程名稱等等。
測試:case是否全面、自動(dòng)回歸。
上線:是否灰度:N+1, N+2;回滾方案、數(shù)據(jù)回滾。
分組和隔離
- 網(wǎng)絡(luò)流量隔離:大數(shù)據(jù)單獨(dú)部署,QOS;
- 業(yè)務(wù)系統(tǒng)隔離:秒殺系統(tǒng)獨(dú)立出主交易;
- 流量分組:對使用者按照重要程度、請求量、SLA要求等因素分級(jí)
- 存儲(chǔ)的分組:按照使用者重要程度、實(shí)時(shí)性要求等因素,將數(shù)據(jù)庫的復(fù)制集分組
傳統(tǒng)世界的例子:道路被劃分為高速道路、自行道、人行道等,各行其道。
流量分組
舉例:商品基礎(chǔ)信息讀服務(wù)。對使用者按照重要程度、請求量、SLA要求等因素分級(jí),將服務(wù)實(shí)例和存儲(chǔ)分組:交易、生產(chǎn)、網(wǎng)站、移動(dòng)、promise、ERP...
讀寫分離
舉例:商品主數(shù)據(jù)服務(wù)。按照使用者重要程度、實(shí)時(shí)性要求等因素,將數(shù)據(jù)庫分組:ERP、POP、網(wǎng)站、大數(shù)據(jù)平臺(tái)...
限流
- 限流原則:影響到用戶體驗(yàn),謹(jǐn)慎使用
- 區(qū)分正常流量和超預(yù)期流量:限流標(biāo)準(zhǔn)來自壓力測試、折算
- 讀少限,寫多限
- 客戶端配合限流
- 不同分組的限流閾值
- 各層限流手段
前置限流,快速失?。罕热缤ㄟ^提供給調(diào)用方的JSF客戶端,封裝限流邏輯。
Nginx層限流:自主研發(fā)的模塊;幾個(gè)規(guī)則:賬戶,IP,系統(tǒng)調(diào)用流程。
應(yīng)用限流:減少并發(fā)數(shù)線程數(shù);讀少限,寫多限;DB限流;連接數(shù)。
降級(jí)
保證用戶的核心需求
降級(jí)需要有預(yù)案和開關(guān):確定系統(tǒng)和功能級(jí)別,是否可降,影響如何;降級(jí)需要有開關(guān)
非關(guān)鍵業(yè)務(wù)屏蔽:購物車的庫存狀態(tài)
業(yè)務(wù)功能模塊降級(jí):實(shí)時(shí)價(jià)格更新不及時(shí);peking庫,保訂單管道、生產(chǎn),暫停統(tǒng)計(jì)相關(guān)
數(shù)據(jù)降級(jí):動(dòng)態(tài)降級(jí)到靜態(tài);遠(yuǎn)程服務(wù)降級(jí)到本地緩存:采銷崗服務(wù)
監(jiān)控和切換
無所不在的監(jiān)控:網(wǎng)絡(luò)流量;操作系統(tǒng)指標(biāo);服務(wù)接口調(diào)用量、TP99、錯(cuò)誤率...;日志;業(yè)務(wù)量變化;太多監(jiān)控了,如何提高監(jiān)控的質(zhì)量
切換:切換開關(guān);成熟的流程可自動(dòng)化;數(shù)據(jù)的重要性、一致性,要求強(qiáng)一致的,可以人工介入;系統(tǒng)的指標(biāo)沒法判斷、監(jiān)控點(diǎn)不全的,需人工判斷決定
review
Nginx層限流:自主研發(fā)的模塊;幾個(gè)規(guī)則:賬戶,IP,系統(tǒng)調(diào)用流程。
應(yīng)用限流:減少并發(fā)數(shù)線程數(shù);讀少限,寫多限;DB限流;連接數(shù)。
如何驗(yàn)證性能和穩(wěn)定性
- 線上壓測:兩類壓力測試場景(讀業(yè)務(wù)壓測、寫業(yè)務(wù)壓測);壓力測試方案(從集群中縮減服務(wù)器、復(fù)制流量、模擬流量、憋單)
- 全流程演練:降級(jí)、切換等
讀業(yè)務(wù)壓力測試:是將線上業(yè)務(wù)隔離后,壓測至系統(tǒng)臨界點(diǎn),通過分析系統(tǒng)在臨界點(diǎn)時(shí)軟硬件指標(biāo)定位系統(tǒng)短板并優(yōu)化。
寫邏輯壓力測試,如果數(shù)據(jù)具有不可恢復(fù)性,一定要提前做好數(shù)據(jù)隔離保護(hù),如訂單號(hào)壓測,為避免影響線上業(yè)務(wù),壓測前后都要做好“跳號(hào)”以隔離線上數(shù)據(jù)。
從集群中縮減服務(wù)器。加大單臺(tái)服務(wù)器的壓力。大概估算出正常的集群規(guī)模能夠承載的流量。
復(fù)制流量。主要通過 Tcpcopy 復(fù)制端口流量,多層翻倍放大流。
模擬流量。模擬流量主要腳本攻擊工具和壓測工具結(jié)合,主要用ab,siege,webbench,loadruner通過多臺(tái)機(jī)器壓測。分機(jī)房,按分支進(jìn)行壓測。
憋單。主要針對后續(xù)的訂單生產(chǎn)系統(tǒng)壓測。通過在管道積壓一批訂單,然后快速釋放,形成對后續(xù)生產(chǎn)系統(tǒng)持續(xù)快速的沖擊,達(dá)到壓測的目的。
【本文來自51CTO專欄作者張開濤的微信公眾號(hào)(開濤的博客),公眾號(hào)id: kaitao-1234567】