新聞中心
本篇文章給大家整理分享28道php面試題(附答案分享),帶你梳理基礎(chǔ)知識,有一定的參考價值,有需要的朋友可以參考一下,希望對大家有所幫助。

過完年之后打算尋找新的工作機(jī)會,發(fā)現(xiàn)之前自己對于很多基礎(chǔ)的面試?yán)斫夂蛯W(xué)習(xí)不夠深刻,為了鼓勵自己持續(xù)前進(jìn)所以最近開始在論壇和搜索引擎上開始學(xué)習(xí)和總結(jié)相關(guān)知識,其中有一些題目時論壇里面一些前輩分享過的題目或者答案,還有一部分時自己最近面試遇到的問題,基于自己的理解和前輩們的分享歸檔了一部分,所以分享出來,希望對其他的小伙伴們也有幫助,同時也希望能收到大佬們對于理解有誤的地方的指導(dǎo),最近一段時間會持續(xù)更新
1、底層實(shí)現(xiàn)是通過散列表(hash table) + 雙向鏈表(解決hash沖突)
-
hashtable:將不同的關(guān)鍵字(key)通過映射函數(shù)計(jì)算得到散列值(Bucket->h) 從而直接索引到對應(yīng)的Bucket
-
hash表保存當(dāng)前循環(huán)的指針,所以foreach 比for更快
-
Bucket:保存數(shù)組元素的key和value,以及散列值h
2、如何保證有序性
-
1. 散列函數(shù)和元素?cái)?shù)組(Bucket)中間添加一層大小和存儲元素?cái)?shù)組相同的映射表。
-
2. 用于存儲元素在實(shí)際存儲數(shù)組中的下標(biāo)
-
3. 元素按照映射表的先后順序插入實(shí)際存儲數(shù)組中
-
4. 映射表只是原理上的思路,實(shí)際上并不會有實(shí)際的映射表,而是初始化的時候分配Bucket內(nèi)存的同時,還會分配相同數(shù)量的 uint32_t 大小的空間,然后將 arData 偏移到存儲元素?cái)?shù)組的位置。
3、解決hash重復(fù)(php使用的鏈表法):
-
1. 鏈表法:不同關(guān)鍵字指向同一個單元時,使用鏈表保存關(guān)鍵字(遍歷鏈表匹配key)
-
2. 開放尋址法:當(dāng)關(guān)鍵字指向已經(jīng)存在數(shù)據(jù)的單元的時候,繼續(xù)尋找其他單元,直到找到可用單元(占用其他單元位置,更容易出現(xiàn)hash沖突,性能下降)
4、基礎(chǔ)知識
-
鏈表:隊(duì)列、棧、雙向鏈表、
-
鏈表 :元素 + 指向下一元素的指針
-
雙向鏈表:指向上一元素的指針 + 元素 + 指向下一元素的指針
二、冒泡排序的時間復(fù)雜度和空間復(fù)雜度
1、代碼實(shí)現(xiàn)
$arr = [2, 4, 1, 5, 3, 6];
for ($i = 0; $i < (count($arr)); $i++) {
for ($j = $i + 1; $j < (count($arr)); $j++) {
if ($arr[$i] <= $arr[$j]) {
$temp = $arr[$i];
$arr[$i] = $arr[$j];
$arr[$j] = $temp;
}
}
}
result : [6,5,4,3,2,1]
2、計(jì)算原理
-
第一輪:將數(shù)組的第一個元素和其他所有的元素進(jìn)行比較,哪個元素更大,就換順序,從而冒泡出第一大(最大)的元素
-
第一輪:將數(shù)組的第二個元素和其他所有的元素進(jìn)行比較(第一大已經(jīng)篩選出來不用繼續(xù)比較了),哪個元素更大,就換順序,從而冒泡出第二大的元素
-
... 依次類推,冒泡從大到小排序的數(shù)組
平均時間復(fù)雜度:O(n^2) ;
最優(yōu)時間復(fù)雜度:O(n) ,需要加判斷,第一次循環(huán)如果一次都沒有交換就直接跳出循環(huán)
空間復(fù)雜度:O(1),交換元素的時候的臨時變量占用的空間
最優(yōu)空間復(fù)雜度:O(1),排好序,不需要交換位置
3、時間復(fù)雜度和空間復(fù)雜度
時間復(fù)雜度:全程為漸進(jìn)時間復(fù)雜度,估算對處理器的使用效率(描述算法的效率趨勢,并不是指算法具體使用的時間,因?yàn)椴煌瑱C(jī)器的性能不一致,只是一種效率計(jì)算的通用方法)
表示方法:大O符號表示法
復(fù)雜度量級:
-
常數(shù)階O(1)
-
線性階O(n)
-
平方階O(n2)
-
立方階O(n3)
-
K次方階O(n^k)
-
指數(shù)階(2^n)
-
對數(shù)階O(logN)
-
線性對數(shù)階O(nlogN)
時間復(fù)制類型:
-
最好時間復(fù)雜度
-
最壞時間復(fù)雜度
-
平均時間復(fù)雜度
-
均攤時間復(fù)雜度
空間復(fù)雜度:全程漸進(jìn)空間復(fù)雜度,估算對計(jì)算機(jī)內(nèi)存的使用程度(描述算法占用的存儲空間的趨勢,不是實(shí)際占用空間,同上)
三、網(wǎng)絡(luò)七層協(xié)議及 TCP 和 TCP
應(yīng)用層、表示層、會話層、傳輸層、網(wǎng)絡(luò)層、(數(shù)據(jù))鏈路層、物理層
記憶套路:
首字:應(yīng)表會傳(物鏈網(wǎng))
第一個字:應(yīng)用層(出現(xiàn)次數(shù)多,易憶)
前四個正向:應(yīng)表 - 會傳
后三個反向:物聯(lián)網(wǎng)諧音比網(wǎng)鏈物更好記
四、TCP 和 UDP 的特點(diǎn)和區(qū)別
1、都是屬于傳輸層協(xié)議
2、TCP
-
面向連接,所以只能一對一
-
面向字節(jié)流傳輸
-
數(shù)據(jù)可靠,不丟失
-
全雙工通信
3、UDP(根據(jù)TCP特點(diǎn)反記)
-
無連接,支持一對一,一對多,多對多
-
面向保溫傳輸
-
首部開銷小,數(shù)據(jù)不一定可靠但是速度更快
五、TCP 的三次握手和四次揮手
1、三次握手:
-
1)第一次:客戶端發(fā)送SYN = 1,seq = client_isn
作用:
客戶端:無
服務(wù)端:確認(rèn)自己的接收功能和客戶端的發(fā)送功能
-
2)第二次:服務(wù)端發(fā)送SYN = 1,seq = server_isn,ACK =client_isn +1
作用:
客戶端:確認(rèn)自己發(fā)送和接收都正常,確認(rèn)服務(wù)端的接收和發(fā)送正常
服務(wù)端:確認(rèn)自己的接收正常,確認(rèn)服務(wù)端的發(fā)送正常(這時候服務(wù)端還不能確認(rèn)客戶端接收是否正常)
-
3)第三次:客戶端發(fā)送SYN = 0, ACK = server_isn+1,seq =client_isn+1
作用:雙方確認(rèn)互相的接收和發(fā)送正常,建立連接
2、四次揮手
-
1)第一次:客戶端發(fā)送FIN
作用:告訴服務(wù)端我沒有數(shù)據(jù)發(fā)送了(但是還能接收數(shù)據(jù))
-
2)第二次:服務(wù)端發(fā)送ACK
作用:告訴客戶端收到請求了,可能服務(wù)端可能還有數(shù)據(jù)需要發(fā)送,所以客戶端收到進(jìn)入FIN_WAIT狀態(tài),等服務(wù)端數(shù)據(jù)傳輸完之后發(fā)送FIN
-
3)第三次:服務(wù)端發(fā)送FIN
作用:服務(wù)端告訴客戶端我發(fā)送完了,可以關(guān)閉連接了。
-
4)第四次:客戶端發(fā)送ACK
作用:客戶端收到FIN之后,擔(dān)心服務(wù)端不知道要關(guān)閉,所以發(fā)送一個ACK,進(jìn)入TIME_WAIT,等待2MSL之后如果沒有收到回復(fù),證明服務(wù)端已經(jīng)關(guān)閉了,這時候客戶端也關(guān)閉連接。
注意:
-
當(dāng)收到對方的FIN報(bào)文時,僅僅表示對方不再發(fā)送數(shù)據(jù)了但是還能接收數(shù)據(jù)
-
最后需要等待2MSL是因?yàn)榫W(wǎng)絡(luò)是不可靠的,如果服務(wù)端沒有收到最后一次ACK,服務(wù)端會重新放FIN包然后等客戶端再次發(fā)送ACK包然后關(guān)閉(所以客戶端最后發(fā)送ACK之后不能立即關(guān)閉連接)
六、HTTP 狀態(tài)碼
1、狀態(tài)碼分類
-
- 1xx:信息,服務(wù)器收到請求,需要請求者繼續(xù)操作
-
- 2xx:成功
-
- 3xx:重定向
-
- 4xx:客戶端錯誤
-
- 5xx:服務(wù)端錯誤
2、常用狀態(tài)碼
-
200:請求成功
-
301:永久重定向
-
302:臨時移動
-
400 bad request:客戶端請求語法錯誤
-
401 unauthorized:客戶端沒有權(quán)限
-
403 forbidden:服務(wù)器拒絕客戶端請求
-
404 not found:客戶端請求資源不存在
-
500 Internal Server Eerro:服務(wù)器內(nèi)部錯誤
-
502 bad gateway:作為網(wǎng)關(guān)或者代理工作的服務(wù)器嘗試執(zhí)行請求時,從上游服務(wù)器接收到無效的響應(yīng)
-
503 Service Unavailable 超載或系統(tǒng)維護(hù)
-
504 Gateway timeout:網(wǎng)關(guān)超時
3、502 的原因及解決方法
原因:nginx將請求提交給網(wǎng)關(guān)(php-fpm)處理異常導(dǎo)致
1)fastcgi 緩沖區(qū)設(shè)置過小
fastcgi_buffers 8 16k;
fastcgi_buffer_size 32k;
2)php-cgi的進(jìn)程數(shù)設(shè)置過少
查看FastCgi進(jìn)程數(shù):netstat -anpo | grep "php-cgi"| wc -l
調(diào)整參數(shù)最大子進(jìn)程數(shù):max_children
一般按照單個進(jìn)程20M計(jì)算需要需要設(shè)置的子進(jìn)程數(shù)
3)max_requests(內(nèi)存溢出或頻繁重啟)
參數(shù)指明每個children最多能處理的請求數(shù)量,到達(dá)最大值之后會重啟children。
設(shè)置過小可能導(dǎo)致頻繁重啟children:
php將請求輪詢給每個children,在大流量的場景下,每一個children 到達(dá)最大值的時間差不多,如果設(shè)置過小可能多個children 在同一時間關(guān)閉,nginx無法將請求轉(zhuǎn)發(fā)給php-fpm,cpu降低,負(fù)載變高。
設(shè)置過大可能導(dǎo)致內(nèi)存泄露
4)php執(zhí)行時間超過nginx等待時間
fastcgi_connect_timeout
fastcgi_send_timeout
fastcgi_read_timeout
5)fastcgi執(zhí)行時間
max_execution_time
七、http 和 HTTPS 的區(qū)別
1、端口:http 80; https :443
2、http無狀態(tài),https是有http + ssl構(gòu)建的可進(jìn)行加密傳輸?shù)膮f(xié)議
3、http明文傳輸,https加密傳輸
4、http更快,三次握手三個包,https 需要12個包(3個tcp包+9個ssl握手包)
八、redis 分布式鎖及問題
1、實(shí)現(xiàn):
加鎖:setnx
解鎖:del
鎖超時:expire
2、可能出現(xiàn)的問題
-
1)setnx 和expire非原子性問題(加鎖之后還沒來得及設(shè)置超時就掛了)
解決方案:
Redis 2.6.12以上版本為set指令增加了可選參數(shù),偽代碼如下:set(key,1,30,NX),這樣就可以取代setnx指令
-
2)超時誤刪其他進(jìn)程鎖。(A進(jìn)程執(zhí)行超時,導(dǎo)致鎖釋放,這時候B進(jìn)程獲取鎖開始處理請求,這時候A進(jìn)程處理完成,會誤刪B進(jìn)程的鎖)
解決方案:只能刪除自己進(jìn)程的鎖 (lua腳本防止B進(jìn)程獲取過期鎖之后誤刪A進(jìn)程的鎖)
-
3)并發(fā)場景,A進(jìn)程執(zhí)行超時導(dǎo)致鎖釋放,這時候B進(jìn)程獲取到鎖。
解決方案:開啟守護(hù)進(jìn)程,給當(dāng)前進(jìn)程要過期的鎖延時。
-
4)單點(diǎn)實(shí)例安全問題
單機(jī)宕機(jī)之后導(dǎo)致所有客戶端無法獲取鎖
解決:
主從復(fù)制,因?yàn)槭钱惒酵瓿傻乃詿o法完全實(shí)現(xiàn)解決
九、redis 為什么是單線程?為什么快?
十、redis 的數(shù)據(jù)類型及應(yīng)用場景
1、string :
普通的key/value存儲
2、hash:
hashmap:鍵值隊(duì)集合,存儲對象信息
3、list:
雙向鏈表:消息隊(duì)列
4、set:
value永遠(yuǎn)為null的hashMap:無序集合且不重復(fù):計(jì)算交集、并集、差集、去重值
5、zset:
有序集合且不重復(fù):hashMap(去重) + skiplist跳躍表(保證有序):排行榜
十一、redis 實(shí)現(xiàn)持久化的方式及原理、特點(diǎn)
1、RDB持久化(快照):指定時間間隔內(nèi)的內(nèi)存數(shù)據(jù)集快照寫入磁盤
1)fork一個子進(jìn)程,將快照內(nèi)容寫入臨時RDB文件中(dump.rdb),當(dāng)子進(jìn)程寫完快照內(nèi)容之后新的文件替換老的文件
2)整個redis數(shù)據(jù)庫只包含一個備份文件
3)性能最大化,只需要fork子進(jìn)程完成持久化工作,減少磁盤IO
4)持久化之前宕機(jī)可能會導(dǎo)致數(shù)據(jù)丟失
2、AOF持久化 :以日志的形式記錄服務(wù)器的所有的寫、刪除操作
1)每接收到一個寫的命令用write函數(shù)追加到文件appendonly.aof
2)持久化的文件會越來越大,存在大量多余的日志(0 自增100次到100,會產(chǎn)生100條日志記錄)
3)可以設(shè)置不同的fsync策略
-
appendfsync everysec :1s一次,最多丟失1s的數(shù)據(jù)(默認(rèn))
-
appendfsync always :每次變動都會執(zhí)行一次
-
appendfsync no :不處理
4)AOF文件太大之后會進(jìn)行重寫:壓縮AOF文件大小
-
fork一個子進(jìn)程,將redis內(nèi)地?cái)?shù)據(jù)對象的最新狀態(tài)寫入AOF臨時文件(類似rdb快照)
-
主進(jìn)程收到的變動會先寫入內(nèi)存中,然后同步到老的AOF文件中(重寫失敗之后也能保證數(shù)據(jù)完整性)
-
子進(jìn)程完成重寫之后會將內(nèi)存中的新變動同步追加到AOF的臨時文件中
-
父進(jìn)程將臨時AOF文件替換成新的AOF文件,并重命名。之后收到的新命令寫入到新的文件中
十二、秒殺設(shè)計(jì)流程及難點(diǎn)
1、靜態(tài)緩存
2、nginx 負(fù)載均衡
三種方式:DNS輪詢、IP負(fù)債均衡、CDN
3、限流機(jī)制
方式:ip限流、接口令牌限流、用戶限流、header動態(tài)token(前端加密,后端解密)
4、分布式鎖
方式:
-
setnx + expire (非原子性,redis2.6 之后set保證原子性)
-
釋放鎖超時 (開啟守護(hù)進(jìn)程自動續(xù)時間)
-
過期鎖誤刪其他線程(requestId驗(yàn)證或者lua腳本保證查 + 刪的原子性)
5、緩存數(shù)據(jù)
方式:
-
緩存擊穿:緩存數(shù)據(jù)預(yù)熱 + 布隆過濾器/空緩存
-
緩存雪崩:緩存設(shè)置隨機(jī)過期時間,防止同一時間過期
6、庫存及訂單
-
扣庫存
-
redis 自減庫存,并發(fā)場景下可能導(dǎo)致負(fù)數(shù),影響庫存回倉:使用lua腳本保證原子性
-
redis預(yù)扣庫存之后,然后使用異步消息創(chuàng)建訂單并更新庫存變動
-
數(shù)據(jù)庫更新庫存使用樂觀鎖:where stock_num - sell_num > 0
-
添加消息發(fā)送記錄表及重試機(jī)制,防止異步消息丟失
-
-
創(chuàng)建訂單
-
前端建立websocket連接或者輪詢監(jiān)聽訂單狀態(tài)
-
消費(fèi)驗(yàn)證記錄狀態(tài),防止重復(fù)消費(fèi)
-
-
回倉
-
創(chuàng)建訂單之后發(fā)送延時消息,驗(yàn)證訂單支付狀態(tài)及庫存是否需要回倉
-
十三、防 sql 注入
1、過濾特殊字符
2、過濾數(shù)據(jù)庫關(guān)鍵字
3、驗(yàn)證數(shù)據(jù)類型及格式
4、使用預(yù)編譯模式,綁定變量
十四、事務(wù)隔離級別
1、標(biāo)準(zhǔn)的sql隔離級別實(shí)現(xiàn)原理
-
未提交讀:其他事務(wù)可以直接讀到?jīng)]有提交的:臟讀
-
事務(wù)對當(dāng)前被讀取的數(shù)據(jù)不加鎖
-
在更新的瞬間加行級共享鎖到事務(wù)結(jié)束釋放
-
-
提交讀:事務(wù)開始和結(jié)束之間讀取的數(shù)據(jù)可能不一致,事務(wù)中其他事務(wù)修改了數(shù)據(jù):不可重復(fù)度
-
事務(wù)對當(dāng)前讀取的數(shù)據(jù)(被讀到的時候)行級共享鎖,讀完釋放
-
在更新的瞬間加行級排他鎖到事務(wù)結(jié)束釋放
-
-
可重復(fù)讀:事務(wù)開始和結(jié)束之前讀取的數(shù)據(jù)保持一致,事務(wù)中其他事務(wù)不能修改數(shù)據(jù):可重復(fù)讀
-
事務(wù)對當(dāng)前讀到的數(shù)據(jù)從事務(wù)一開始就加一個行級共享鎖
-
在更新的瞬間加行級排他鎖到事務(wù)結(jié)束釋放
-
其他事務(wù)再事務(wù)過程中可能會新增數(shù)據(jù)導(dǎo)致幻讀
-
-
串行化
-
事務(wù)讀取數(shù)據(jù)時加表級共享鎖
-
事務(wù)更新數(shù)據(jù)時加表級排他鎖
-
2、innodb的事務(wù)隔離級別及實(shí)現(xiàn)原理(?。『蜕厦娴牟灰粯?,區(qū)分理解一個是隔離級別 一個是??!事務(wù)!!隔離級別)
1)基本概念
-
mvcc:多版本并發(fā)控制:依賴于undo log 和read view
-
讓數(shù)據(jù)都讀不會對數(shù)據(jù)加鎖,提高數(shù)據(jù)庫并發(fā)處理能力
-
寫操作才會加鎖
-
一條數(shù)據(jù)有多個版本,每次事務(wù)更新數(shù)據(jù)的時候會生成一個新的數(shù)據(jù)版本,舊的數(shù)據(jù)保留在undo log
-
一個事務(wù)啟動的時候只能看到所有已經(jīng)提交的事務(wù)結(jié)果
-
-
當(dāng)前讀:讀取的是最新版本
-
快照讀:讀取的是歷史版本
-
間隙鎖:間隙鎖會鎖住一個范圍內(nèi)的索引
-
update id between 10 and 20
-
無論是否范圍內(nèi)是否存在數(shù)據(jù),都會鎖住整個范圍:insert id = 15,將被防止
-
只有可重復(fù)讀隔離級別才有間隙鎖
-
-
next-key lock:
-
索引記錄上的記錄鎖+ 間隙鎖(索引值到前一個索引值之間的間隙鎖)
-
前開后閉
-
阻止幻讀
-
2)事務(wù)隔離級別
-
未提交讀
-
事務(wù)對當(dāng)前讀取的數(shù)據(jù)不加鎖,都是當(dāng)前讀
-
在更新的瞬間加行級共享鎖到事務(wù)結(jié)束釋放
-
-
提交讀
-
事務(wù)對當(dāng)前讀取的數(shù)據(jù)不加鎖,都是快照讀
-
在更新的瞬間加行級排他鎖到事務(wù)結(jié)束釋放
-
-
可重復(fù)讀
-
事務(wù)對當(dāng)前讀取的數(shù)據(jù)不加鎖,都是快照讀
-
事務(wù)再更新某數(shù)據(jù)的瞬間,必須加行級排他鎖(Record 記錄鎖、GAP間隙鎖、next-key 鎖),事務(wù)結(jié)束釋放
-
間隙鎖解決的是幻讀問題
-
主從復(fù)制的情況下 ,如果沒有間隙鎖,master庫的A、B進(jìn)程
-
A進(jìn)程 delete id < 6 ;然后還沒有commit
-
B進(jìn)程insert id = 3,commit
-
A進(jìn)程提交commit
-
該場景下,主庫會存在一條id =3 的記錄,但是binlog里面是先刪除再新增就會導(dǎo)致從庫沒有數(shù)據(jù),導(dǎo)致主從的數(shù)據(jù)不一致
-
-
MVCC的快照解決的是不可重復(fù)讀問題
-
-
串行化
-
事務(wù)讀取數(shù)據(jù)時加表級,當(dāng)前讀
-
事務(wù)更新數(shù)據(jù)時加表級排他鎖
-
十五、索引原理
索引就是幫助數(shù)據(jù)庫高效查找數(shù)據(jù)的存儲結(jié)構(gòu),存儲再磁盤中,需要消耗磁盤IO
1、存儲引擎
-
myisam 支持表鎖,索引和數(shù)據(jù)分開存儲適合跨服務(wù)器遷移
-
innodb 支持行鎖,索引和數(shù)據(jù)存儲再一個文件
2、索引類型
-
hash索引
-
適合精確查詢且效率高
-
無法排序、不適合范圍查詢
-
hash沖突的情況下需要遍歷鏈表(php數(shù)組的實(shí)現(xiàn)原理、redis zset 的實(shí)現(xiàn)原理類似)
-
-
b-tree、b+tree
-
b-tree 和b+tree的去區(qū)別
-
b+tree 的數(shù)據(jù)全部存儲在葉子節(jié)點(diǎn),內(nèi)部節(jié)點(diǎn)只存key,一次磁盤IO能獲取到更多的節(jié)點(diǎn)
-
b-tree 的內(nèi)部節(jié)點(diǎn)和葉子節(jié)點(diǎn)都存儲key和數(shù)據(jù),查找數(shù)據(jù)不需要找到葉子節(jié)點(diǎn),內(nèi)部節(jié)點(diǎn)可以直接返回?cái)?shù)據(jù)
-
b+tree 增加了葉子節(jié)點(diǎn)到相鄰節(jié)點(diǎn)的指針,方便返回查詢遍歷
-
-
-
聚簇索引和非聚簇索引
-
概念
-
聚簇索引 :索引和數(shù)據(jù)存儲在一個節(jié)點(diǎn)
-
非聚簇索引:索引和數(shù)據(jù)分開存儲,通過索引找到數(shù)據(jù)實(shí)際存儲的地址
-
-
-
詳解:
-
innodb 使用的聚簇索引,且默認(rèn)主鍵索引為聚簇索引(沒有主鍵索引的時候,選擇一個非空索引,還沒有則隱式的主鍵索引),輔助索引指向聚簇索引位置,然后在找到實(shí)際存儲地址
-
myisam 使用非聚簇索引,所有的索引都只需要查詢一次就能找到數(shù)據(jù)
-
聚簇索引的優(yōu)勢和略勢
1. 索引和數(shù)據(jù)在一起,同一頁的數(shù)據(jù)會被緩存到(buffer)內(nèi)存中,所以查看同一頁數(shù)據(jù)的時候只需要從內(nèi)存中取出,
2. 數(shù)據(jù)更新之后之只需要維護(hù)主鍵索引即可,輔助索引不受影響
3. 輔助索引存的是主鍵索引的值,占用更多的物理空間。所以會受到影響
4. 使用隨機(jī)的UUID,數(shù)據(jù)分布不均勻,導(dǎo)致聚簇索引可能掃全表,降低效率,所以盡量使用自增主鍵id
-
十六、分表 (分庫) 的策略
1、流程
評估容量和分表數(shù)量-> 根據(jù)業(yè)務(wù)選定分表key->分表規(guī)則(hash、取余、range)->執(zhí)行->考慮擴(kuò)容問題
2、水平拆分
-
根據(jù)字段水平拆分為多個表
-
每個表的結(jié)構(gòu)相同
-
所有分表的合集是全量數(shù)量
3、垂直拆分
-
根據(jù)字段垂直拆分
-
表結(jié)構(gòu)不一樣,分表的同一個關(guān)聯(lián)行是一條完整的數(shù)據(jù)
-
擴(kuò)展表,熱點(diǎn)字段和非熱點(diǎn)字段的拆分(列表和詳情的拆分)
-
獲取數(shù)據(jù)時,盡量避免使用join,而是兩次查詢結(jié)果組合
4、問題
-
跨庫join問題
-
全局表:需要關(guān)聯(lián)部分系統(tǒng)表的場景
-
冗余法:常用字段進(jìn)行冗余
-
組裝法:多次查詢的結(jié)果進(jìn)行組裝
-
-
跨節(jié)點(diǎn)的分頁、排序、函數(shù)問題
-
事務(wù)一致性
-
全局主鍵id
-
使用uuid -> 會降低聚簇索引效率
-
使用分布式自增id
-
-
擴(kuò)容問題
-
升級從庫
-
從庫升級為主庫,數(shù)據(jù)一致,只需要刪除冗余數(shù)據(jù)即可
-
成倍擴(kuò)容:需要在加一倍從庫
-
-
雙寫遷移:
-
新數(shù)據(jù)進(jìn)行雙寫,同時寫進(jìn)新老數(shù)據(jù)庫
-
舊數(shù)據(jù)復(fù)制到新數(shù)據(jù)庫
-
以老數(shù)據(jù)庫為準(zhǔn),驗(yàn)證數(shù)據(jù)一致性之后刪除冗余數(shù)據(jù)
-
-
十七、select 和 update 的執(zhí)行流程
1、mysql 構(gòu)成
-
server層:連接器->緩存器->分析器(預(yù)處理器)->優(yōu)化器->執(zhí)行器
-
引擎層 : 查詢和存儲數(shù)據(jù)
2、select 執(zhí)行過程
-
客戶端發(fā)送請求,建立連接
-
server層查找緩存,命中直接返回,否則繼續(xù)
-
分析七分析sql語句以及預(yù)處理(驗(yàn)證字段合法性及類型等)
-
優(yōu)化器生成執(zhí)行計(jì)劃
-
執(zhí)行器調(diào)用引擎API查詢結(jié)果
-
返回查詢結(jié)果
3、update執(zhí)行過程
-
基礎(chǔ)概念
-
buffer pool(緩存池),在內(nèi)存中,下次讀取同一頁的數(shù)據(jù)的時候可以直接從buffer pool中返回(innodb的聚簇索引)
-
更新數(shù)據(jù)的時候先更新buffer pool,然后在更新磁盤
-
臟頁:內(nèi)存中的緩存池更新了,但是沒有更新磁盤
-
刷臟:inndb 中有一個專門的進(jìn)程將buffer pool的數(shù)據(jù)寫入磁盤,每隔一段時間將多個修改一次性寫入磁盤
-
redo log 和 binlog
-
redo log(重做日志),innodb特有的日志,物理日志,記錄修改
-
redo log是重復(fù)寫,空間固定且會用完,會覆蓋老日志
-
binlog 是server層共有的日志,邏輯日志,記錄語句的原始邏輯
-
binlog 是追加寫到一定大小切換到下一個,不會覆蓋以前的日志
-
redo log主要是用來恢復(fù)崩潰,bin log是用來記錄歸檔的二進(jìn)制日志
-
redo log只能恢復(fù)短時間內(nèi)的數(shù)據(jù),binlog可以通過設(shè)置恢復(fù)更大的數(shù)據(jù)
-
-
WAL(write-ahead-logging)先寫日志方案
-
記錄日志是順序IO
-
直接寫入磁盤(刷盤)是隨機(jī)IO,因?yàn)閿?shù)據(jù)是隨機(jī)的,可能分布在不同的扇區(qū)
-
順序IO的效率更高,先寫入修改日志,可以延遲刷盤時機(jī),提高吞吐量
-
-
redo log 刷盤機(jī)制,check point
-
redo log大小固定,循環(huán)寫入
-
redo log 就像一個圓圈,前面是check point (到這個point就開始覆蓋老的日志),后面是write point (當(dāng)前寫到的位置)
-
write point 和check point 重疊的時候就證明redo log 滿了,需要開始同步redo log 到磁盤中了
-
-
-
執(zhí)行步驟(兩階段提交 - 分布式事務(wù),保證兩個日志的一致性)
-
分析更新條件,查找需要更新的數(shù)據(jù)(會用到緩存)
-
server 調(diào)用引擎層的API,Innodb 更新數(shù)據(jù)到內(nèi)存中,然后寫入redo log,然后進(jìn)入prepare
-
引擎通知server層開始提交數(shù)據(jù)
-
server層寫入binlog 日志,并且調(diào)用innodb 的接口發(fā)出commit請求
-
引擎層收到請求之后提交commit
-
-
宕機(jī)后數(shù)據(jù)崩潰恢復(fù)規(guī)則
-
如果redo log 狀態(tài)為commit ,則直接提交
-
如果redo log 狀態(tài)為prepare,則判斷binlog 中的事務(wù)是否commit,是則提交,否則回滾
-
-
如果不使用兩次提交的錯誤案例(update table_x set value = 10 where value = 9)
-
先redo log 再寫入binlog
1. redo log 寫完之后,binlog沒寫完,這時候宕機(jī)。
2. 重啟之后redo log 完整,所以恢復(fù)數(shù)據(jù) value = 10
3. bin log日志中沒有記錄,如果需要恢復(fù)數(shù)據(jù)的時候 value = 9
-
先寫binlog 再寫redo log
1. binlog 寫入完成,redo log 未完成
2. 重啟之后沒有redo log ,所以value 還是9
3. 當(dāng)需要恢復(fù)數(shù)據(jù)的時候binlog 日志完整,value 更新成10
-
-
undo log
-
在更新寫入buffer pool之前記錄
-
如果更新過程中出錯,直接回滾到undo log 的狀態(tài)
-
十八、binlog 的作用和三種格式
作用:
1. 數(shù)據(jù)恢復(fù)
2. 主從復(fù)制
格式(二進(jìn)制文件):
1)statement
-
1. 記錄每次sql語句的原文
-
2. 刪除一個表只需要記錄一條sql語句,不需要記錄每一行的變化,節(jié)約IO,提高性能,減少日志量
-
3. 可能出現(xiàn)主從不一致(存儲過程、函數(shù)等)
-
4. RC隔離級別(讀提交),因?yàn)閎inlog 記錄順序是按照事務(wù)commit 順序記錄的,所以可能導(dǎo)致主從復(fù)制不一致。通過可重復(fù)讀級別的間隙鎖的引入,可以解決。
2)row
-
1. 記錄每條記錄的修改情況,不需要記錄sql語句的上下文記錄
-
2. 導(dǎo)致binlog日志量很大
-
3. 刪除一個表:記錄每條記錄都被刪除的狀況
3)mixed
-
1. 前兩個格式的混合版
-
2. 根據(jù)語句自動選擇使用哪一種:
-
一般的sql語句修改使用statement
-
修改表結(jié)構(gòu)、函數(shù)、存儲過程等操作選擇row
-
update 和delete 還是會記錄全部記錄的變化
-
十九、主從同步(主從復(fù)制)的原理和問題及讀寫分離
1、解決的問題
-
數(shù)據(jù)分布
-
負(fù)載均衡
-
數(shù)據(jù)備份,高可用,避免單點(diǎn)失敗
-
實(shí)現(xiàn)讀寫分離,緩解數(shù)據(jù)庫壓力
-
升級測試(使用高版本mysql當(dāng)從庫)
2、支持的復(fù)制類型(binlog 的三種格式)
-
基于sql語句的復(fù)制
-
基于行的復(fù)制
-
混合型復(fù)制
3、原理
1)基礎(chǔ)概念
-
從庫生成兩個線程
-
I/O線程
-
SQL線程
-
-
主庫生成線程
-
log dumo 線程
-
2)流程(主節(jié)點(diǎn)必須開啟bin log功能,)
-
1. 從節(jié)點(diǎn)開啟start slave 命令之后,創(chuàng)建一個IO進(jìn)程連接到主節(jié)點(diǎn)
-
2. 連接成功之后,主節(jié)點(diǎn)創(chuàng)建一個 log dump線程(主節(jié)點(diǎn)會為每一個從節(jié)點(diǎn)創(chuàng)一個log dump線程)
-
3. 當(dāng)binlog發(fā)生變化時,主節(jié)點(diǎn)的dump log線程會讀取bin-log內(nèi)容并發(fā)送給從節(jié)點(diǎn)
-
4. 主節(jié)點(diǎn)dump log 線程讀取bin-log 的內(nèi)容時會對主節(jié)點(diǎn)的bin-log加鎖,讀取完成在發(fā)送給從節(jié)點(diǎn)之前釋放鎖
-
5. 從節(jié)點(diǎn)的IO線程接收主節(jié)點(diǎn)發(fā)送的binlog內(nèi)容,并將其寫入本地relay log 文件中
-
6. 主從節(jié)點(diǎn)通過binlog文件+position偏移量定位主從同步的位置,從節(jié)點(diǎn)會保存接收到的position偏移量,如果從節(jié)點(diǎn)發(fā)生宕機(jī)重啟,自動從postion位置發(fā)起同步
-
7. 從節(jié)點(diǎn)的SQL線程復(fù)制讀取本地relay log的內(nèi)容,解析成具體的操作并執(zhí)行,保證主從數(shù)據(jù)一致性
4、主從復(fù)制的模式
1)異步模式(默認(rèn)方式)
-
1. 可能導(dǎo)致主從不一致(主從延時)
-
2. 主節(jié)點(diǎn)接收到客戶端提交的事務(wù)之后直接提交事務(wù)并返回給客戶端
-
3. 如果主節(jié)點(diǎn)事務(wù)提交之后,log dump還沒來得及寫入就宕機(jī)就會導(dǎo)致主從數(shù)據(jù)不一致
-
4. 不用關(guān)心主從的同步操作,性能最好
2)全同步模式
-
1. 可靠更高,但是會影響主庫相應(yīng)時間
-
2. 主節(jié)點(diǎn)接收到客戶端提交的事務(wù)之后,必須等待binlog 發(fā)送給從庫,并且所有從庫全部執(zhí)行完事務(wù)之后才返回給客戶端
3)半同步模式
-
1. 增加一部分可靠性,增加主庫一部分相應(yīng)時間
-
2. 主節(jié)點(diǎn)接收到客戶端提交的事務(wù)之后,等待binlog發(fā)送給至少一個從庫并且成功保存到本地relay log中,此時主庫提交事務(wù)并返回給客戶端
4)server-id的配置和server-uuid
-
1. server-id用于標(biāo)識數(shù)據(jù)庫實(shí)例,防止在鏈?zhǔn)街鲝?、多主多從拓?fù)渲袑?dǎo)致SQL語句的無限循環(huán)
-
2. server-id默認(rèn)值為0,對于主機(jī)來說依然會記錄二進(jìn)制日志,但是會拒絕所有的從機(jī)連接。
-
2. server-id = 0 對于從機(jī)來說會拒絕連接其他實(shí)例
-
3. server-id是一個全局變量,修改之hi偶必須重啟服務(wù)
-
4. 主庫和從庫的server-id重復(fù)時
-
默認(rèn)replicate-same-server-id = 0,從庫會跳過所有主從同步的數(shù)據(jù),導(dǎo)致主從數(shù)據(jù)不一致
-
replicate-same-server-id = 1,可能導(dǎo)致無線循環(huán)執(zhí)行sql
-
-
兩個從庫(B、C)server-id重復(fù)會導(dǎo)致主從連接異常,時斷時連
-
主庫(A)發(fā)現(xiàn)相同的server-id會斷開之前的連接,重新注冊新的連接
-
B、C從庫的連接會周而復(fù)始的重連
-
-
MySQL服務(wù)會自動創(chuàng)建并生成server-uuid配置
-
當(dāng)主從同步時如果主從實(shí)例的server-uuid相同會報(bào)錯退出,不過我們可以通過設(shè)置replicate-same-server-id=1來避免報(bào)錯(不推薦)
-
5、讀寫分離
1)基于代碼實(shí)現(xiàn),減少硬件開支
2)基于中間代理實(shí)現(xiàn)
3)主從延時
-
從庫性能比主庫差
-
大量查詢導(dǎo)致從庫壓力大,消耗大量CPU資源,影響同步速度:一主多從
-
大事務(wù)執(zhí)行:事務(wù)執(zhí)行完之后才會寫入binlog,從庫讀取延時
-
主庫ddl(alter、drop、create)
二十、死鎖
1、產(chǎn)生的四個必要條件
-
1. 互斥條件
-
2. 請求與保持條件:一次性分配全部資源,否則一個都不分配
-
3. 非剝奪條件:當(dāng)進(jìn)程獲得一部分資源等待其他資源的時候釋放占有的資源
-
4. 循環(huán)等待條件:
理解:一個資源只能被一個進(jìn)程占用,進(jìn)程獲取資源資源還能申請新的資源,并且已經(jīng)獲得的資源不能被剝奪,同時多個進(jìn)程相互等待其他進(jìn)程被占用的資源
2、解除死鎖
-
1. 終止進(jìn)程(全部干掉)
-
2. 逐個種植(殺一個看一下有沒有解除)
二十一、Mysql 優(yōu)化大分頁查詢 limit 100000 (offset),10 (page_sie)
1、原因
mysql查詢分頁數(shù)據(jù)時不是直接跳過offset(100000),而是取offset + page_size = 100000 + 10 = 100010條數(shù)據(jù),然后放棄其掉前面的100000條數(shù)據(jù),所以效率地下
2、優(yōu)化方案
-
延時關(guān)聯(lián):使用覆蓋索引
-
主鍵閾值法:主鍵是自增的情況下,通過條件推算出符合條件的主鍵最大值&最小值(使用覆蓋索引)
-
記錄上一頁的結(jié)果位置,避免使用 OFFSET
二十二、redis 緩存和 mysql 數(shù)據(jù)一致性
方式:
1、先更新redis 再更新數(shù)據(jù)庫
場景:update set value = 10 where value = 9
1) redis更新成功:redis value = 10
2)數(shù)據(jù)庫更新失敗:mysql value = 9
3)數(shù)據(jù)不一致
2、先更新數(shù)據(jù)庫,再更新redis
場景: A進(jìn)程update set value = 10 where value = 9 ;B進(jìn)程 update set value = 11 where value = 9;
1)A 進(jìn)程先更新數(shù)據(jù)庫,還未寫入緩存:mysql value = 10 ;redis value = 9
2)B 進(jìn)程更新數(shù)據(jù)庫并且提交事務(wù),寫入緩存:mysql value = 11;redis value = 11;
3)A 進(jìn)程處理完請求提交事務(wù),寫入緩存:redis value = 10;
4)最終 mysql value = 11; redis value = 10
3、先刪除緩存再更新數(shù)據(jù)庫
場景:A進(jìn)程update set value = 10 where value = 9 ;B進(jìn)程查詢value;
1)A 進(jìn)程先刪除緩存 還沒來得及修改數(shù)據(jù)或者事務(wù)未提交
2)B 進(jìn)程開始查詢,沒有命中緩存,所以查庫并寫入緩存 redis value = 9
3)A 進(jìn)程更新數(shù)據(jù)庫完成 mysql value = 10
4)最終 mysql value = 10;redis value = 9
解決方案:
1、延時雙刪除
場景:A進(jìn)程update set value = 10 where value = 9 ;B進(jìn)程查詢value;
1)A 進(jìn)程先刪除緩存 還沒來得及修改數(shù)據(jù)或者事務(wù)未提交
2)B 進(jìn)程開始查詢,沒有命中緩存,所以查庫并寫入緩存 redis value = 9
3)A 進(jìn)程更新數(shù)據(jù)庫完成 mysql value = 10
4)A 進(jìn)程估算延時時間,sleep之后再次刪除緩存
5)最終mysql value = 10;redis value 為空(下次查詢直接查庫)
6)延時的原因時防止B進(jìn)程在A進(jìn)程更新完之后B進(jìn)程還沒來得及寫入緩存
2、請求串行化
1)創(chuàng)建兩個隊(duì)列 :更新隊(duì)列和查詢隊(duì)列
2)當(dāng)緩存不存在需要查庫的時候?qū)ey存入更新隊(duì)列
3)如果查詢未完成之前有新的請求進(jìn)來,并且發(fā)現(xiàn)更新隊(duì)列中還存在key則將key放入查詢隊(duì)列,則等待;不存在則重復(fù)第二步
4)如果查詢的數(shù)據(jù)發(fā)現(xiàn)查詢隊(duì)列已經(jīng)存在則不需要再次寫入隊(duì)列
5)數(shù)據(jù)更新完成之后rpop更新隊(duì)列,同時rpop查詢隊(duì)列,釋放查詢請求
6)查詢請求可以使用while + sleep 查詢緩存并且設(shè)置最大延遲時間,還沒有完成則返回空
二十三、redis 中的 connect 和 pconnect
1、connect :腳本結(jié)束之后釋放連接
1. close :釋放連接
2、pconnect(長連接) :腳本結(jié)束連接不釋放,連接保持在php-fpm進(jìn)程中,生命周期隨著php-fpm進(jìn)程的生命周期
-
1. close不釋放連接
-
只是當(dāng)前php-cgi進(jìn)程中不能再次請求redis
-
當(dāng)前php-cgi中的后續(xù)連接仍然可以復(fù)用,直到php-fpm結(jié)束生命周期
-
-
2. 減少建立redis連接的消耗
-
3. 減少一個php-fpm多次建立連接
-
4. 消耗更多的內(nèi)存,并且連接數(shù)持續(xù)增加
-
5. 同一個php-fpm的woker子進(jìn)程(php-cgi)的上一個請求可能會影響到下一個請求
3、pconnect 的連接復(fù)用問題
-
變量A select db 1 ;變量B select db 2;會影響到變量A的db
-
解決:每一個db創(chuàng)建一個連接實(shí)例
二十四、redis zset 有序集合使用 skiplist 的原理
1、基本概念
1. skiplist是一個隨機(jī)的數(shù)據(jù),以有序的方式在層次化的鏈表中保存元素(只能用于元素有序的情況)
2. skiplist實(shí)在有序鏈表和多層鏈表的基礎(chǔ)上演變的
3. 允許重復(fù)值,所以對比檢查除了要對比key 還要對比value
4. 每個節(jié)點(diǎn)都帶有一個高度為1的后退指針,用于表頭方向到表尾方向的迭代
5. 時間復(fù)雜度O(logn)、空間復(fù)雜度O(n)
2、跳躍表和平衡樹的對比
1)范圍查詢效率
-
跳躍表范圍查詢效率更高,因?yàn)檎业阶钚≈抵笾恍枰獙Φ谝粚拥逆湵磉M(jìn)行遍歷直到小于最大值即可
-
平衡樹范圍查詢找到最小值之后還要進(jìn)行中序遍歷找到其他不超過最大值的節(jié)點(diǎn)
2)內(nèi)存占用
-
skiplist 每個節(jié)點(diǎn)的指針數(shù)量為1/(1-p)
-
平衡樹的每個節(jié)點(diǎn)指針數(shù)都為2
3)插入和刪除操作
-
skiplist只需要修改相鄰節(jié)點(diǎn)的指針
-
平衡樹變更會引起子樹的調(diào)整
二十五、redis 的過期刪除和淘汰機(jī)制
1、常規(guī)過期刪除策略
1)定時刪除
-
通過定時器在過期的時候立即刪除
-
內(nèi)存釋放及時但是消耗更多的CPU,大并發(fā)的時候需要消耗CPU資源影響處理請求的速度
-
內(nèi)存友好,CPU不友好
2)惰性刪除
-
放任鍵過期不管,到下次需要去取出的時候檢查是否過期并刪除
-
可能存在大量過期鍵,且不會使用,導(dǎo)致內(nèi)存溢出
-
內(nèi)存不友好,CPU友好
3)定期刪除
-
每隔一段時間檢查,刪除過期的鍵
-
刪除多少和檢查多少有算法決定
2、redis采用的 惰性刪除 + 定期刪除
-
周期性隨機(jī)測試一些設(shè)置了過期時間的鍵進(jìn)行檢查,到期則刪除
-
每次清理的時間不超過CPU的25%,達(dá)到時間則退出檢查
-
定期沒有刪除到的鍵,且以后不會使用的鍵還是會存在內(nèi)存中,所以需要配合淘汰策略
3、淘汰策略(內(nèi)存不足以寫入新數(shù)據(jù)的時候執(zhí)行)
-
volatile-lru :設(shè)置了過期時間且最近使用越少越優(yōu)先淘汰
-
volatile-ttl :設(shè)置了過期時間且過期時間越早越優(yōu)先淘汰
-
volatile-random :設(shè)置了過期時間中隨機(jī)刪除
-
allkeys-lru :所有鍵中過期時間越早越優(yōu)先淘汰
-
allkeys-random :所有鍵中過期隨機(jī)淘汰
-
no-enviction :不允許淘汰,內(nèi)存不足報(bào)錯
二十六、redis 常見問題及解決方案
1、緩存雪崩:同一時間大量緩存失效,導(dǎo)致請求直接查詢數(shù)據(jù)庫,數(shù)據(jù)庫內(nèi)存和CPU壓力增加甚至宕機(jī)
解決:
-
熱點(diǎn)數(shù)據(jù)永不過期或者分布到不同實(shí)例,降低單機(jī)故障問題
-
緩存時間添加隨機(jī)數(shù),防止大量緩存同時失效
-
做二級緩存或者雙緩存,A為原始緩存 短時效,B為備份緩存 ,長期有效。更新時候雙寫緩存
2、緩存穿透:緩存和數(shù)據(jù)庫都沒有數(shù)據(jù),大量請求下,所有請求直接擊穿到數(shù)據(jù)庫,導(dǎo)致宕機(jī)。
解決:
-
布隆過濾器:長度為m的位向量或者位列表組成(僅包含0或1位值的列表)
-
使用多個不用的hash函數(shù),產(chǎn)生多個索引值,填充對應(yīng)多個位置的值為1
-
布隆過濾器可以檢查值是 “可能在集合中” 還是 “絕對不在集合中”
-
可能誤判但是基礎(chǔ)過濾效率高
-
極端情況,當(dāng)布隆過濾器沒有空閑位置的時候每次查詢返回true
-
-
空緩存(短時效)
-
業(yè)務(wù)層參數(shù)過濾
3、緩存擊穿:數(shù)據(jù)庫中有數(shù)據(jù),但是緩存突然失效之后發(fā)生大量請求導(dǎo)致數(shù)據(jù)庫壓力增加甚至打垮宕機(jī)
解決:
-
熱點(diǎn)數(shù)據(jù)永不過期
-
互斥鎖:獲取鎖之后不管成功還是失敗都要釋放鎖
二十七、php-fpm 詳解及生命周期
1、基礎(chǔ)知識
1)CGI協(xié)議
-
動態(tài)語言的代碼文件需要通過對應(yīng)的解析器才能被服務(wù)器識別
-
CGI協(xié)議就是用來使服務(wù)器和解釋器相互通信的
-
服務(wù)器解析PHP文件需要PHP解釋器加上對應(yīng)的CGI協(xié)議
2)CGI程序 = php-cgi
-
php-cgi就是一個遵守CGI協(xié)議的CGI程序
-
同時也就是PHP解釋器
-
標(biāo)準(zhǔn)的CGI每個請求都會解析php.ini,初始化執(zhí)行環(huán)境等,降低性能
-
每次修改配置之后需要重新php-cgi才能讓php.ini生效
-
不能動態(tài)worker調(diào)度,只能一開始指定數(shù)量的worker
3)FastCGI協(xié)議
-
和CGI一樣也是一個協(xié)議/規(guī)范,不過是再CGI的基礎(chǔ)上優(yōu)化,效率更高
-
用來提高CGI程序性能的
-
實(shí)現(xiàn)了CGI進(jìn)程的管理
4)FastCGI程序 = php-fpm
-
php-fpm就是一個遵守FastCGI協(xié)議的FastCGI程序
-
FastCGI程序?qū)GI程序的管理模式
-
啟動一個master進(jìn)程,解析配置文件,初始化環(huán)境
-
啟動多個worker子進(jìn)程
-
接受到請求之后,傳遞給woker進(jìn)程去執(zhí)行
-
-
解決修改php.ini之后平滑重啟問題
-
process_control_timeout:子進(jìn)程接受主進(jìn)程復(fù)用信號的超時時間(在規(guī)定時間內(nèi)處理完請求,完成不了就不管了)
-
設(shè)定php-fpm留給fastcgi進(jìn)程響應(yīng)重啟信號的時間
-
process_control_timeout = 0,也就是不生效,無法保證平滑重啟
-
process_control_timeout設(shè)置過大可能導(dǎo)致系統(tǒng)請求堵塞
-
process_control_timeout =10的情況下,如果代碼邏輯需要11s,重啟舊可能導(dǎo)致代碼執(zhí)行部分退出
-
建議值:request_terminate_timeout
-
-
重啟類型
-
優(yōu)雅重啟
-
強(qiáng)制重啟
-
2、php-fpm生命周期:待更新
PHP-FPM 生命周期:https://www.abelzhou.com/php/php-fpm-lifespan/#
二十八、Nginx 和 php 之間的通信
1、通信方式:fastcgi_pass
1)tcp socket
-
跨服務(wù)器,nginx和php不在一個機(jī)器時,只能用這個方式
-
面向連接的協(xié)議,更好的保證通信的正確性和完整性
2)unix socket
-
不需要網(wǎng)絡(luò)協(xié)議棧、打包拆包等
-
減少tcp 開銷,效率比tcp socket 更高
-
高并發(fā)時候不穩(wěn)定,連接數(shù)暴增產(chǎn)生大量的長時緩存,大數(shù)據(jù)包可能直接返回異常
二十九、web 漏洞及問題
1、sql注入
2、XSS攻擊
推薦閱讀(很詳細(xì)的案例來分析XSS攻擊的不同類型及解決方案):[前端安全系列(一):如何防止XSS攻擊?](https://tech.meituan.com/2018/09/27/fe-security.html)
3、CSRF攻擊:
推薦閱讀 :[前端安全系列(二):如何防止CSRF攻擊?](https://tech.meituan.com/2018/10/11/fe-security-csrf.html)
4、文件上傳漏洞
推薦閱讀 :[淺析文件上傳漏洞](https://xz.aliyun.com/t/7365)
5、跨域問題:
1)jsonp
2)cors
3)nginx代理
名稱欄目:分享2022年最新的28道PHP面試題(附答案)
鏈接分享:http://m.fisionsoft.com.cn/article/cojspoo.html


咨詢
建站咨詢
