2021年最新PHP 面試、筆試題匯總(二)
二十一、語句include和require的區別
require是無條件包含,也就是如果一個流程里加入require,無論條件成立與否都會先執行require,當文件不存在或者無法打開的時候,會提示錯誤,并且會終止程序執行
include有返回值,而require沒有(可能因為如此require的速度比include快),如果被包含的文件不存在的化,那么會提示一個錯誤,但是程序會繼續執行下去
注意:包含文件不存在或者語法錯誤的時候require是致命的,而include不是
require_once,include_once表示了只包含一次,避免了重復包含
二十二、php中傳值與傳引用的區別,并說明傳值什么時候傳引用
變量默認總是傳值賦值,那也就是說,當將一個表達式的值賦予一個變量時,整個表達式的值被賦值到目標變量,這意味著:當一個變量的賦予另外一個變量時,改變其中一個變量的值,將不會影響到另外一個變量
php也提供了另外一種方式給變量賦值:引用賦值。這意味著新的變量簡單的引用(換言之,成為了其別名或者指向)了原始變量。改動的新的變量將影響到原始變量,反之亦然。
使用引用賦值,簡單地將一個&符號加到將要賦值的變量前(源變量)
對象默認是傳引用
對于較大的數據,可以考慮傳引用,這樣可以節省內存的開銷
二十三、PHP 不使用第三個變量實現交換兩個變量的值
//方法一
$a.=$b;
$b=str_replace($b,"",$a);
$a=str_replace($b,"",$a);
//方法二
list($b,$a)=array($a,$b);
var_dump($a,$b);
二十四、mysql優化
MySQL查詢SQL優化
二十五、redis 和 memache 緩存的區別
1.數據類型
redis支持多種數據類型(5種):hash string list set zset
memcache 只支持key-value
2.持久性
redis 支持兩種持久化方式 RDB、AOF
memcache 不支持持久化
3.分布式存儲
redis支持master-slave復制模式
memcache可以使用一致性hash做分布式
4.value大小不同
memcache是一個內存緩存,key的長度小于250字符,單個item存儲要小于1M,不適合虛擬機使用
5.線程模型
memcache是master+worker的線程模型,其中master完成網絡監聽后投遞到worker線程,由worker線程處理
redis是單進程單線程模型,即單個線程完成所有的事情
這兩種實現造成下面的差異,即redis更容易實現多種數據結構,類似列表,集合,hash,有序集合等,由于是單線程的,如果單實例部署redis,不能全面用到服務器多核的優勢,通常部署時,都會通過多實例的方式去部署
6.內存管理
redis:redis沒有自己得內存池,而是直接使用時分配,即什么時候需要什么時候分配,內存管理的事交給內核,自己只負責取和釋放,直接malloc和free即可。內存管理沒有什么特殊的算法,通過使用google的jmalloc庫來做內存管理(申請,釋放)
memcache:memcached是有自己得內存池的,即預先分配一大塊內存,然后接下來分配內存就從內存池中分配,這樣可以減少內存分配的次數,提高效率,這也是大部分網絡服務器的實現方式,只不過各個內存池的管理方式根據具體情況而不同。使用了類似linux的內存管理,即slab內存管理方式。
7.其他
redis支持事務,頻道(發布-訂閱),集群;memcache不支持
二十六、apche 和 nginx 的優缺
nginx輕量級,比apache占用更少的內存及資源,抗并發
nginx處理請求是異步非阻塞的,而apache 則是阻塞型的,在高并發下nginx 能保持低資源低消耗高性能。
apache 相對于nginx 的優點:
rewrite比nginx 的rewrite 強大,少bug,穩定。(需要性能用nginx,求穩定就apache)。
二十七、一個函數的參數不能是對變量的引用,除非在php.ini中把 allow_call_time_pass_reference 設為on。
在PHP函數調用的時候,基本數據類型默認會使用值傳遞,而不是引用傳遞。allow_call_time_pass_reference 選項的作用為是否啟用在函數調用時強制參數被按照引用傳遞。如果把allow_call_time_pass_reference 配置為on,那么在函數調用的時候會默認使用引用傳值。但是不推薦使用這種方法,原因是該方法在未來的版本中很可能不再支持。如果想使用引用傳遞,那么推薦在函數調用的時候顯式地使用&進行引用傳遞。
二十八、什么是內存管理?
內存管理主要是指程序運行時對計算機內存資源的分配、使用和釋放等技術,內存管理的目標是高效、快速地分配內存同時及時地釋放和回收內存資源。內存管理主要包括是否有足夠的內存供程序使用,從內存池中獲取可用內存,使用后及時銷毀并重新分配給其他程序使用。
在PHP開發過程中,如果遇到大數組等操作,那么可能會造成內存溢出等問題。一些常見的處理方法如下:
1)通過ini_set(‘memory_limit’,‘64M’)方法重置php可以使用的內存大小,一般在遠程主機上是不能修改php.ini文件的,只能通過程序設置。注:在safe_mode(安全模式)下,ini_set會失效。
2)另一方面可以對數組進行分批處理,及時銷毀無用的變量,盡量減少靜態變量的使用,在需要數據重用時,可以考慮使用引用(&)。同時對于數據庫、文件操作完要及時關閉,對象使用完要及時調用析構函數等。
3)及時使用unset()函數釋放變量,使用時需要注意以下兩點:
① unset()函數只能在變量值占用內存空間超過256字節時才會釋放內存空間。
② 只有當指向該變量的所有變量都銷毀后,才能成功釋放內存。
二十九、Memcache的特征和特性
1)協議簡單。
2)基于libevent的事件處理。
3)內置內存存儲方式。
4)Memcached不互相通信的分布式。
(1)單個item 最大的數據為1MB。
(2)單進程最大的使用內存為2GB,需要更多內存時可開多個端口。
(3)Memcached是多線程,非阻塞io復用的網絡模型,Redis是單線程。
(4)鍵長最大為250字節。
三十、共享Session的方式
1)基于NFS的Session共享。NFS(Network File System)最早由Sun公司為解決Unix網絡主機間的目錄共享而研發。僅需將共享目錄服務器mount到其他服務器的本地session目錄即可。
2)基于數據庫的Session共享。
3)基于Cookie的Session共享。原理是將全站用戶的Session信息加密、序列化后以Cookie的方式,統一種植在根域名下(如:.host.com),利用瀏覽器訪問該根域名下的所有二級域名站點時,會傳遞與之域名對應的所有Cookie內容的特性,從而實現用戶的Cookie化Session 在多服務間的共享訪問。
4)基于緩存(Memcache)的Session共享。Memcache是一款基于Libevent多路異步I/O技術的內存共享系統,簡單的key + value數據存儲模式使得代碼邏輯小巧高效,因此在并發處理能力上占據了絕對優勢,目前能達到2000/s平均查詢,并且服務器CPU消耗依然不到10%。
三十一、memcache或redis雪崩如何解決?
造成原因:通常,在一個網站里,mysql數據庫處理的請求比較少(20%),負載80%,緩存技術處理大多數請求(80%)
如果memcache或redis掛掉,所有請求都會在mysql處理,數據庫的處理能力不足會直接宕機。這時候就算重啟緩存和mysql也是無濟于事的,因為緩存重啟后,數據已經丟失,數據請求還是會走mysql,mysql還是會死掉(死循環)
解決方法:
緩存預熱
1:先啟動緩存,再啟動數據庫。(但是此時不提供對外服務)
2:通過一個PHP腳本把常用的key寫入緩存中
3:開放對外服務【熱點數據已經緩存,請求會被緩存處理,減輕mysql壓力】
三十二、Redis持久化的方式?
1.Aof(append only file)
redis執行命令時,會把我們執行的命令通過日志形式進行追加。安全性高,但是影響性能。
2.Rdb
按照制定規則進行持久化
save 900 1 (900s內1次redis操作 會做一次持久化)
save 300 10 (300s內10次redis操作 會做一次持久化)
save 60 10000 (60s內10000次redis操作 會做一次持久化)
但是可能會存在數據丟失,比如:12:00做過一次持久化,正常的話,12:15會再做持久化,如果12:14緩存死掉,那么14分鐘的數據會丟失。不大安全,但是性能比aof好很多
三十三、Linux系統中,進程間通信的方式。
管道:
管道分為有名管道和無名管道
無名管道是一種半雙工的通信方式,數據只能單向流動,而且只能在具有親緣關系的進程間使用.進程的親緣關系一般指的是父子關系。無明管道一般用于兩個不同進程之間的通信。當一個進程創建了一個管道,并調用fork創建自己的一個子進程后,父進程關閉讀管道端,子進程關閉寫管道端,這樣提供了兩個進程之間數據流動的一種方式。
有名管道也是一種半雙工的通信方式,但是它允許無親緣關系進程間的通信。
消息隊列:
消息隊列是消息的鏈表,存放在內核中并由消息隊列標識符標識.消息隊列克服了信號傳遞信息少,管道只能承載無格式字節流以及緩沖區大小受限等特點.消息隊列是UNIX下不同進程之間可實現共享資源的一種機制,UNIX允許不同進程將格式化的數據流以消息隊列形式發送給任意進程.對消息隊列具有操作權限的進程都可以使用msget完成對消息隊列的操作控制.通過使用消息類型,進程可以按任何順序讀信息,或為消息安排優先級順序.
信號:
信號是一種比較復雜的通信方式,用于通知接收進程某個事件已經發生.
信號量:
信號量是一個計數器,可以用來控制多個線程對共享資源的訪問.,它不是用于交換大批數據,而用于多線程之間的同步.它常作為一種鎖機制,防止某進程在訪問資源時其它進程也訪問該資源.因此,主要作為進程間以及同一個進程內不同線程之間的同步手段.
共享內存:
共享內存就是映射一段能被其他進程所訪問的內存,這段共享內存由一個進程創建,但多個進程都可以訪問.共享內存是最快的IPC(進程間通信)方式,它是針對其它進程間通信方式運行效率低而專門設計的.它往往與其他通信機制,如信號量,配合使用,來實現進程間的同步與通信.
socket:
可用于不同及其間的進程通信
文件,互斥量等,不過我在swoole源碼中看到了通過eventfd這種方式做進程通信的
三十四、海量數據處理相關總結
1、海量日志數據,提取出某日訪問百度次數最多的那個IP。
算法思想:分而治之+Hash
IP地址最多有2^32=4G種取值情況,所以不能完全加載到內存中處理
可以考慮采用“分而治之”的思想,按照IP地址的Hash(IP)%1024值,把海量IP日志分別存儲到1024個小文件中。這樣,每個小文件最多包含4MB個IP地址
對于每一個小文件,可以構建一個IP為key,出現次數為value的Hash map,同時記錄當前出現次數最多的那個IP地址
可以得到1024個小文件中的出現次數最多的IP,再依據常規的排序算法得到總體上出現次數最多的IP
三十五、兩臺mysql服務器,其中一臺掛了,怎么讓業務端無感切換,并保證正常情況下講臺服務器的數據是一致的
不是核心業務的話,先停寫,把備機拉起來,查看兩臺機器的日志,進行數據補償,開寫。
如果是核心業務的話,現在所有的寫操作都在正常的狀態機器上。把好的這臺機器的備機拉起來,當主機。
備機的數據不一致怎么辦?
你要勇敢懟回去,你們每秒多少寫入操作。按照百萬級表,每秒1000的寫入效率,正常的設計是,分布在2臺機器上每臺500。這個級別的數據同步,出現差異的概率 可以忽略不計的。有一臺出現問題,另一臺也可以抗住。
三十六、redis是如何進行同步的,同步的方式,同步回滾怎么辦,數據異常怎么辦
redis 集群主從同步的簡單原理
Redis的復制功能是基于內存快照的持久化策略基礎上的,也就是說無論你的持久化策略選擇的是什么,只要用到了Redis的復制功能,就一定會有內存快照發生
當Slave啟動并連接到Master之后,它將主動發送一個SYNC命令( 首先Master會啟動一個后臺進程,將數據快照保存到文件中[rdb文件] Master 會給Slave 發送一個
Ping命令來判斷Slave的存活狀態 當存活時 Master會將數據文件發送給Slave 并將所有寫命令發送到Slave )。Slave首先會將數據文件保存到本地之后再將數據加載到內存中。
當第一次鏈接或者是故障后,重新連接都會先判斷Slave的存活狀態再做全部數據的同步,之后只會同步Master的寫操作(將命令發送給Slave)
問題:
當 Master 同步數據時 若數據量較大 而Master本身只會啟用一個后臺進程 來對多個Slave進行同步 , 這樣Master就會壓力過大 , 而且Slave 恢復的時間也會很慢!
redis 主從復制的優點:
(1)在一個Redis集群中,master負責寫請求,slave負責讀請求,這么做一方面通過將讀請求分散到其他機器從而大大減少了master服務器的壓力,另一方面slave專注于提供
讀服務從而提高了響應和讀取速度。
(2)在一個Redis集群中,如果master宕機,slave可以介入并取代master的位置,因此對于整個Redis服務來說不至于提供不了服務,這樣使得整個Redis服務足夠安全。
(3)水平增加Slave機器可以提高性能
三十七、如何解決跨域
JSONP
添加響應頭,允許跨域
代理的方式
三十八、寫出以下輸出
Q: "aa" == 1, "aa" == 0, 1 == "1", 1==="1", "12asdsad" + 1, "asdjkfgj12"+1
A: false, true, true, false, 13, 1
why:
php中 字符串==0 恒成立
php中 字符串和數字相加,如果字符串開頭是數字,則等于字符串開頭的數字(字符串第一個位置開始,到第一個非數字和.的位置截止)+數字
三十九、什么是服務容器、控制反轉(IoC)、依賴注入(DI)
服務容器是用來管理類依賴與運行依賴注入的工具。Laravel框架中就是使用服務容器來實現 控制反轉 和 依賴注入 。
控制反轉(IoC) 就是說把創建對象的 控制權 進行轉移,以前創建對象的主動權和創建時機是由自己把控的,而現在這種權力轉移到第三方,也就是 Laravel 中的容器。
依賴注入(DI)則是幫助容器實現在運行中動態的為對象提供提依賴的資源。
四十、Composer自動加載原理
composer加載核心思想是通過composer的配置文件在引用入口文件(autoload.php)時,將類和路徑的對應關系加載到內存中,最后將具體加載的實現注冊到spl_autoload_register函數中.最后將需要的文件包含進來.
四十一、一個請求到PHP,Nginx的主要過程。完整描述整個網絡請求過程,原理。
1)、FastCGI進程管理器php-fpm自身初始化,啟動主進程php-fpm和啟動start_servers個CGI 子進程。主進程php-fpm主要是管理fastcgi子進程,監聽9000端口。fastcgi子進程等待來自Web Server的連接。
2)、當客戶端請求到達Web Server Nginx是時,Nginx通過location指令,將所有以php為后綴的文件都交給127.0.0.1:9000來處理,即Nginx通過location指令,將所有以php為后綴的文件都交給127.0.0.1:9000來處理。
3)FastCGI進程管理器PHP-FPM選擇并連接到一個子進程CGI解釋器。Web server將CGI環境變量和標準輸入發送到FastCGI子進程。
4)、FastCGI子進程完成處理后將標準輸出和錯誤信息從同一連接返回Web Server。當FastCGI子進程關閉連接時,請求便告處理完成。
5)、FastCGI子進程接著等待并處理來自FastCGI進程管理器(運行在 WebServer中)的下一個連接。
四十二、PHP的魔術方法
__set() // 在給不可訪問屬性賦值時,__set()會被調用
__get() // 讀取不可訪問屬性的值時,__get()會被調用
__isset() //當對不可訪問屬性調用isset()或empty(),__isset()會被調用
__unset() // 當對不可訪問屬性調用unset()時,__unset()會被調用
__call() // 在對象中調用一個不可訪問方法時,__call()會被調用
__callStatic() // 在靜態上下文中調用一個不可訪問的方法時,__callStatic會被調用
__construct() // 構造函數的類會在每次創建新對象時先調用此方法,所以非常適合在使用對象之前做一些初始化工作。
__destruct() // 析構函數會在到某個對象的所有引用都被刪除或者當對象被顯式銷毀時執行。
__sleep() // serialize()函數會檢查類中是否存在一個魔術方法__sleep(),如果存在,該方法會先被調用,然后再執行序列化操作。此功能可以用于清理對象,并返回一個包含對象中所有應被序列化的變量名稱的數組。如果該方法未返回任何內容,則 NULL 被序列化,并產生一個 E_NOTICE 級別的錯誤。
__wakeup() // unserialize()函數會檢查是否存在一個__wakeup()方法,如果存在,則會先調用該方法,然后再執行反序列化操作。__wakeup() 經常用在反序列化操作中,例如重新建立數據庫連接,或執行其它初始化操作。
四十三、字符編碼UTF8、GBK、GB2312的區別。
utf8是國際編碼。通用性較好。
gbk是國內編碼。通用型較utf8差,但是占用數據庫比utf8小。
gb2312是一個簡體中文字符集的中國國家標準,共收錄6763個漢字。
四十四、MySQL默認的排序方式是什么
MyIsam存儲引擎:在沒有任何刪除,修改的操作下,執行select不帶order by那么會按照插入的順序下進行排序。
InnDB存儲引擎:在相同的情況下,select不帶order by會根據主鍵來排序,從小到大。
四十五、OSI七層網絡模型
物理層:建立、維護、斷開物理連接
數據鏈路層:建立邏輯鏈接、進行硬件地址尋址、差錯校驗等功能(SDLC、HDLC、PPP、STP)
網絡層:進行邏輯地址尋址,實現不同網絡之間的路徑選擇(IP、IPX、OSPF)
傳輸層:定義傳輸數據的協議端口號,以及流程和差錯校驗(TCP,UDP)數據包一旦離開網卡即進入網絡傳輸層
會話層:建立、管理、終止會話
表示層:數據的表示、安全、壓縮
應用層:網絡服務與最終用戶的一個接口;協議有:HTTP、FTP、TFTP、SMTP、DNS、TELNET、HTTPS、POP3、DHCP
PHP Redis 任務調度
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。