高併發解決方案

1. 高併發和大流量解決方案

高併發架構相關概念
  併發:在操做系統中,是指一個時間段中有幾個程序都處於已啓動運行到運行完畢之間,且這幾個程序都是在同一個處理機上運行,但任一個時刻點上只有一個程序在處理機上運行;在互聯網時代,所講的併發,高併發一般是指併發訪問,也就是在某個時間點,有多少個訪問同時到來。一般一個系統的日PV在千萬以上,有多是一個高併發的系統。有的公司徹底不走技術路線,全靠機器堆,這不在討論範圍內。
  QPS:每秒鐘請求或者查詢的數量,在互聯網領域,指每秒響應請求數(指HTTP請求);併發鏈接數是系統同時處理的請求數量
  吞吐量:單位時間內處理的請求數量(一般由QPS與併發數決定)
  響應時間:從請求發出到收到響應花費的時間。例如系統處理一個HTTP請求須要100ms。
  PV:綜合瀏覽量(page view),即頁面瀏覽量或者點擊量,一個訪客在24小時內訪問的頁面數量;同一我的瀏覽網站同一頁面,只記做一次PV
  UV:獨立訪客(unique visitor),即必定時間範圍內相同訪客屢次訪問網站,只計算爲一個獨立訪客
  帶寬:計算帶寬大小需關注兩個指標,峯值流量和頁面的平均大小
  日網站帶寬=PV/統計時間(換算到s)*平均頁面大小(單位KB)*8;峯值通常是平均值的倍數,根據實際狀況來定
  峯值每秒請求數(QPS)=(總PV數*80%)/(6小時秒數*20%);80%的訪問量集中在20%的時間
  壓力測試:測試能承受的最大併發,測試最大承受的QPS值
  經常使用性能測試工具:ab,wrk,http_load,web_bench,siege,apache jmeter;ab全稱是apache benchmark,apache官方推出的工具,建立多個併發訪問線程,模擬多個訪問者同時對某一trl地址進行訪問,它的測試目標是基於url的,所以既能夠用來測試apache的負載能力,也能夠測試nginx,lighthttp,tomcat,IIS等其它web服務器的壓力;ab的使用:模擬併發請求100次,總共請求5000次,ab -c 100 -n 5000 待測試網站;測試機器與被測試機器分開,不要對線上服務作壓力測試,觀察測試工具ab所在機器,以及被測試的前端機的CPU,內存,網絡等都不超過最高限度的75%
  QPS達到極限:隨着QPS的增加,每一個階段須要根據實際狀況來進行優化,優化的方案也與硬件條件、網絡帶寬息息相關;QPS達到50,能夠稱之爲小型網站,通常的服務器就能夠應付;QPS達到100,假設關係型數據庫的每次請求在0.01s完成,假設單頁面只有一個SQL查詢,那麼100QPS意味着1s完成100次請求,可是此時並不能保證數據庫查詢能完成100次,數據庫緩存層,數據庫的負載均衡;QPS達到800,假設使用百兆帶寬,意味着網站出口的實際帶寬是8M左右,假設每一個頁面只有10k,在這個併發條件下,百兆帶寬已經吃完,CDN加速,負載均衡;QPS達到1000,假設使用memcache緩存數據庫查詢數據,每一個頁面對memcache的請求遠大於直接對db的請求,memcache的悲觀併發數在2w左右,但有可能在以前內網帶寬已經吃光,表現出不穩定,靜態HTML緩存;QPS達到2000,這個級別下,文件系統訪問鎖都成爲了災難,作業務分離,分佈式存儲php

高併發解決方案案例
  流量優化:防盜鏈處理
  前端優化:減小HTTP請求,合併css或js,添加異步請求,啓用瀏覽器緩存和文件壓縮,CDN加速,創建獨立圖片服務器,
  服務端優化:頁面靜態化,併發處理,隊列處理
  數據庫優化:數據庫緩存,分庫分表,分區操做,讀寫分離,負載均衡
  web服務器優化:負載均衡,nginx反向代理,7,4層LVS軟件css

2. web資源防盜鏈

  盜鏈:在本身的頁面上展現一些並不在本身服務器上的內容,得到他人服務器上的資源地址,繞過別人的資源展現頁面,直接在本身的頁面上向最終用戶提供此內容,常見的是小站盜用大站的圖片,音樂,視頻,軟件等資源,經過盜鏈的方法能夠減輕本身服務器的負擔,由於真實的空間和流量均是來自別人的服務器html

  防盜鏈:防止別人經過一些技術手段繞過本站的資源展現頁面,盜用本站的資源,讓繞開本站資源展現頁面的資源連接失效,能夠大大減輕服務器及帶寬的壓力前端

  工做原理:經過請求頭中的referer或者簽名,網站能夠檢測目標網頁訪問的來源網頁,若是是資源文件,則能夠跟蹤到顯示它的網頁地址,一旦檢測到來源不是本站即進行阻止或者返回制定的頁面,經過計算簽名的方式,判斷請求是否合法,若是合法則顯示,不然返回錯誤信息node

  實現方法:referer:nginx模塊ngx_http_referer_module用於阻擋來源非法的域名請求,nginx指令valid_referers none | blocked | server_names | string...,none表示referer來源頭部爲空的狀況,blocked表示referer來源頭部不爲空,可是裏面的值被代理或者防火牆刪除了,這些值都不以http://或者https://開頭,server_names表示referer來源頭部包含當前的server_names,全局變量$invalid_referer。不能完全防範,只能提升門檻。也能夠針對目錄進行防盜鏈。mysql

//在nginx的conf中配置
location ~.*\.(gif|jpg|png|flv|swf|rar|zip)$ { valid_referers none blocked zi.com *.zi.com; if($invalid_referer) { #return 403; rewrite ^/ http://www.zi.com/403.jpg; } }

  傳統防盜鏈遇到的問題:僞造referer:可使用加密簽名解決nginx

  加密簽名:使用第三方模塊HttpAccessKeyModule實現Nginx防盜鏈。accesskey on|off 模塊開關,accesskey_hashmethod md5|sha-1 簽名加密方式,accesskey_arg GET參數名稱,accesskey_signature 加密規則,在nginx的conf中設置web

location ~.*\.(gif|jpg|png|flv|swf|rar|zip)$
{
    accesskey on;
    accesskey_hashmethod md5;
    accesskey_arg sign;
    accesskey_signature "jason$remote_addr";
}


<?php
$sign = md5('jason'.$SERVER['REMOTE_ADDR']);
echo '<img src=".logo.png?sign='.$sign.'">';

3. 減小HTTP請求次數

  性能黃金法則:只有10%-20%的最終用戶響應時間花在接收請求的HTML文檔上,剩下的80%-90%時間花在HTML文檔所引用的全部組件(img,script,css,flash等)進行的HTTP請求上。redis

  如何改善:改善響應時間的最簡單途徑就是減小組件的數量,並由此減小HTTP請求的數量算法

  HTTP鏈接產生的開銷:域名解析--TCP鏈接--發送請求--等待--下載資源--解析時間

  疑問:DNS緩存,查找DNS緩存也須要時間,多個緩存就要查找屢次有可能緩存會被清除;Keep-Alive,HTTP1.1協議規定請求只能串行發送,前面的一個請求完成才能開始下個請求

  減小HTTP請求的方式:圖片地圖:容許在一個圖片上關聯多個URL,目標URL的選擇取決於用戶單擊了圖片上的哪一個位置,以位置信息定位超連接,把HTTP請求減小爲一個,能夠保證設計的完整性和功能的齊全性,使用map和area標籤;

<img usemap="#map" src="/map.gif?t=111">
<map name="map">
    <area shape="rect" coords="0,0,30,30" href=... title="">
    ...       
</map>

    CSS Sprites:CSS精靈,經過使用合併圖片,經過指定css的background-image和background-position來顯示元素。圖片地圖與css精靈的響應時間基本上相同,但比使用各自獨立圖片的方式要快50%以上

    合併腳本和樣式表:使用外部的js和css文件引用的方式,由於這要比直接寫在頁面中性能要更好一點;獨立的一個js比用多個js文件組成的頁面載入要快38%;把多個腳本合併爲一個腳本,把多個樣式表合併爲一個樣式表

    圖片使用base64編碼減小頁面請求數:採用base64的編碼方式將圖片直接嵌入到網頁中,而不是從外部載入

4. 瀏覽器緩存和數據壓縮優化

  HTTP緩存機制:若是請求成功會有三種狀況:200 from cache:直接從本地緩存中獲取相應,最快速,最省流量,由於根本沒有向服務器進行請求;304 not modified:協商緩存,瀏覽器在本地沒有命中的狀況下請求頭中發送必定的校驗數據到服務端,若是服務端數據沒有改變瀏覽器從本地緩存響應,返回304,快速,發送的數據不多,只返回一些基本的響應頭信息,數據量很小,不發送實際響應體;200 OK:以上兩種緩存所有失敗,服務器返回完整響應,沒有用到緩存,相對最慢。

  瀏覽器認爲本地緩存可使用,不會去請求服務端。相關header:pragma:HTTP1.0時代的遺留產物,該字段被設置爲no-cache時,會告知瀏覽器禁用本地緩存,即每次都向服務器發送請求;expires:HTTP1.0時代用來啓用本地緩存的字段,瀏覽器與服務器的時間沒法保持一致,若是時間差距大,就會影響緩存結果;cache-control:HTTP1.1針對expires時間不一致的解決方案,告知瀏覽器緩存過時的時間間隔而不是時刻,即便具體時間不一致,也不影響緩存的管理;能夠設置的值:no-store:禁止瀏覽器緩存響應;no-cache:不容許直接使用本地緩存,先發起請求和服務器協商;max-age=delta-seconds:告知瀏覽器該響應本地緩存有效的最長期限,以秒爲單位;優先級:pragma >cache-control > expires。當瀏覽器沒有命中本地緩存,如本地緩存過時或者響應中聲明不容許直接使用本地緩存,那麼瀏覽器確定會發起服務端請求;

  服務端會驗證數據是否修改,若是沒有通知瀏覽器使用本地緩存。相關header:last-modified:通知瀏覽器資源的最後修改時間;if-modified-since:獲得資源的最後修改時間後,會將這個信息經過它提交到服務器作檢查,若是沒有修改,返回304狀態碼;ETag:HTTP1.1推出,文件的指紋標識符,若是文件內容修改,指紋會改變;if-none-match:本地緩存失效,會攜帶此值去請求服務端,服務端判斷該資源是否改變,若是沒有改變,直接使用本地緩存,返回304

  緩存策略的選擇:適合緩存的內容:不變的圖像,如logo,圖標等,js,css靜態文件,可下載的內容,媒體文件;建議使用協商緩存:html文件,常常替換的圖片,常常修改的js,css文件,js和css文件的加載能夠加入文件的簽名來拒絕緩存,如a.css?簽名或a.簽名.js;不建議緩存的內容:用戶隱私等敏感數據,常常改變的api數據接口

  nginx配置緩存策略:
  本地緩存配置:add_header指令:添加狀態碼爲2xx和3xx的響應頭信息,add_header name value [always];,能夠設置Pragma/Expires/Cache-Control,能夠繼承;expires指令:通知瀏覽器過時時長,expires time;,爲負值時表示Cache-Control: no-cache;,當爲正或者0時,就表示Cache-Control: max-age=指定的時間;;當爲max時,Cache-Control設置到10年;
  協商緩存相關配置:Etag指令:指定簽名;etag on|off;,默認是on

  前端代碼和資源的壓縮:讓資源文件更小,加快文件在網絡中的傳輸,讓網頁更快的展示,下降帶寬和流量開銷;壓縮方式:js,css,圖片,html代碼的壓縮,Gzip壓縮。js代碼壓縮:通常是去掉多餘的空格和回車,替換長變量名,簡化一些代碼寫法等,代碼壓縮工具不少UglifyJS(壓縮,語法檢查,美化代碼,代碼縮減,轉化)、YUI Compressor(來自yahoo,只有壓縮功能)、Closure Compiler(來自google,功能和UglifyJS相似,壓縮的方式不同),有在線工具tool.css-js.com,應用程序,編輯器插件。css代碼壓縮:原理和js壓縮原理相似,一樣是去除空白符,註釋而且優化一些css語義規則等,壓縮工具CSS Compressor(能夠選擇模式)。html代碼壓縮:不建議使用代碼壓縮,有時會破壞代碼結構,可使用Gzip壓縮,固然也可使用htmlcompressor工具,不過轉換後必定要檢查代碼結構。img壓縮:通常圖片在web系統的比重都比較大,壓縮工具:tinypng,JpegMini,ImageOptim。Gzip壓縮:配置nginx服務,gzip on|off,gzip_buffers 32 4K|16 8K #緩衝(在內存中緩存幾塊?每塊多大),gzip_comp_level [1-9] #推薦6 壓縮級別(級別越高,壓的越小,越浪費CPU計算資源),gzip_disable #正則匹配UA 什麼樣的uri不進行gzip,gzip_min_length 200 #開始壓縮的最小長度,gzip_http_version 1.0|1.1 #開始壓縮的http協議版本,gzip_proxied #設置請求者代理服務器,該如何緩存內容,gzip_types text/plain applocation/xml #對哪些類型的文件用壓縮,gzip_vary on|off #是否傳輸gzip壓縮標誌。其餘工具:自動化構建工具Grunt。

5. CDN加速

  CDN:Content Delivery Network,內容分發網絡,儘量避開互聯網上有可能影響數據傳輸速度和穩定性的瓶頸和環節,使內容傳輸的更快更穩定;在網絡各處放置節點服務器所構成的在現有的互聯網基礎之上的一層智能虛擬網絡;CDN系統可以實時的根據網絡流量和各節點的鏈接,負載狀況以及到用戶的距離和響應時間等綜合信息將用戶的請求從新導向離用戶最近的服務節點上。本地cache加速,提升了企業站點(尤爲含有大量img和靜態頁面站點)的訪問速度;跨運營商的網絡加速,保證不一樣網絡的用戶都獲得良好的訪問質量;遠程訪問用戶根據DNS負載均衡技術智能自動選擇cache服務器;自動生成服務器的遠程Mirror cache服務器,遠程用戶訪問時從cache服務器上讀數據,減小遠程訪問的帶寬,分擔網絡流量,減輕原站點web服務器負載等功能;普遍分佈的CDN節點加上節點之間的只能智能冗餘機制,能夠有效的預防黑客入侵

  CDN的工做原理:傳統訪問:用戶在瀏覽器輸入域名發起請求--解析域名獲取服務器IP地址--根據IP地址找到對應的服務器--服務器響應並返回數據;使用CDN訪問:用戶發起請求--智能DNS的解析(根據IP判斷地理位置,接入網類型,選擇路由最短和負載最輕的服務器)--取得緩存服務器IP--把內容返回給用戶(若是緩存中有)--向源站發起請求--將結果返回給用戶--將結果存入緩存服務器

  CDN適用場景:站點或者應用中大量靜態資源的加速分發,如css,js,img和html;大文件下載;直播網站等

  CDN的實現:BAT等都有提供CDN服務,可用LVS作4層負載均衡;可用nginx,Varnish,Squid,Apache TrafficServer作7層負載均衡和cache;使用squid反向代理,或者nginx等的反向代理

6. 創建獨立的圖片服務器

  獨立的必要性:分擔web服務器的I/O負載-將耗費資源的圖片服務分離出來,提升服務器的性能和穩定性;可以專門的圖片服務器進行優化-爲圖片服務設置有針對性的緩存方案,減小帶寬成本,提升訪問速度;提升網站的可擴展性-經過增長圖片服務器,提升圖片吞吐能力

  採用獨立域名:緣由:同一域名下瀏覽器的併發鏈接數有限制,突破瀏覽器鏈接數的限制;因爲cookie的緣由,對緩存不利,大部分web cache都只緩存不帶cookie的請求,致使每次的圖片請求都不能命中cache

  獨立後的問題:如何進行圖片上傳和圖片同步:NFS共享方式;利用FTP同步

7. 動態語言靜態化

  將現有PHP等動態語言的邏輯代碼生成爲靜態HTML文件,用戶訪問動態腳本重定向到靜態HTML文件的過程。對實時性要求不高的頁面比較適合。緣由:動態腳本一般會作邏輯計算和數據查詢,訪問量越大,服務器壓力越大;訪問量大時可能會形成CPU負載太高,數據庫服務器壓力過大;靜態化能夠下降邏輯處理壓力,下降數據庫服務器查詢壓力

  靜態化的實現方式:
  使用模板引擎:可使用smarty的緩存機制生成靜態HTML緩存文件;$smarty->cache-dir = $ROOT."/cache";//緩存目錄,$smarty->caching=true;//是否開啓緩存,$smarty->cache_lifetime="3600";//緩存時間,$smarty->display(string template[, string cache_id[, string compile_id]]);,$smarty->clear_all_cache();//清除全部緩存,$smarty->clear_cache('a.html');//清除指定的緩存,$smarty->clear_cache('a.html', $art_id);//清除同一個模板下的指定緩存號的緩存
  利用ob系列的函數:ob_start():打開輸出控制緩衝,ob_ge_contents():返回輸出緩衝區內容,ob_clean():清空輸出緩衝區,ob_end_flush():沖刷出(送出)輸出緩衝區內容並關閉緩衝,能夠判斷文件的inode修改時間,判斷是否過時使用filectime函數

8. 動態語言層的併發處理

  進程:計算機中的程序關於某數據集合上的一次運行活動,是系統進行資源分配和調度的基本單位,是操做數據結構的基礎,是一個「執行中的程序」;進程的三態模型:多道程序系統中,進程在處理器上交替運行,狀態不斷的發生變化;運行:當一個進程在處理機上運行時,稱該進程處於運行狀態,處於此狀態的進程的數目小於等於處理器的數目,對於單處理機系統,處於運行狀態的進程只有一個,在沒有其餘進程能夠執行時(如全部進程都在阻塞狀態),一般會自動執行系統的空閒進程;就緒:當一個進程得到了除處理機之外的一切所需資源,一旦獲得處理機便可運行,則稱此進程處於就緒狀態,就緒進程能夠按多個優先級來劃分隊列,如當一個進程因爲時間片用完而進入就緒狀態時,排入低優先級隊列,當進程由I/O操做完成而進入就緒狀態時,排入高優先級隊列;阻塞:也稱爲等待或睡眠狀態,一個進程正在等待某一事件發生(如請求I/O而等待I/O完成等)而暫時中止運行,這時即便把處理機分配給進程也沒法運行;進程的五態模型:對於一個實際的系統,進程的狀態及其轉換更爲複雜,新建態:對應於進程剛剛被建立時沒有被提交的狀態,並等待系統完成建立進程的全部必要信息;活躍就緒/靜止就緒:進程在主存而且可被調度的狀態/指進程被對換到輔存時的就緒狀態,是不能被直接調度的狀態,只有當主存中沒有活躍就緒態進程,或者是掛起就緒態進程具備更高的優先級,系統將把掛起就緒態進程調回主存並轉換爲活躍就緒;運行,活躍阻塞/靜止阻塞:指進程已在主存,一旦等待的時間產生便進入活躍就緒狀態/進程對換到輔存時的阻塞狀態,一旦等待的事件產生便進入靜止就緒狀態;終止態:進程已結束運行,回收除進程控制塊以外的其餘資源,並讓其餘進程從進程控制塊中收集有關信息;因爲用戶的併發請求,爲每個請求都建立一個進程顯然是行不通的,從系統資源開銷方面或是響應用戶請求的效率方面來看,所以線程的概念被引進。

  線程:有時被稱爲輕量級進程,是程序執行流的最小單元。是進程中的一個實體,是被系統獨立調度和分派的基本單位,本身不擁有系統資源,只擁有一點在運行中必不可少的資源但它可與同屬一個進程的其它進程共享進程所擁有的所有資源。一個線程能夠建立和撤銷另外一個線程,同一進程中的多個線程之間能夠併發執行。線程是程序中一個單一的順序控制流程,進程內一個相對獨立的、可調度的執行單元,是系統獨立調度和分派CPU的基本單位指運行中的程序的調度單位。在單個程序中同時運行多個線程完成不一樣的工做成爲多線程。每個程序都至少有一個線程,若程序只有一個線程,那就是程序自己。線程的狀態:就緒:線程具有運行的全部條件,邏輯上能夠運行,在等待處理機;運行:線程佔有處理機正在運行;阻塞:線程在等待一個事件(如某個信號量),邏輯上不可執行。 

  協程:是一種用戶態的輕量級線程,調度徹底由用戶控制;協程擁有本身的寄存器上下文和棧;協程調度切換時,將寄存器上下文和棧保存到其餘地方,在切回來的時候,恢復先前保存的寄存器上下文和棧,直接操做棧則基本沒有內核切換的開銷,能夠不加鎖的訪問全局變量,因此上下文的切換很是快。

  進程和線程的區別:線程是進程內的一個執行單元,進程內至少有一個線程,共享進程的地址空間,而進程有本身獨立的地址空間;進程是資源分配和擁有的單元,同一個進程內的線程共享進程的資源;線程是處理器調度的基本單位,但進程不是;兩者都可併發執行;每一個獨立的線程有一個程序運行的入口,順序執行序列和程序的出口,可是線程不可以獨立執行,必須依存在應用程序中,由應用程序提供多個線程執行控制

  線程和協程的區別:一個線程能夠多個協程,一個進程也能夠單獨擁有多個協程;進程線程都是同步機制,而協程則是異步;協程能保留上一次調用時的狀態,每次過程重入時,就至關於進入上一次調用的狀態。 

  多進程:同一時間裏,同一個計算機系統中若是容許兩個或兩個以上的進程處於運行狀態;多開一個進程,多分配一份資源,進程間通信不方便;

  多線程:線程就是把一個進程分爲不少片,每一片均可以是一個獨立的流程,與多進程的區別是隻會使用一個進程的資源,線程間能夠直接通訊;

  同步阻塞:多進程:最先的服務器端程序都是經過多進程,多線程來解決併發I/O的問題;一個請求建立一個進程,而後子進程進入循環同步阻塞地與客戶端鏈接進行交互,收發處理數據;多線程:線程中能夠直接向某一個客戶端鏈接發送數據;步驟:建立一個socket,進入while循環,阻塞在進程accept操做上,等待客戶端鏈接進入,主進程在多進程模型下經過fork建立子進程,多線程模型下能夠建立子線程,子進程/線程建立成功後進入while循環,阻塞在recv調用上,等待客戶端向服務器發送數據,收到數據後服務器程序進行處理而後使用send向客戶端發送響應,當客戶端鏈接關閉時,子進程/線程退出並銷燬全部資源。主進程/線程會回收掉此子進程/線程;缺點:這種模型嚴重依賴進程的數量解決併發問題,啓動大量進程會帶來額外的進程調度消耗

  異步非阻塞:如今各類高併發異步IO的服務器程序都是基於epoll(無限數量鏈接,無需輪詢)實現的。IO複用異步非阻塞程序使用經典的Reactor模型,Reactor顧名思義就是反應堆的意思,它自己不處理任何數據收發,只是能夠監視一個socket句柄的事件變化。Reactor模型:Add:添加一個socket到Reactor,Set:修改socket對應的事件,如可讀可寫,Del:從Reactor中移除,Callback:事件發生後回調指定的函數。Nginx:多線程Reactor,swoole:多線程Reactor+多進程Worker

  PHP的swoole擴展:PHP的異步,並行,高性能網絡通訊引擎,使用純c語言編寫,提供了PHP語言的異步多線程服務器,異步TCP/UDP網絡客戶端,異步mysql,異步redis,數據庫鏈接池,asynctask,消息隊列,毫秒定時器,異步文件讀寫,異步DNS查詢;除了異步IO的支持以外,swoole爲PHP多進程的模式設計了多個併發數據結構和IPC通訊機制,能夠大大簡化多進程併發編程的工做;swoole2.0支持了相似Go語言的協程,可使用徹底同步的代碼實現異步程序

  消息隊列:用戶註冊後,須要發註冊郵件和註冊短信;串行方式:將註冊信息寫入數據庫成功後,發送註冊郵件,再發送註冊短信;並行方式:將註冊信息寫入數據庫成功後,發送註冊郵件的同時,發送註冊短信;消息隊列方式:將註冊信息寫入數據庫成功後,將成功信息寫入隊列,此時直接返回成功給用戶,寫入隊列的時間很是短,能夠忽略不計,而後異步發送郵件和短信。應用解耦:場景說明:用戶下單後,訂單系統須要通知庫存系統。假如庫存系統沒法訪問,則訂單減庫存將失敗,從而致使訂單失敗;訂單系統與庫存系統耦合;引用隊列:用戶下單後,訂單系統完成持久化處理,將消息寫入消息隊列,返回用戶訂單下單成功,訂閱下單的消息,採用拉/推的方式,獲取下單信息,庫存系統根據下單信息,進行庫存操做。流量削峯:應用場景:秒殺活動,流量瞬時激增,服務器壓力大。用戶發起請求,服務器接收後,先寫入消息隊列,假如消息隊列長度超過最大值,則直接報錯或提示用戶,後續程序讀取消息隊列再作處理,控制請求量,緩解高流量。日誌處理:應用場景:解決大量日誌的傳輸。日誌採集程序將程序寫入消息隊列,而後經過日誌處理程序的訂閱消費日誌。消息通信:應用場景:聊天室。多個客戶端訂閱同一主題,進行消息發佈和接收。常見消息隊列產品:Kafka,ActiveMQ,ZeroMQ,RabbitMQ,Redis等

  接口的併發請求:curl_multi_init

9. 數據庫緩存層的優化

  mysql等一些常見的關係型數據庫的數據都存儲在磁盤當中,在高併發場景下,業務應用對mysql產生的增刪改查的操做形成的巨大的IO開銷和查詢壓力,這無疑對數據庫和服務器都是一種巨大的壓力,爲了解決此類問題,緩存數據的概念應運而生。極大的解決數據庫服務器的壓力,提升應用數據的響應速度。常見的緩存形式:內存緩存,文件緩存。

  緩存數據是爲了讓客戶端不多甚至不訪問數據庫服務器進行數據的查詢,高併發下,能最大程度的下降對數據庫服務器的訪問壓力。默認狀況下:用戶請求->數據查詢->鏈接數據庫服務器並查詢數據->將數據緩存起來(html,內存,json,序列化數據)->顯示給客戶端;用戶再次請求或者新用戶訪問->數據查詢->直接從緩存中獲取數據->顯示給客戶端

  mysql的查詢緩存:query_cache_type:查詢緩存類型,有0,1,2三個取值,0則不使用查詢緩存,1表示始終使用查詢緩存,2表示按需使用查詢緩存。query_cache_type爲1時,亦可關閉查詢緩存,SELECT SQL_NO_CACHE * FROM my_table WHERE condition。query_cache_type爲2時,可按需使用查詢緩存,SELECT SQL_CACHE * FROM my_table WHERE condition。query_cache_size:默認狀況下爲0,表示爲查詢緩存預留的內存爲0,則沒法使用查詢緩存。SET GLOBAL query_cache_size = 134217728。查詢緩存能夠看作是SQL文本和查詢結果的映射。第二次查詢的SQL和第一次查詢的SQL徹底相同,則會使用緩存。SHOW STATUS LIKE 'Qcache_hits'; 查看命中次數。表的結構或數據發生改變時,查詢緩存中的數據再也不有效。清理緩存:FLUSH QUERY CACHE; //清理查詢緩存內存碎片,RESET QUERY CACHE; //從查詢緩存中移出全部查詢,FLUSH TABLES; //關閉全部打開的表,同時該操做將會清空查詢緩存中的內容

  使用memcache緩存查詢數據:對於大型站點,若是沒有中間緩存層,當流量打入數據庫層時,即使有以前的幾層爲咱們擋住一部分流量,可是在大併發的狀況下,仍是會有大量請求涌入數據庫層,這樣對於數據庫服務器的壓力衝擊很大,響應速度也會降低,所以添加中間緩存層頗有必要。memcache是一套分佈式的高速緩存系統,由livejournal的bradfitzpatrick開發,但目前被許多網站使用以提高網站的訪問速度,尤爲對於一些大型的,須要頻繁訪問數據庫的網站訪問速度提高效果十分顯著。

  memcache工做原理:是一個高性能的分佈式的內存對象緩存系統,經過在內存裏維護一個統一的巨大的hash表,可以用來存儲各類格式的數據,包括圖像,視頻,文件以及數據庫檢索的結果等,簡單的說就是將數據調用到內存,而後從內存中讀取,從而大大提升讀取速度。

  memcache工做流程:先檢查客戶端的請求數據是否在memcache中,若有,直接把請求數據返回,再也不對數據庫進行任何操做;若是請求的數據不在memcache中,就去查數據庫,把從數據庫中獲取的數據返回給客戶端,同時把數據緩存一份到memcache中。

  memcache方法:獲取:get(key) 設置:set(key, val, expire) 刪除:delete(key)

  通用緩存機制:用查詢的方法名+參數做爲查詢時的key value對中的key值

  使用redis緩存查詢數據:與memcache的區別:性能相差不大,redis在2.0版本後增長了本身的VM特性,突破物理內存的限制,memcache能夠修改最大可用內存,採用LRU算法;redis依賴客戶端來實現分佈式讀寫,memcache自己沒有數據冗餘機制;redis支持快照,AOF,依賴快照進行持久化,aof加強了可靠性的同時,對性能有所影響,memcache不支持持久化,一般作緩存,提高性能;memcache在併發場景下,用cas保證一致性,redis事務支持比較弱,只能保證事務中的每一個操做連續執行;redis支持多種類的數據類型;redis用於數據量較小的高性能操做和運算上,memcache用於在動態系統中減小數據庫負載,提高性能,適合作緩存,提升性能

  緩存其餘數據:session:session_set_save_handler

10. mysql數據庫層的優化

  優化方向:數據表數據類型優化,索引優化,sql語句優化,存儲引擎的優化,數據表結構設計的優化,數據庫服務器架構的優化

  數據表數據類型優化:字段使用什麼樣的數據類型更合適,性能更快,tinyint、smallint、bigint,考慮空間和範圍的問題;char、varchar,存儲字符串長度是否固定;enum,特定固定的分類可使用enum存儲,效率更快;IP地址的存儲,ip2long(),使用整型存儲IP地址

  索引的優化:創建合適的索引,索引在什麼場景下效率最高,索引的建立原則:不是越多越好,在合適的字段上建立合適的索引,複合索引的前綴原則,like查詢%的問題,全表掃描優化,or條件索引使用狀況,字符串類型索引失效的問題

  sql語句的優化:優化查詢過程當中的數據訪問,優化長難句、特定類型的查詢語句。使用limit,返回列不用*,變複雜爲簡單,切分查詢,分解關聯查詢,優化count(),優化關聯查詢,優化子查詢,優化group by和distinct,優化limit和union

  存儲引擎的優化:儘可能使用innoDB存儲引擎

  數據表結構設計的優化:分區操做,經過特定的策略對數據表進行物理拆分,對用戶透明,partition by;分庫分表,水平拆分,垂直拆分

  數據庫架構的優化:主從複製,讀寫分離,雙主熱備,binlog日誌,中繼日誌,主從庫binlog的交換,事件傳輸;負載均衡,經過LVS的三種基本模式實現負載均衡,mycat數據庫中間件實現負載均衡

11. web服務器的負載均衡

  七層負載均衡的實現:基於URL等應用層信息的負載均衡,nginx的proxy是它一個很強大的功能,實現了7層負載均衡,功能強大,性能卓越,運行穩定,配置簡單靈活,可以自動剔除工做不正常的後端服務器,上傳文件使用異步模式,支持多種分配策略,能夠分配權重,分配方式靈活。

  nginx負載均衡:內置策略:IP Hash,加權輪詢;擴展策略:fair策略,通用hash,一致性hash
  加權輪詢:首先將請求都分給高權重的機器,直到該機器的權值降到了比其餘機器低,纔開始將請求分給下一個高權重的機器,當全部後端機器都down掉時,nginx會當即將全部機器的標誌位清成初始狀態,以免形成全部的機器都處在timeout的狀態;IP Hash:流程和輪詢很相似,只是其中的算法和具體的策略有些變化,算法是一種變相的輪詢算法;fair:根據後端服務器的響應時間判斷負載狀況,從中選出負載最輕的機器進行分流;通用hash,一致性hash:通用hash比較簡單,能夠以nginx內置的變量爲key進行hash,一致性hash採用了nginx內置的一致性hash環,支持memcache

  nginx配置:

http {
    upstream cluster{
#ip_hash; server srv1 weight=1; server srv2; server srv3; } server { listen 80; location / { proxy_pass http://cluster; } } }

  四層負載均衡的實現:經過報文中的目標地址和端口,再加上負載均衡設備設置的服務器選擇方式,決定最終選擇的內部服務器。LVS實現服務器集羣負載均衡有三種方式,NAT,DR和TUN。

相關文章
相關標籤/搜索