1. 程式人生 > 其它 >第八章 高併發大流量

第八章 高併發大流量

技術標籤:php面試題資料庫

一.高併發架構相關概念

  1. 併發
    併發,在作業系統中,是指一個時間段中有幾個程式都處於已啟動執行到執行完畢之間,且這幾個程式都是在同一個處理機上執行,但任意時刻點只能有一個程式 在處理機上執行。

我們說的高併發是什麼?
在網際網路時代,高併發指的是併發訪問。也就是在某個時間點,有多少個訪問同時到來。
通常一個系統的日PV在千萬以上,就可能是一個高併發系統

高併發問題,我們具體該關心什麼?
QPS:每秒鐘請求或者查詢的數量,在網際網路領域,指每秒響應請求數(指HTTP請求)
吞吐量:單位時間內處理的請求數量(通常由QPS與併發數決定)
響應時間:從請求發出到收到響應花費的時間。如系統處理一個HTTP請求需要100ms,100ms就是系統的響應時間

PV:綜合瀏覽量(page view),即頁面瀏覽量或者點選量,一個網站在24小時內訪問的頁面數量
UV:獨立訪客(UniQue Visitor),即一定時間範圍內相同訪客多次訪問網站,只計算為1個獨立訪客

日網站頻寬 = PV/統計時間(換算成秒)*平均頁面大小(單位KB)*8
峰值一般是平均值的倍數,根據實際情況來定。

QPS不等於併發連線數
QPS是每秒HTTP請求數量,併發連線數是系統同時處理的請求數量

(總PV數80%)/(6小時秒數20%) = 峰值每秒請求數(QPS)
80%訪問量集中在20%的時間

壓力測試
測試能承受的最大併發
測試最大承受的QPS值

常用效能測試工具
ab、wrk 、 http_load、 Web Bench 、 Siege 、 Apache JMeter

ab
全程是apache benchmark,是apache官方推出的工具
建立多個併發訪問執行緒,模擬多個訪問者同時對某一URL地址進行訪問。他的測試目標是基於URL的,因此,他既可以用來測試apache的負載壓力,也可以測試nginx、lighthttp、tomact、IIS等其他web伺服器的壓力。
ab使用
模擬併發請求100次,總共請求5000次
ab -c 100 -n 5000 待測試網站

注意事項
測試機器與被測試機器分開
不要對線上服務做壓力測試
觀察測試工具ab所在機器,以及被測試的前端機的CPU,記憶體,網路等都不超過最高限度的75%

QPS達到極限
隨著QPS的增長,每個階段需要根據實際情況來進行優化,優化的方案也與硬體條件、網路頻寬息息相關。

QPS達到50
可以稱為小型網站,一般伺服器就可以應付
QPS達到100
假設關係型資料庫的每次請求在0.01秒完成
假設單頁面只有一個SQL查詢,那麼100QPS意味著1秒鐘完成100次請求,但是此時我們並不能保證資料庫查詢能完成100次
方案:資料庫快取層、資料庫的負載均衡
QPS達到800
假設我們使用百兆頻寬,意味著網站出口的實際頻寬是8M左右
假設每個頁面只有10K,在這個併發條件下,百兆頻寬已經吃完
方案:CDN加速,負載均衡

QPS達到1000
假設我們使用Memcache快取資料庫查詢資料,每個頁面對Memcache的請求遠大於直接對DB的請求
Memcache的悲觀併發數在2W左右,但有可能在之前內網頻寬已經吃光,表現出不穩定
方案:靜態HTML快取

QPS達到2000
達到這個級別,檔案系統訪問鎖都成為災難
方案:做業務分離,分散式儲存

高併發解決方案案例

  1. 流量優化
    防盜鏈
  2. 前端優化
    減少HTTP請求
    新增非同步請求
    啟用瀏覽器快取和檔案壓縮
    CDN加速
    建立獨立的圖片伺服器
  3. 服務端優化
    頁面靜態化
    併發處理
    佇列處理
  4. 資料庫優化
    資料庫快取
    分庫分表、分割槽操作
    讀寫分離
    負載均衡
  5. Web伺服器優化
    負載均衡

二. 流量優化

防盜鏈處理

  1. 盜鏈概念
    盜鏈是指在自己的頁面上展示一些並不在自己伺服器上的內容,獲得他人伺服器上的資源地址,繞過別人的資源展示頁面,直接在自己的頁面上向終端使用者提供此內容
    常見的是小站盜用大站的圖片、音樂、視訊、軟體等資源
    通過盜鏈的方法可以減輕自己伺服器的負擔,因為真實的空間和流量均來自別人的伺服器
  2. 什麼是防盜鏈
    防止別人通過一些技術手段繞過本站的資源展示頁面,盜用本站的資源,讓繞開本站資源展示頁面的資源連結失效
    可以大大減輕伺服器及頻寬的壓力
  3. 防盜鏈
    防盜鏈的工作原理
    通過Referer或者簽名,網站可以檢測目標網頁訪問的來源網頁,如果是資原始檔,則可以跟蹤到顯示他的網頁地址。
    一旦檢測到來源不是本站即進行阻止或者返回指定的頁面
    通過計算簽名的方式,判斷請求是否合法,如果請求合法則顯示,否則返回錯誤資訊
    防盜鏈的實現方法
    Referer
    Nginx模組ngx_http_referer_module用於阻擋來源非法的域名請求
    Nginx指令valid_referers,全域性變數$invalid_referer
    Referer
    valid_referers none | blocked |server_names |string …;
    none : "Referer"來源頭部為空
    blocked : "Referer"來源頭部不為空,但裡面的值被代理或者防火牆刪除了,這些值都不以http://或者https://開頭
    server_names : "Referer"來源頭部包含當前的server_names
  location ~ .*\.(gif|jpg|png|flv|swf|rar|zip)$
  {
    valid_referers none blocked ityhc.com  *.ityhc.com;
    if($invalid_referer)
    {
        return 403;
        #rewrite ^/ http://www.ityhc.com/403.jpg;
    }
  }

以上仿盜鏈技術有缺陷,因為可以偽造Referer
所以還可以通過加密簽名的方式實現防盜鏈
加密簽名
使用第三方模組HttpAccessKeyModule實現Nginx仿盜鏈
accesskey on|off 模組開關
accesskey_hashmethod md5 |sha-1 簽名加密方式
accesskey_arg GET引數名稱
accesskey_signature 加密規則

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

三. 前端優化

  1. 減少HTTP請求
    為什麼減少HTTP請求
    效能黃金法則
    只有10%-20%的使用者響應時間花在接收請求的HTTP文件上,剩下的80%-90%的時間花在HTTP文件所引用的所有元件(圖片、script、css、flash等等)進行的HTTP請求上

  2. 減少HTTP請求的方式
    如何改善
    (1)改善響應時間的最簡單途徑就是減少元件的數量,並由此減少HTTP請求的數量
    HTTP連線產生的開銷
    域名解析—TCP連線—請求傳送—等待—下載資源—解析時間
    疑問?
    DNS快取
    查詢DNS快取也需要時間,多個快取就要查詢多次有可能快取會被清除
    Keep-Alive
    HTTP1.1協議規定請求只能序列傳送,也就是說一百個請求必須依次逐個傳送,前面的一個請求結束才能開始下一個請求
    (2)圖片地圖
    圖片地圖允許你在一個圖片上關聯多個URL。目標URL的選擇取決於使用者單擊了圖片上的哪個位置
    使用:
    (3) CSS Sprites
    CSS精靈,通過使用合併圖片,指定CSS的background-image和background-position來顯示圖片
    圖片地圖和CSS精靈的響應時間基本相同,但比使用各自獨立圖片的方式要快50%以上
    (4)合併指令碼和樣式表
    使用外部JS和CSS檔案引入的方式,因為這比直接寫在頁面中效能要更好一點
    獨立的一個JS比用多個JS檔案組成的頁面的載入要快38%
    把多個指令碼寫在一個指令碼,把多個樣式檔案寫入一個樣式檔案
    (5)圖片使用Base64編碼減少頁面請求數
    採用Base64編碼方式將圖片直接嵌入到網頁中,而不是從外部載入

四. 啟用瀏覽器快取和檔案壓縮

HTTP快取機制

  1. 快取分類
    HTTP快取模型中,如果請求成功會有三種情況
    200 from cache:直接從本地快取中獲取響應,最快速,最省流量,因為根本沒向伺服器傳送請求
    304 Not Modified:協商快取,瀏覽器在本地沒有命中的情況下請求頭中傳送一定的校驗資料到服務端,如果服務端資料沒有改變,瀏覽器從本地快取響應,返回304
    快速,傳送的資料很少,只返回一些基本的響應頭資訊,資料量很小,不傳送實際響應體
    200 OK:以上兩種快取全都失敗,伺服器返回完整的響應。沒有用到快取,相對最慢。

  2. 本地快取
    相關Header
    Pragma:HTTP1.0時代的遺留產物,該欄位被設定為no-cache時,會告知瀏覽器禁用本地快取,即每次都向伺服器傳送請求。
    Expires:HTTP1.0時代用來啟用本地快取的欄位,expires值對應一個形如 Thu,31 Dec 2037 23:55:55GMT的格林威治時間,告訴瀏覽器快取實現的時刻,如果還沒到該時刻,標明快取有效,無需傳送請求。
    瀏覽器和伺服器的時間無法保持一致,如果時間差距大,就會影響快取結果
    Cache-Control:HTTP1.1針對Expires時間不一致的解決方案,運用Cache-Control告知瀏覽器快取過期的時間間隔而不是時刻,即使具體時間不一致,也不影響快取的管理。
    no-store :禁止瀏覽器快取響應
    no-cache:不允許直接使用本地快取,先發起請求和伺服器協商
    max-age=delta-seconds:告知瀏覽器該響應本地快取有效的最長期限,以秒為單位
    優先順序
    Pragma>Cache-Control>Expires

  3. 協商快取
    當瀏覽器沒有命中本地快取,如本地快取過期或者響應中宣告不允許直接使用本地快取,那麼瀏覽器肯定發起伺服器端請求
    服務端會驗證資料是否修改,如果沒有通知瀏覽器使用本地快取
    相關Header

Last-Modified:通知瀏覽器資源的最後修改時間
Last-Modified:Mon ,28 Sep 2015 08:06:43 GMT
If-Modified-Since:得到資源的最後修改時間後,會將這個資訊通過If-Modified-Since提交到伺服器做檢查,如果沒有修改,返回304狀態碼
If-Modified-Since:Mon ,28 Sep 2015 08:06:43 GMT

ETag:HTTP1.1推出,檔案的指紋識別符號,如果檔案內容修改,指紋會改變
ETag:“782342342-2342”
If-None-Match:本地快取失效,會攜帶此值取請求服務端,服務端判斷該資源是否改變,如果沒有改變,直接使用本地快取,返回304

適合快取的內容
不變的影象,如logo,圖示等
js、css靜態檔案
可下載的內容,媒體檔案

建議使用協商快取
HTML檔案
經常替換的圖片
經常修改的JS、CSS檔案
js、css檔案的載入可以加入檔案簽名來拒絕快取
index.css?簽名
index.簽名.js

不建議快取的內容
使用者隱私等敏感資料
經常改變的API資料介面

  1. 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時,會把Expires設定為"Mon ,28 Sep 2037 08:06:43 GMT",Cache-Control設定為10年

協商快取相關配置
Etag指令:指定簽名
etag on | off;預設為on

  1. 前端程式碼和資源的壓縮
    優勢
    讓資原始檔更小,加快檔案在網路中的傳輸,讓網頁更快的展現,降低頻寬和流量開銷
    壓縮方式
    JS CSS 圖片 HTML程式碼的壓縮
    Gzip壓縮

JS程式碼壓縮
JS程式碼壓縮的原理是去掉多餘的空格和回車,替換長變數名、簡化一些程式碼寫法等
壓縮工具有很多,有線上工具,有應用程式,有編輯器外掛
壓縮工具:UglifyJS、YUI Compressor、Closure Compiler

css程式碼壓縮
常用工具:YUI Compressor、CSS Compressor、

HTML程式碼壓縮
不建議使用程式碼壓縮,有時會破壞程式碼結構,可以使用Gzip壓縮,當然也可以使用htmlcompressor工具,不過轉換後一定要檢查程式碼結構。

圖片壓縮
壓縮工具:tinypng JpegMini ImageOptim

Gzip壓縮
配置Nginx
gzip on|off; #是否開啟gzip
gzip_buffers 32 4K |16 8K #緩衝(在記憶體中緩衝幾塊?每塊多大)
gzip_comp_level[1-9] #推薦6 壓縮級別(級別越高,壓的越小越浪費CPU計算資源)
gzip_disable #正則匹配UA 什麼樣的URL不進行gzip
gzip_min_length 200#開始壓縮的最小長度
gzip_http_version 1.0|1.1 #開始壓縮的HTTP協議版本
gzip_proxied #設定請求者代理伺服器,該如何快取內容
gzip_types text/plain application/xml #對哪些型別的檔案進行壓縮 如txt,html,css,xml
gzip_vary on|off # 是否傳輸gzip壓縮標誌

其他工具
自動化構建工具Grunt

五. CDN加速

  1. 相關概念
    什麼是CDN
    CDN全稱(Content Delivery Network內容分發網路)儘可能避開網際網路上有可能影響資料傳輸速度和穩定性的瓶頸和環節,使內容傳輸的更快、更穩定
    在網路各處放置節點伺服器所構成的在現有的網際網路基礎之上的一層智慧虛擬網路
    CDN系統能夠實時根據網路流量和各節點的連線、負載狀況以及到使用者的距離和響應時間等綜合資訊將使用者的請求重新導向離使用者最近的服務節點上

使用CDN的優勢
本地Cache加速,提高企業站點(尤其含有大量圖片和靜態頁面站點)的訪問速度
跨運營商的網路加速,保證不同網路的使用者都得到良好的訪問質量
遠端訪問使用者根據DNS負載均衡技術智慧自動選擇Cache伺服器
自動生成伺服器的遠端Mirror(映象)cache伺服器,遠端使用者訪問時從cache伺服器上讀取資料,減少遠端訪問的頻寬、分擔網路流量、減輕原站點WEB伺服器負載等功能
廣泛分佈的CDN節點機上節點間的只能冗餘機制,可以有效的預防黑客入侵

CDN工作原理
傳統訪問
使用者在瀏覽器中輸入域名發起請求—》解析域名獲取伺服器的IP地址—》根據IP地址找到對應的伺服器—》伺服器響應並返回資料
使用CDN訪問
使用者發起請求—》智慧DNS解析(根據IP判斷地址位置、接入網型別、選擇路由最短和負載最輕的伺服器)—》取得快取伺服器IP---->把內容返回給使用者(如果快取中有)—》向源站發起請求—》將結果返回給使用者—》將結果存入快取伺服器

CDN的適用場景
場景
站點或應用中大量靜態資源的加速分發,例如:CSS,JS,圖片和THML
大檔案下載
直播網站

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

六. 建立獨立的圖片伺服器

  1. 相關概念
    獨立的必要性
    分擔WEB伺服器的I/O負載-將耗費資源的圖片服務分離出來,提高伺服器的效能和穩定性
    能夠專門對圖片伺服器進行優化–為圖片服務設定有針對性的快取方法,減少頻寬成本,提高訪問速度
    提高網站的可擴充套件性–通過增加圖片伺服器,提高圖片吞吐能力
    採用獨立域名
    原因:同一域名下瀏覽器的併發連線數有限制,突破瀏覽器連線數的限制
    由於cookie的原因,對快取不利,大部分WEB cache都只快取不帶cookie的請求,導致每次的圖片請求都不能命中cache
    獨立後的問題
    如何進行圖片上傳和圖片同步
    NFS共享方式
    利用FTP同步

服務端優化

七. 頁面靜態化

  1. 相關概念
    什麼是動態語言靜態化
    將現有PHP等動態語言的邏輯程式碼生成為靜態HTML檔案,使用者訪問動態指令碼重定向到靜態HTML檔案的過程。
    對實時性要求不高的頁面

為什麼要靜態化
原因:動態指令碼通常會做邏輯計算和資料查詢,訪問量越大,伺服器壓力越大
訪問量大時,可能造成CPU負載過高,資料庫伺服器壓力過大
靜態化可以減低邏輯處理壓力,降低資料庫伺服器查詢壓力

靜態化的實現方式
(1)使用模板引擎
可以使用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(‘file.html’);//清除指定的快取
s m a r t y − > c l e a r c a c h e ( ′ a r t i c l e . h t m l ′ , smarty->clear_cache('article.html', smarty>clearcache(article.html,art_id);//清除同一個模板下的指定快取號的快取
(2)利用ob系列函式
ob_start():開啟輸出控制緩衝
ob_get_contents():返回輸出緩衝區內容
ob_clean():清空輸出緩衝區
ob_end_flush():沖刷出(送出)輸出緩衝區內容並關閉緩衝

ob_start();
輸出到頁面的HTML程式碼
。。。。
ob_get_contents();
ob_end_flush();
fopen()寫入

可以判斷檔案的inode修改時間,判斷是否過期使用filectime函式

併發處理

1. 相關概念

什麼是程序、執行緒、協程
程序(Process)是計算機中的程式關於某資料集合上的一次執行活動,是系統進行資源分配和排程的基本單位,是作業系統結構的基礎
程序是一個執行的程式
程序的三態模型:多道程式系統中,程序在處理器上交替執行,狀態不斷地發生變化
執行、就緒、阻塞
執行:當一個程序在處理機上執行時,則稱該程序處於執行狀態。處於此狀態的程序的數目小於等於處理器的數目,對於單處理機系統,處於執行狀態的進行只有一個。在沒有其他程序可以執行時(如所有的程序都在阻塞狀態),通常會自動執行系統的空閒程序。
就緒:當一個程序獲得了除處理機意外的一切所需資源,一旦得到處理機即可執行,則稱此程序處於就緒狀態。就緒程序可以按多個優先順序來劃分佇列。例如,當一個程序由於時間片用完而進入就緒狀態時,排入低優先順序佇列;當程序由I/O操作完成而進入就緒狀態時,排入高優先順序佇列。
阻塞:也稱為等待或睡眠狀態,一個程序正在等待某一事件發生(例如請求I/O而等待I/O完成等)而暫時停止執行,這時即使把處理機分配給程序也無法執行,故稱該程序處於阻塞狀態。

程序的五態模型:對於一個實際的系統,程序的狀態及其轉換更為複雜
新建態、活躍就緒/靜止就緒、執行、活躍阻塞/靜止阻塞、終止態
新建態:對應於程序剛剛被建立時沒有被提交的狀態,並等待系統完成建立程序的所有必要資訊。
終止態:程序已結束執行,回收除程序控制塊之外的其他資源,並讓其他程序從程序控制塊中收集有關資訊。
活躍就緒:指程序在主存並且可被排程的狀態
靜止就緒(掛起就緒):指程序被對換到輔存時的就緒狀態,是不能被直接排程的狀態,只有當主存中沒有活躍就緒態程序,或者是掛起就緒態程序具有更高的優先順序,系統將把掛起就緒態程序調回主存並轉換為活躍就緒。
活躍阻塞:指程序已在主存,一旦等待的事件產生便進入活躍就緒狀態。
靜止阻塞:程序對換到輔存時的阻塞狀態,一旦等待的事件產生便進入靜止就緒狀態。
由於使用者的併發請求,為每一個請求都建立一個程序顯然是行不通的,從系統資源開銷方面或是響應使用者請求的效率方面來看。因此作業系統中執行緒的概念便被引入了。
執行緒,有時候被稱為輕量級程序(lightweight Process,LWP),是程式執行流的最小單元。
執行緒是程序中的一個實體,是被系統獨立排程和分派的基本單位,執行緒自己不擁有系統資源,只擁有一點在執行中必不可少的資源但它可與同屬於一個程序的其他執行緒共享程序所擁有的全部資源。
一個執行緒可以建立和撤銷另一個執行緒,同一個程序中的多個執行緒之間可以併發執行。
執行緒是程式中一個單一的順序控制流程。程序內一個相對獨立的、可排程的執行單元,是系統獨立排程和分派CPU的基本單位指執行中的程式排程單位。
在單個程式中同時執行多個執行緒完成不同的工作,稱為多執行緒。
每個程式都至少有一個執行緒,若程式只有一個執行緒,那就是程式本身。
執行緒的狀態:就緒、阻塞、執行
就緒狀態:執行緒具備執行的所有條件,邏輯上可以執行,在等待處理機。
執行狀態:執行緒佔有處理機正在執行。
阻塞狀態:執行緒在等待一個事件(如某個訊號量),邏輯上不可執行。

協程是一種使用者態的輕量級執行緒,協程的排程完全由使用者控制。協程擁有自己的暫存器上下文和棧。協程排程切換時,將暫存器上下文和棧儲存到其他地方,在切回來的時候,恢復先前儲存的暫存器上下文和棧,直接操作棧則基本沒有核心切換的開銷,可以不加鎖的訪問全域性變數,所以上下文的切換非常快。

程序、執行緒的區別

  1. 執行緒是程序內的一個執行單元,程序內至少有一個執行緒,他們共享程序的地址空間,而程序有自己獨立的地址空間
  2. 程序是資源分配和擁有的單位,同一個程序內的執行緒共享程序的資源
  3. 執行緒是處理器排程的基本單位,但程序不是
  4. 兩者均可併發執行
  5. 每個獨立的執行緒有一個程式執行的入口、順序執行序列和程式的出口,但執行緒不能夠獨立執行,必須依存在應用程式中,由應用程式提供多個執行緒執行控制

執行緒和協程的區別

  1. 一個執行緒可以多個協程,一個程序也可以單獨擁有多個協程
  2. 執行緒程序都是同步機制,而協程則是非同步
  3. 協程能保留上一次呼叫時的狀態,每次過程重入時,就相當於進入上一次呼叫的狀態

什麼是多程序、多執行緒
多程序:同一個時間裡,同一個計算機系統中如果允許兩個或兩個以上的程序處於執行狀態,這就是多程序
邊玩QQ,邊瀏覽網頁
多開一個程序,多分配一份資源,程序間通訊不方便
多執行緒:執行緒就是把一個程序分為很多片,每一片都可以是一個獨立的流程
與多程序的區別是隻會使用一個程序的資源,執行緒間可直接通訊

多概念之間的區別
例子
單程序單執行緒:一個人在一個桌子上吃飯
單程序多執行緒:多個人在同一個桌子上一起吃飯
多程序單執行緒:多個人每個人在自己桌子上吃飯

同步阻塞模型

多程序
最早的伺服器端程式都是通過多程序、多執行緒來解決併發IO的問題
一個請求建立一個程序,然後子程序進入迴圈同步阻塞地與客戶端連線進行互動,收發處理資料
多執行緒
用多執行緒模式實現非常簡單,執行緒中可以直接向某個客戶端連線傳送資料
步驟
建立一個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併發程式設計實踐
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

八. 資料庫優化

  1. 什麼是資料庫快取
    MySQL等關係型資料庫的資料儲存在磁碟上,在高併發場景,業務應用對MySQL產生的增刪改查的操作造成巨大的I/O開銷和查詢壓力,這無疑對資料庫和伺服器都是一種巨大的壓力,為了解決此類問題,快取資料的概念應運而生。
    極大的解決資料庫伺服器的壓力
    提高應用資料的響應速度
    常見的快取形式:記憶體快取,檔案快取

  2. 為什麼要使用快取
    快取資料是為了讓客戶端很少甚至不訪問資料庫伺服器進行資料的查詢,高併發下,能最大程式的降低對資料庫伺服器的訪問壓力
    使用者請求–》資料查詢–》連線資料庫伺服器並查詢資料–》將資料快取起來(HTML,記憶體、JSON、序列化資料)—》顯示給客戶端
    第二次請求時
    使用者再次請求或者新使用者訪問—》資料查詢—》直接從快取中獲取資料—》顯示給客戶端
    快取方式的選擇
    快取場景的選擇
    快取資料的實時性
    快取資料的穩定性

  3. 使用MySQL查詢快取
    啟用MySQL查詢快取
    query_cache_type
    查詢快取型別,有0、1、2三個取值。0表示不使用查詢快取。1表示始終使用查詢快取。2表示按需使用查詢快取。
    query_cache_type為1時,也可以關閉查詢快取
    SELECT SQL_NO_CACHE * FROM my_table WHERE conditon;
    極大降低CPU使用率

query_cache_type為2時,按需使用查詢快取
SELECT SQL_CACHE * FROM my_table WHERE conditon;

query_cache_size
預設情況下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;//關閉所有開啟的表,同時該操作會清空查詢快取中的內容

  1. 使用Memcache快取
    對於大型站點,如果沒有中間快取層,當流量打入資料庫層時,即便有之前的幾層為我們擋住一部分流量,但是在大併發的情況下,還是會有大量請求湧入資料庫層,這樣對於資料庫伺服器的壓力衝擊很大,響應速度也會下降,因此新增中間快取層很有必要。
    memcache是一套分散式的快取記憶體系統,由liveJournal的 BradFitzpatrick開發,但目前被很多網站使用以提升網站的訪問速度,尤其對於一些大型的、需要頻繁訪問資料庫的網站訪問速度提升效果十分顯著
    工作原理
    memcache是一個高效能的分散式的記憶體物件快取系統,通過在記憶體中維護一個統一的巨大的hash表,它能夠用來儲存各種格式的資料,包括影象、視訊、檔案以及資料庫檢索的結果等。簡單的說就是將資料呼叫到記憶體,然後從記憶體中讀取,從而大大提高讀取速度
    工作流程
    先檢查客戶端的請求資料是否在memcached中,如果有,直接把請求資料返回,不再對資料庫進行任何操作;如果請求的資料不在memcached中,就去查資料庫,把從資料庫中獲取的資料返回給客戶端,同時把資料快取一份到memcached中
    方法
    獲取:get(key)
    設定:set(key,val,expire)
    刪除:delete(key)
    通用快取機制
    用查詢的方法名+引數作為查詢時的key value對中的key值

  2. 使用Redis快取
    與Memcache的區別
    (1)效能相差不大,使用場景不同
    (2)Redis2.0增加了自己的VM特性,突破實體記憶體限制,Memcache可以修改最大可用記憶體,採用LRU演算法
    (3)Redis依賴客戶端實現分散式讀寫
    (4)Memcache本身沒有資料冗餘機制
    (5)Redis支援(快照、AOF),依賴快照進行持久化,AOF增強了可靠性的同時,對效能有所影響
    (6)Memcache不支援持久化,通常做快取,提升效能
    (7)Memcache在併發場景下,用cas保證一致性,redis事務支援比較弱,只能保證事務中的每個操作連續執行
    (8)redis支援多種型別的資料型別
    (9)redis用於資料量較小的高效能操作和運算上
    (10)Memcache用於在動態系統中減少資料庫負載,提升效能;適合做快取,提高效能

  3. 快取其他資料
    其他資料
    Session
    session_set_save_handler

八. 資料庫優化

  1. 資料表資料型別優化
    tinyint smallint bigint
    char varchar
    enum 特定、固定的分類使用enum 男 女
    IP地址儲存

  2. 索引優化
    索引建立原則
    在合適的欄位建立合適的索引
    複合索引的字首原則

索引注意事項
複合索引的字首原則
like查詢%
全表掃描優化
or條件索引使用情況
字串型別索引失效問題

  1. SQL語句優化

(1)優化查詢過程中的資料訪問
使用limit
返回列不用*

(2)優化長難句的查詢語句
變複雜為簡單
切分查詢
分解關聯查詢

(3)優化特定型別的查詢語句
優化count()
優化關聯查詢
優化子查詢
優化group by和distinct
優化limit和union

  1. 儲存引擎優化
    (1)儘量使用innoDB儲存引擎

  2. 資料表結構設計優化
    (1)分割槽操作
    通過特定的策略對資料表進行物理拆分
    對使用者透明
    partition by
    (2)分庫分表
    水平拆分
    垂直拆分

  3. 資料庫伺服器架構優化
    (1)主從複製
    (2)讀寫分離
    (3)雙主熱備
    (4)負載均衡
    通過lvs的三種基本模式實現負載均衡
    MyCAT資料庫中介軟體實現負載均衡

九. WEB伺服器負載均衡

  1. 七層負載均衡的實現
    基於URL等應用層資訊的負載均衡
    Nginx的proxy是它一個很強大的功能,實現了7層負載均衡
    功能強大,效能卓越,執行穩定
    配置簡單靈活
    能夠自動剔除工作不正常的後端伺服器
    上傳檔案使用非同步模式
    支援多種分配策略,可以分配權重,分配方式靈活

  2. Nginx負載均衡
    內建策略、擴充套件策略
    內建策略:IP Hash,加權輪詢
    擴充套件策略:fair策略,通用hash,一致性hash

  3. 加權輪詢策略
    首先將請求都分給高權重的機器,知道該機器的權重降到了比其他機器低,才開始講請求分給下一個高權重的機器
    當所有後端機器都down掉時,Nginx會立即將所有機器的標誌位清成初試狀態,以避免造成所有機器都處在timeout的狀態

  4. IP hash策略
    是一種變相的輪詢演算法

  5. fair策略
    根據後端伺服器的響應時間判斷負載情況,從中選出負載最輕的機器進行分流

  6. 通用hash,一致性hash策略
    通用hash比較簡單,可以以Nginx內建的變數為key進行hash,一致性hash採用Nginx內建的一致性hash環,支援memcache

NGINX配置
http{
    upstream cluster{
        server srv1;
        server srv2;
        server srv3;
    }
    server{
        listen 80;
        location /{
            proxy_pass http://cluster;
        }
    }
}

  1. 四層負載均衡的實現
    通過報文中的目標地址和埠,再加上負載均衡裝置設定的伺服器選擇方式,決定最終選擇的內部伺服器
    LVS實現伺服器叢集負載均衡有三種方式,NAT,DR和TUN