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