商城性能優(yōu)化技術(shù)工作總結(jié)

大前提:主要針對商城促銷日搶購是10秒以內(nèi)完成20萬訂單的搶購。
為了這個目標(biāo),進行了如下兩個方面的優(yōu)化:
一 程序tps(每秒處理請求數(shù)),程序抗并發(fā)能力的優(yōu)化。
二 集群tps優(yōu)化,集群抗并發(fā)能力優(yōu)化。
先說單程序tps優(yōu)化:
影響單個程序tps的關(guān)鍵點如下:

  1. json的序列化與反序列化,非常消耗cpu,尤其是沒有用fastjson的時候,cpu彪的非常高。解決方案:減少序列化和反序列化操作,能緩存的盡量走緩存,盡量把要頻繁使用的序列化或者反序列化好的結(jié)果數(shù)據(jù)存到緩存中,減少序列化和反序列化的執(zhí)行次數(shù)。
  2. 緩存的使用技巧:
    不涉及到全局性的緩存數(shù)據(jù),都盡量使用本地緩存(谷歌的開發(fā)包提供了很優(yōu)秀的本地緩存功能)
    設(shè)計到全局性的緩存,比如統(tǒng)一的庫存,統(tǒng)一的售罄狀態(tài)等,可以使用redis等緩存方案。
    如果數(shù)據(jù)源在數(shù)據(jù)庫中,并且要求實時或者近似實時的查詢,其實也可以通過評估延遲時間來使用緩存。
    比如某些查詢操作需要實時去數(shù)據(jù)庫中查詢,如果有100臺web服務(wù)器會查數(shù)據(jù)庫,每臺的tps是5000的話,總tps也有50萬。
    數(shù)據(jù)庫是絕對扛不住的,即使做了讀寫分離。 而且這種實時查詢,再高并發(fā)下主從同步很可能都是分鐘級別的延遲。 對數(shù)據(jù)庫的持續(xù)壓力是非常大的。
    此時就可以做一個評估了,比如我們允許接收數(shù)據(jù)有1秒鐘的延遲,那么我們就可以請求來的時候,先從數(shù)據(jù)庫中查出數(shù)據(jù),然后存到本地緩存中,本地緩存是非常快的,使用時的時間消耗基本可以忽略不計。 那么 100臺機器 每秒只需要請求數(shù)據(jù)庫100次就可以了,比50萬節(jié)省了太多了。 另外如果想提升redis的性能,第一要有一個足夠高頻的單核cpu(因為redis主要是用單線程模式),外加足夠的內(nèi)存。 可以給redis部屬自帶的哨兵,讓redis有一定的容災(zāi)能力。
  3. 數(shù)據(jù)庫連接池的優(yōu)化
    在高并發(fā)場景下,數(shù)據(jù)庫是我們永遠的痛, 數(shù)據(jù)庫有幾個重要的稀缺資源,數(shù)據(jù)庫連接數(shù)(一般的mysql的數(shù)據(jù)庫實例,最好是2000左右的連接數(shù),如果連接數(shù)再提高,會影響數(shù)據(jù)庫的性能,但也不是絕對的,有些時候可以適當(dāng)?shù)臓奚B接數(shù)換取服務(wù)器端更高的并發(fā)處理能力來提升tps,這里就需要通過壓測找到那個性能最好的平衡點了)。 另外對于數(shù)據(jù)庫連接池的配置,一般我們會使用阿帕奇的開源工具dbcp,它可以設(shè)置三個數(shù)量 初始連接數(shù),最大連接數(shù),最小連接數(shù)。 建議把這3個設(shè)置成一樣的,這樣會減小高并發(fā)時連接池新增或銷毀鏈接帶來的開銷。 dbcp還有很多優(yōu)化的技巧,這里不再說了,大家可以百度一下。
  4. 我理解的一個完整的單機性能模型:
    當(dāng)一大批請求訪問到web容器(tomcat或者resion)時, web容器會有兩個隊列,第一個隊列是能夠得到資源執(zhí)行處理的隊列(可以通過調(diào)整web容器的線程數(shù)來調(diào)整隊列的大?。?,第二個隊列是排隊等待的隊列。 當(dāng)請求數(shù)比第一個隊列承受的并發(fā)高的時候,請求會進入到排隊中,當(dāng)排隊的隊列也滿了之后,請求會直接返回50x錯誤。 web容器還可以調(diào)整能夠處理的最大線程數(shù),再壓測的時候我們做過調(diào)整,1024,2048,8192. 再我們用恒定高并發(fā)壓的時候,如果cpu是瓶頸,那么調(diào)這個屬性幾乎對tps沒太多幫助。 【web容器內(nèi)部的模型純屬猜測,大家有興趣可以細細研究】 數(shù)據(jù)庫連接數(shù)設(shè)置多少最合適呢,其實就是能夠與服務(wù)所需要的連接數(shù)匹配。 什么是匹配呢,就是沒有線程因為拿不到數(shù)據(jù)庫連接而進行等待。
  5. 性能分析的工具:jprofiler
    它可以分析cpu的高消耗位置,線程等待的位置,內(nèi)存泄露的位置等。 我們主要優(yōu)化的其實就是這些點, 不要讓線程消耗太多cpu,不要讓線程因為稀缺資源而等待(用緩存替代數(shù)據(jù)庫就是干這個的),不要有內(nèi)存溢出。
    (友情提示,這個軟件非常消耗cpu,大概自己就能吃60%的cpu,開啟的時候請讓并發(fā)數(shù)小一點,50左右就夠了)
  6. 網(wǎng)絡(luò)資源:
    當(dāng)我們單機的tps達到5000+的時候,其實我們消耗的網(wǎng)絡(luò)帶寬是非常大的,那么此時啟動服務(wù)器端的Gzip就非常有用了,它會多消耗一些cpu資源,但是會節(jié)省很多網(wǎng)絡(luò)帶寬。 我們最終可以根據(jù)我們手頭的硬件資源來評估,到底是要cpu還是要帶寬。
  7. 分庫分表:
    分表要解決的問題是mysql單表存儲數(shù)據(jù)最大量的問題,當(dāng)單表數(shù)據(jù)量過大(超過1000萬)時,對表操作時性能會開始下降。 分庫要解決的時硬件性能的問題。 分表的方法更多的需要借助中間鍵,或者代碼中有一些邏輯。 分庫則可以通過部屬的方式簡單實現(xiàn)。 比如同一套代碼, 部屬的時候可以 部屬十組,每組服務(wù)器上綁定不同的host去連不同的數(shù)據(jù)庫。 然后再web服務(wù)器之上用nginx來基于某個值做哈希讓請求總能打到唯一的一組服務(wù)器上。 這種方式運維的壓力會大,但程序之需要一套代碼。
  8. 硬件上需要監(jiān)控的參數(shù):
    包量(主要用于計算網(wǎng)卡是否跑滿),連接數(shù)(結(jié)合服務(wù)器端口數(shù)來計算是否占滿),各個單體之間的連接是長連接還是短連接。影響集群tps1 在集群環(huán)境下,由于resion的海量增加,很多其他節(jié)點都可能成為瓶頸, 比如lvs,nginx,網(wǎng)卡,redis,數(shù)據(jù)庫等。lvs 和 nginx 出現(xiàn)瓶頸后,也是從cpu,網(wǎng)卡,連接數(shù),包量,流量等方向查起。 redis出問題主要看內(nèi)存是否達到瓶頸, cpu是否達到瓶頸。 redis是很需要一個強勁的cpu的,我們使用的都是單線程模式的redis,比較穩(wěn)定。數(shù)據(jù)庫瓶頸:一般數(shù)據(jù)庫瓶頸有幾個, 連接數(shù)資源(一般2000左右最好,超過了就開始有性能損失,達到4000就對數(shù)據(jù)庫操作有非常大的影響了)
    2.2. 分流:把流量轉(zhuǎn)移,比如把靜態(tài)內(nèi)容發(fā)布到cdn中,來分擔(dān)服務(wù)器端的壓力。 把同一個resion中的服務(wù)拆分到其他resion中,分開部署,使用獨立的數(shù)據(jù)庫資源等。
    3.3. 限流:直接對流量進行限制,比如再nginx中可以設(shè)置基于ip或者location的限流,訪問頻次控制等,比如一分鐘,某個url下的某個參數(shù)(一般是user_id)能訪問服務(wù)幾次。
    4.4. 降級:直接把服務(wù)中不重要的功能去掉,或者直接去掉不重要的服務(wù)。系統(tǒng)處于可運行狀態(tài),但是邊緣功能暫時不展示或無法使用。 以保證主交易流程的暢通無阻。
    5.5. 容災(zāi):對于核心系統(tǒng)來說,容災(zāi)是一個很重要的話題。 首先部署層面同一個服務(wù)不能全部部署在同一個宿主機的虛機上,同業(yè)務(wù)的宿主機不能再機房再同一個機柜中,同一套服務(wù)不能只在一個機房中。 機房間要有快速切換的方案,服務(wù)切換時要有有數(shù)據(jù)同步的機制,保證數(shù)據(jù)的有效容災(zāi)。
    --------------------------運維視角看性能-------------------------
一 cpu篇

通過監(jiān)控能夠看到cpu的各項指標(biāo),比較重要的有 cpu idel(cpu空閑), 100%-cpuidle=cpu使用量。 cpu io wait: cpu等待磁盤io所消耗的百分比,這個值如果高就說明磁盤可能有問題了。 這個可以和磁盤的swap交換量結(jié)合起來一起看。( 命令:free -m 看swap交換) cpu user:程序使用的cpu

二 監(jiān)控的load性能圖標(biāo)。

load這個值是用cpu,磁盤,內(nèi)存等一起計算出來的一個值。
一般load數(shù)值cpu核數(shù)3>12 就說明性能已經(jīng)不行了。

三 內(nèi)存

內(nèi)存主要就是通過swap置換量來分析,如果成百上千的swap置換,就說明內(nèi)存已經(jīng)不足,開始大量使用磁盤代替內(nèi)存,此時往往 cpu io wait 也會高很多。 (free -m)用來看swap置換量等。

四 網(wǎng)絡(luò)

time wait 等待的連接 close 關(guān)閉的連接 Estable 目前已經(jīng)建立的鏈接 y.. 半連接 如果time wait 比較多,可以考慮把短連接改成長連接,當(dāng)然也是基于具體場景的。 (命令:ss -s 看連接數(shù), ss -an 看其他的)

五 網(wǎng)卡

消耗網(wǎng)卡的主要是兩個東西,1 流量 2 包量 流量消耗的是網(wǎng)卡的吞吐亮,比如千兆網(wǎng)卡, 流量上限就是1G。 包量消耗的時網(wǎng)卡的性能,一般一臺虛機 10萬左右的包量基本就是極限了,再多久可能有丟包。 可以用 w -get命令 來實驗是否丟包。 可以通過給網(wǎng)卡做bading, 把多個網(wǎng)卡綁在一起來提高網(wǎng)卡性能。 理論可以綁定無限多個,目前我們是2個或者4個綁定在一起。

六 磁盤

一般磁盤的性能瓶頸是看磁盤的iops (一秒多少次磁盤讀寫) 磁盤的io wait比較高的時候,就是磁盤有瓶頸的時候。 一般此時,cpu io wait 也會高。

七 端口數(shù)

我們的七層代理(nginx) 一個ip可以有65535個端口。 這個量很可能不夠。 解決的辦法是nginx做多ip回源,比如nginx用多個ip吧請求upstream到下面的resion,這樣就解決了端口數(shù)不夠的問題。 也可以增加nginx的數(shù)量。 (命令 ss -s 可以看有多少端口數(shù))

八 主機虛擬化

一個性能好的主機可以虛擬出很多的虛擬機,一般虛擬化之后,總體的性能損耗是20%-30%左右,但是帶來的好處是可以做隔離,帶來更多端口數(shù),減少硬件資源浪費。 虛擬化之后其實網(wǎng)卡也被虛擬化了,所以虛擬化之后的主機對于包量的處理能力會低,一般10萬左右的包量就基本到上限了。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 在服務(wù)器端程序開發(fā)領(lǐng)域,性能問題一直是備受關(guān)注的重點。業(yè)界有大量的框架、組件、類庫都是以性能為賣點而廣為人知。然而...
    零一間閱讀 951評論 0 12
  • 在服務(wù)器端程序開發(fā)領(lǐng)域,性能問題一直是備受關(guān)注的重點。業(yè)界有大量的框架、組件、類庫都是以性能為賣點而廣為人知。然而...
    dreamer_lk閱讀 1,108評論 0 17
  • 前端優(yōu)化 并發(fā)策略 緩存優(yōu)化 數(shù)據(jù)庫優(yōu)化 如何構(gòu)建一個高性能的Web應(yīng)用, 其實是一個很大的話題。之前在公司內(nèi)部對...
    曲水流觴TechRill閱讀 953評論 0 14
  • 1.1 資料 ,最好的入門小冊子,可以先于一切文檔之前看,免費。 作者Antirez的博客,Antirez維護的R...
    JefferyLcm閱讀 17,323評論 1 51
  • 最近聽了羅胖的一篇文章《學(xué)校的作用》。話說傳統(tǒng)的學(xué)校在人類歷史上存在已幾千年,面對近些年社會媒體對學(xué)校教育的種種詬...
    堅持成長閱讀 392評論 0 0

友情鏈接更多精彩內(nèi)容