服務器配置優化php
系統參數調整前端
Linux 系統內核參數優化mysql
vim /etc/sysctl.conf nginx
net.ipv4.ip_local_port_range = 1024 65535 # 用戶端口範圍 web
net.ipv4.tcp_max_syn_backlog = 4096 redis
net.ipv4.tcp_fin_timeout = 30 算法
fs.file-max=65535 # 系統最大文件句柄,控制的是能打開文件最大數量sql
數據庫參數優化數據庫
實例總體編程
thread_concurrency #併發線程數量個數
sort_buffer_size #排序緩存
read_buffer_size #順序讀取緩存
read_rnd_buffer_size #隨機讀取緩存
key_buffer_size #索引緩存
thread_cache_size #線程緩存(1G—>8, 2G—>16, 3G—>32, >3G—>64)
鏈接層(基礎優化)
設置合理的鏈接客戶和鏈接方式
max_connections #最大鏈接數,看交易筆數設置
max_connect_errors #最大錯誤鏈接數,能大則大
connect_timeout #鏈接超時
max_user_connections #最大用戶鏈接數
skip-name-resolve #跳過域名解析
wait_timeout #等待超時
back_log #能夠在堆棧中的鏈接數量
SQL 層(基礎優化)
query_cache_size:查詢緩存
OLAP 類型數據庫,須要重點加大此內存緩存.
可是通常不會超過 GB.
對於常常被修改的數據,緩存會立馬失效。
咱們能夠實用內存數據庫(redis、memecache),替代他的功能。
存儲引擎層
innodb 基礎優化參數
default-storage-engine
innodb_buffer_pool_size # 沒有固定大小,50%測試值,看看狀況再微調。可是儘可能設置不要超過物理內存70% innodb_file_per_table=(1,0)
innodb_flush_log_at_trx_commit=(0,1,2) #1是最安全的,0是性能最高,2折中
binlog_sync
Innodb_flush_method=(O_DIRECT, fdatasync)
innodb_log_buffer_size #100M如下
innodb_log_file_size #100M 如下
innodb_log_files_in_group #5個成員如下,通常2-3個夠用(iblogfile0-N)
innodb_max_dirty_pages_pct #達到百分之75的時候刷寫 內存髒頁到磁盤。log_bin
max_binlog_cache_size #能夠不設置
max_binlog_size #能夠不設置
innodb_additional_mem_pool_size #小於2G內存的機器,推薦值是20M。32G內存以上100M
大數據的一些操做
大數據的分頁
直接用 limit start, count 分頁語句
當起始頁較小時,查詢沒有性能問題,隨着起始記錄的增長,時間也隨着增大
發現
1)limit 語句的查詢時間與起始記錄的位置成正比
2)mysql 的 limit 語句是很方便,可是對記錄不少的表並不適合直接使用
對 limit 分頁問題的性能優化方法
利用表的覆蓋索引來加速分頁查詢
咱們都知道,利用了索引查詢的語句中若是隻包含了那個索引列(覆蓋索引),那麼這種狀況會查詢很快。
由於利用索引查找有優化算法,且數據就在查詢索引上面,不用再去找相關的數據地址了,這樣節省了不少時間。另外 Mysql 中也有相關的索引緩存,在併發高的時候利用緩存就效果更好了。
id 字段是主鍵,天然就包含了默認的主鍵索引。
覆蓋索引
若是一個索引包含 (或覆蓋) 全部須要查詢的字段的值,稱爲‘覆蓋索引’。即只需掃描索引而無須回表。
覆蓋索引優勢
1.索引條目一般遠小於數據行大小,只須要讀取索引,則mysql會極大地減小數據訪問量。
2.由於索引是按照列值順序存儲的,因此對於IO密集的範圍查找會比隨機從磁盤讀取每一行數據的IO少不少。
3.一些存儲引擎如myisam在內存中只緩存索引,數據則依賴於操做系統來緩存,所以要訪問數據須要一次系統調用
4.innodb的聚簇索引,覆蓋索引對innodb表特別有用。
覆蓋索引必需要存儲索引列的值,而哈希索引、空間索引和全文索引不存儲索引列的值,因此 mysql 只能用 B-tree 索引作覆蓋索引。
例子
select id from product limit 866613, 20
SELECT * FROM product WHERE ID > =(select id from product limit 866613, 1) limit 20
SELECT * FROM product a JOIN (select id from product limit 866613, 20) b ON a.ID = b.id
百萬級的數據的導出
一。對於數據超過了 65535 行的問題,很天然的就會想到將整個數據分塊,利用 excel 的多 sheet 頁的功能,將超出 65535 行後的數據寫入到下一個 sheet 頁中,即經過多 sheet 頁的方式,突破了最高 65535 行數據的限定,具體作法就是,單獨作一個連接,使用 JSP 導出,在 JSP 上經過程序判斷報表行數,超過 65535 行後分 SHEET 寫入。這樣這個問題就得以解決了
二。在這種大數據量的報表生成和導出中,要佔用大量的內存,尤爲是在使用 TOMCAT 的狀況下,JVM 最高只能支持到 2G 內存,則會發生內存溢出的狀況。此時的內存開銷主要是兩部分,一部分是該報表生成時的開銷,另外一部分是該報表生成後寫入一個 EXCEL 時的開銷。因爲 JVM 的 GC 機制是不能強制回收的,所以,對於此種情形,咱們要改變一種方式:
將該報表設置起始行和結束行參數,在 API 生成報表的過程當中,分步計算報表,好比一張 20 萬行數據的報表,在生成過程當中,可經過起始行和結束行分 4-5 次進行。這樣,就下降了報表生成時的內存佔用,在後面報表生成的過程當中,若是發現內存不夠,便可自動啓動 JVM 的 GC 機制,回收前面報表的緩存
導出 EXCEL 的過程,放在每段生成報表以後當即進行,改多個 SHEET 頁爲多個 EXCEL,即在分步生成報表的同時分步生成 EXCEL,則經過 POI 包生成 EXCEL 的內存消耗也得以下降。經過
屢次生成,一樣能夠在後面 EXCEL 生成所須要的內存不足時,有效回收前面生成 EXCEL 時佔用的內存
再使用文件操做,對每一個客戶端的導出請求在服務器端根據 SESSIONID 和登錄時間生成惟一的臨時目錄,用來放置所生成的多個 EXCEL,而後調用系統控制檯,打包多個 EXCEL 爲 RAR
或者 JAR 方式,最終反饋給用戶一個 RAR 包或者 JAR 包,響應客戶請求後,再次調用控制檯刪除該臨時目錄。
經過分段運算和生成,有效下降了報表從生成結果到生成 EXCEL 的內存開銷。其次是經過使用壓縮包,響應給用戶的生成文件體積大大縮小,下降了多用戶並
發訪問時服務器下載文件的負擔,有效減小多個用戶導出下載時服務器端的流量,從而達到進一步減輕服務器負載的效果
php 相關
cgi ,fastcgi,php-fpm 區別
cgi
CGI 的英文是(COMMON GATEWAY INTERFACE)公共網關接口,它的做用就是幫助服務器與語言通訊,這裏就是 nginx 和 php 進行通訊,由於 nginx 和 php 的語言不通,所以須要一個溝通轉換的過程,而 CGI 就是這個溝通的協議。
nginx 服務器在接受到瀏覽器傳遞過來的數據後,若是請求的是靜態的頁面或者圖片等無需動態處理的則會直接根據請求的 url 找到其位置而後返回給瀏覽器,這裏無需 php 參與,可是若是是一個動態的頁面請求,這個時候 nginx 就必須與 php 通訊,這個時候就會須要用到 cgi 協議,將請求數據轉換成 php 能理解的信息,而後 php 根據這些信息返回的信息也要經過 cgi 協議轉換成 nginx 能夠理解的信息,最後 nginx 接到這些信息再返回給瀏覽器。
fast-cgi
傳統的 cgi 協議在每次鏈接請求時,會開啓一個進程進行處理,處理完畢會關閉該進程,所以下次鏈接,又要再次開啓一個進程進行處理,所以有多少個鏈接就有多少個 cgi 進程,這也就是爲何傳統的 cgi 會顯得緩慢的緣由,所以過多的進程會消耗資源和內存。
而 fast-cgi 每次處理完請求後,不會 kill 掉這個進程,而是保留這個進程,使這個進程能夠一次處理多個請求。這樣每次就不用從新 fork 一個進程了,大大提升效率。
php-cgi
php-cgi 是 php 提供給 web serve 也就是 http 前端服務器的 cgi 協議接口程序,當每次接到 http 前端服務器的請求都會開啓一個 php-cgi 進程進行處理,並且開啓的 php-cgi 的過程當中會先要重載配置,數據結構以及初始化運行環境,若是更新了 php 配置,那麼就須要重啓 php-cgi 才能生效,例如 phpstudy 就是這種狀況。
php-fpm
php-fpm 是 php 提供給 web serve 也就是 http 前端服務器的 fastcgi 協議接口程序,它不會像 php-cgi 同樣每次鏈接都會從新開啓一個進程,處理完請求又關閉這個進程,而是容許一個進程對多個鏈接進行處理,而不會當即關閉這個進程,而是會接着處理下一個鏈接。它能夠說是 php-cgi 的一個管理程序,是對 php-cgi 的改進。
php-fpm 會開啓多個 php-cgi 程序,而且 php-fpm 常駐內存,每次 web serve 服務器發送鏈接過來的時候,php-fpm 將鏈接信息分配給下面其中的一個子程序 php-cgi 進行處理,處理完畢這個 php-cgi 並不會關閉,而是繼續等待下一個鏈接,這也是 fast-cgi 加速的原理,可是因爲 php-fpm 是多進程的,而一個 php-cgi 基本消耗 7-25M 內存,所以若是鏈接過多就會致使內存消耗過大,引起一些問題,例如 nginx 裏的 502 錯誤。
同時 php-fpm 還附帶一些其餘的功能:
例如平滑過渡配置更改,普通的 php-cgi 在每次更改配置後,須要從新啓動才能初始化新的配置,而 php-fpm 是不須要,php-fpm 分將新的鏈接發送給新的子程序 php-cgi,這個時候加載的是新的配置,而原先正在運行的 php-cgi 仍是使用的原先的配置,等到這個鏈接後下一次鏈接的時候會使用新的配置初始化,這就是平滑過渡。
參考連接:https://blog.csdn.net/belen_xue/article/de…
PHP5 跟 php7 的區別
PHP7.0 號稱是性能提高上革命性的一個版本。面對 Facebook 家的 HHVM 引擎帶來的壓力,開發團隊重寫了底層的 Zend Engine,名爲 Zend Engine 2。
底層內核解析
PHP7 中最重要的改變就是 zval 再也不單獨從堆上分配內存而且不本身存儲引用計數。須要使用 zval 指針的複雜類型(好比字符串、數組和對象)會本身存儲引用計數。這樣就能夠有更少的內存分配操做、更少的間接指針使用以及更少的內存分配。在 PHP7 中的 zval, 已經變成了一個值指針,它要麼保存着原始值,要麼保存着指向一個保存原始值的指針。也就是說如今的 zval 至關於 PHP5 的時候的 zval . 只不過相比於 zval , 直接存儲 zval, 咱們能夠省掉一次指針解引用,從而提升緩存友好性.
參考連接:https://www.jb51.net/article/76732.htm
PHP7 爲何比 PHP5 性能提高了
一、變量存儲字節減少,減小內存佔用,提高變量操做速度
二、改善數組結構,數組元素和 hash 映射表被分配在同一塊內存裏,下降了內存佔用、提高了 cpu 緩存命中率
三、改進了函數的調用機制,經過優化參數傳遞的環節,減小了一些指令,提升執行效率
安全
函數修改
preg_replace () 再也不支持 /e 修飾符,,同時官方給了咱們一個新的函數 preg_replace_callback
create_function () 被廢棄,實際上它是經過執行 eval 實現的。
mysql* 系列全員移除,若是你要在 PHP7 上面用老版本的 mysql* 系列函數須要你本身去額外裝了,官方不在自帶,如今官方推薦的是 mysqli 或者 pdo_mysql。
unserialize () 增長一個可選白名單參數,其實就是一個白名單,若是反序列數據裏面的類名不在這個白名單內,就會報錯。
assert () 默認不在能夠執行代碼
語法修改
foreach 再也不改變內部數組指針
8 進制字符容錯率下降,在 php5 版本,若是一個八進制字符若是含有無效數字,該無效數字將被靜默刪節。在 php7 裏面會觸發一個解析錯誤。
十六進制字符串再也不被認爲是數字
移除了 ASP 和 script PHP 標籤
超大浮點數類型轉換截斷,將浮點數轉換爲整數的時候,若是浮點數值太大,致使沒法以整數表達的狀況下, 在 PHP5 的版本中,轉換會直接將整數截斷,並不會引起錯誤。在 PHP7 中,會報錯。
整體
性能提高:PHP7 比 PHP5.0 性能提高了兩倍。
全面一致的 64 位支持。
之前的許多致命錯誤,如今改爲 [拋出異常]。
PHP 7.0 比 PHP5.0 移除了一些老的不在支持的 SAPI([服務器端] 應用編程端口)和擴展。
.PHP 7.0 比 PHP5.0 新增了空接合操做符。
PHP 7.0 比 PHP5.0 新增長告終合比較運算符。
PHP 7.0 比 PHP5.0 新增長了函數的返回類型聲明。
PHP 7.0 比 PHP5.0 新增長了標量類型聲明。
PHP 7.0 比 PHP5.0 新增長匿名類。
多進程同時讀寫一個文件
PHP 是支持進程的而不支持多線程(這個先搞清楚了),若是是對於文件操做,其實你只須要給文件加鎖就能解決,不須要其它操做,PHP 的 flock 已經幫你搞定了。
用 flock 在寫文件前先鎖上,等寫完後解鎖,這樣就實現了多線程同時讀寫一個文件避免衝突。
流程
flock 參數說明:file 必需,規定要鎖定或釋放的已打開的文件,lock 必需。規定要使用哪一種鎖定類型。block 可選。若設置爲 1 或 true,則當進行鎖定時阻擋其餘進程。
LOCK_SH 要取得共享鎖定(讀取的程序)
LOCK_EX 要取得獨佔鎖定(寫入的程序)
LOCK_UN 要釋放鎖定(不管共享或獨佔)
LOCK_NB 若是不但願 flock () 在鎖定時堵塞
在 PHP 中,flock 彷佛工做的不是那麼好!在多併發狀況下,彷佛是常常獨佔資源,不即時釋放,或者是根本不釋放,形成死鎖,從而使服務器的 cpu 佔用很高,甚至有時候會讓服務器完全死掉。好因此使用 flock 以前,必定要慎重考慮。
解決方案
對文件進行加鎖時,設置一個超時時間,超時設置爲 1ms,若是這裏時間內沒有得到鎖,就反覆得到,直接得到到對文件操做權爲止,固然。若是超時限制已到,就必需立刻退出,讓出鎖讓其它進程來進行操做。
不使用 flock 函數,借用臨時文件來解決讀寫衝突的問題
將須要更新的文件考慮一份到咱們的臨時文件目錄,將文件最後修改時間保存到一個變量,併爲這個臨時文件取一個隨機的,不容易重複的文件名。
當對這個臨時文件進行更新後,再檢測原文件的最後更新時間和先前所保存的時間是否一致。
若是最後一次修改時間一致,就將所修改的臨時文件重命名到原文件,爲了確保文件狀態同步更新,因此須要清除一下文件狀態。
可是,若是最後一次修改時間和先前所保存的一致,這說明在這期間,原文件已經被修改過,這時,須要把臨時文件刪除,而後返回 false, 說明文件這時有其它進程在進行操做。
對操做的文件進行隨機讀寫,以下降併發的可能性。
先前須要定義一個隨機空間,空間越大,併發的的可能性就越小,這裏假設隨機讀寫空間爲 [1-500], 那麼咱們的日誌文件的分佈就爲 log1~ 到 log500 不等。每一次用戶訪問,都將數據隨機寫到 log1~log500 之間的任一文件。在同一時刻,有 2 個進程進行記錄日誌,A 進程多是更新的 log32 文件,而 B 進程呢?則此時更新的可能就爲 log399. 要知道,若是要讓 B 進程也操做 log32, 機率基本上爲 1/500, 差很少約等於零。在須要對訪問日誌進行分析時,這裏咱們只須要先將這些日誌合併,再進行分析便可。使用這種方案來記錄日誌的一個好處時,進程操做排隊的可能性比較小,可使進程很迅速的完成每一次操做。
將全部要操做的進程放入一個隊列中。
隊列中的每個排除的進程至關於第一個具體的操做,因此第一次咱們的服務只須要從隊列中取得至關於具體操做事項就能夠了,若是這裏還有大量的文件操做進程,不要緊,排到咱們的隊列後面便可,只要願意排,隊列的多長都不要緊。