作者:PHP學習網 出處:https://www.viphper.com/?p=1236 本文版權歸作者,歡迎轉載,但未經作者同意必須保留此段宣告,且在文章頁面明顯位置給出原文連線,否則保留追究法律責任的權利。
公司出了一些自我評測的PHP題目,現將題目和答案記錄於此,以方便記憶。
1. 魔術函式有哪些,分別在什麼時候呼叫?
__construct(),類的建構函式
__destruct(),類的解構函式
__call(),在物件中呼叫一個不可訪問方法時呼叫
__callStatic(),用靜態方式中呼叫一個不可訪問方法時呼叫
__get(),獲得一個類的成員變數時呼叫
__set(),設定一個類的成員變數時呼叫
__isset(),當對不可訪問屬性呼叫isset()或empty()時呼叫
__unset(),當對不可訪問屬性呼叫unset()時被呼叫。
__sleep(),執行serialize()時,先會呼叫這個函式
__wakeup(),執行unserialize()時,先會呼叫這個函式
__toString(),類被當成字串時的回應方法
__invoke(),呼叫函式的方式呼叫一個物件時的回應方法
__set_state(),呼叫var_export()匯出類時,此靜態方法會被呼叫。
__clone(),當物件複製完成時呼叫
2.isset和empty函式有什麼區別?
PHP的isset()函式 一般用來檢測變數是否設定
格式:bool isset ( mixed var [, mixed var [, …]] )
功能:檢測變數是否設定
返回值:
若變數不存在則返回 FALSE
若變數存在且其值為NULL,也返回 FALSE
若變數存在且值不為NULL,則返回 TURE
同時檢查多個變數時,每個單項都符合上一條要求時才返回 TRUE,否則結果為 FALSE
版本:PHP 3, PHP 4, PHP 5
更多說明:
使用 unset() 釋放變數之後,它將不再是 isset()。
PHP函式isset()只能用於變數,傳遞任何其它引數都將造成解析錯誤。
檢測常量是否已設定可使用 defined() 函式。
PHP的empty()函式 判斷值為否為空
格式:bool empty ( mixed var )
功能:檢查一個變數是否為空
返回值:
若變數不存在則返回 TRUE
若變數存在且其值為””、0、”0″、NULL、、FALSE、array()、var $var; 以及沒有任何屬性的物件,則返回 TURE
若變數存在且值不為””、0、”0″、NULL、、FALSE、array()、var $var; 以及沒有任何屬性的物件,則返回 FALSE
版本:PHP 3, PHP 4, PHP 5
更多說明:
empty()的返回值=!(boolean) var,但不會因為變數未定義而產生警告資訊。參見轉換為布林值獲取更多資訊。
empty() 只能用於變數,傳遞任何其它引數都將造成Paser error而終止執行。
檢測常量是否已設定可使用 defined() 函式。
3.PHP的與定義變數有哪些,分別是什麼?
超全域性變數 — 超全域性變數是在全部作用域中始終可用的內建變數
$GLOBALS — 引用全域性作用域中可用的全部變數
$_SERVER — 伺服器和執行環境資訊
$_GET — HTTP GET 變數
$_POST — HTTP POST 變數
$_FILES — HTTP 檔案上傳變數
$_REQUEST — HTTP Request 變數
$_SESSION — Session 變數
$_ENV — 環境變數
$_COOKIE — HTTP Cookies
$php_errormsg — 前一個錯誤資訊
$HTTP_RAW_POST_DATA — 原生POST資料
$http_response_header — HTTP 響應頭
$argc — 傳遞給指令碼的引數數目
PHP 中的許多預定義變數都是“超全域性的”,這意味著它們在一個指令碼的全部作用域中都可用。在函式或方法中無需執行 global $variable; 就可以訪問它們。
這些超全域性變數是:
$GLOBALS
$_SERVER
$_GET
$_POST
$_FILES
$_COOKIE
$_SESSION
$_REQUEST
$_ENV
4.簡述PHP的垃圾回收機制
php 5.3之前使用的垃圾回收機制是單純的“引用計數”,也就是每個記憶體物件都分配一個計數器,當記憶體物件被變數引用時,計數器+1;當變數引用撤掉後,計數器-1;當計數器=0時,表明記憶體物件沒有被使用,該記憶體物件則進行銷燬,垃圾回收完成。
“引用計數”存在問題,就是當兩個或多個物件互相引用形成環狀後,記憶體物件的計數器則不會消減為0;這時候,這一組記憶體物件已經沒用了,但是不能回收,從而導致記憶體洩露;
php5.3開始,使用了新的垃圾回收機制,在引用計數基礎上,實現了一種複雜的演算法,來檢測記憶體物件中引用環的存在,以避免記憶體洩露。
php變數存在一個叫”zval”的變數容器中,”zval”變數容器包括含變數的型別和值,還包括額外的兩個位元組資訊,分別是“is_ref”表示變數是否屬於引用,“refcount”指向這個zval變數容器的變數個數。
5.列舉PHP的效能優化方法和技巧
opcache
通訊快取
查詢快取
6.MySQL儲存引擎中,innodb和myisam的區別
MyISAM 和 InnoDB 講解
InnoDB和MyISAM是許多人在使用MySQL時最常用的兩個表型別,這兩個表型別各有優劣,視具體應用而定。基本的差別為:MyISAM型別不支援事務處理等高階處理,而InnoDB型別支援。MyISAM型別的表強調的是效能,其執行數度比InnoDB型別更快,但是不提供事務支援,而InnoDB提供事務支援已經外部鍵等高階資料庫功能。
以下是一些細節和具體實現的差別:
◆1.InnoDB不支援FULLTEXT型別的索引。
◆2.InnoDB 中不儲存表的具體行數,也就是說,執行select count() from table時,InnoDB要掃描一遍整個表來計算有多少行,但是MyISAM只要簡單的讀出儲存好的行數即可。注意的是,當count()語句包含 where條件時,兩種表的操作是一樣的。
◆3.對於AUTO_INCREMENT型別的欄位,InnoDB中必須包含只有該欄位的索引,但是在MyISAM表中,可以和其他欄位一起建立聯合索引。
◆4.DELETE FROM table時,InnoDB不會重新建立表,而是一行一行的刪除。
◆5.LOAD TABLE FROM MASTER操作對InnoDB是不起作用的,解決方法是首先把InnoDB表改成MyISAM表,匯入資料後再改成InnoDB表,但是對於使用的額外的InnoDB特性(例如外來鍵)的表不適用。
另外,InnoDB表的行鎖也不是絕對的,假如在執行一個SQL語句時MySQL不能確定要掃描的範圍,InnoDB表同樣會鎖全表,例如update table set num=1 where name like “%aaa%”
兩種型別最主要的差別就是Innodb 支援事務處理與外來鍵和行級鎖.而MyISAM不支援.所以MyISAM往往就容易被人認為只適合在小專案中使用。
我作為使用MySQL的使用者角度出發,Innodb和MyISAM都是比較喜歡的,但是從我目前運維的資料庫平臺要達到需求:99.9%的穩定性,方便的擴充套件性和高可用性來說的話,MyISAM絕對是我的首選。
原因如下:
1、首先我目前平臺上承載的大部分專案是讀多寫少的專案,而MyISAM的讀效能是比Innodb強不少的。
2、MyISAM的索引和資料是分開的,並且索引是有壓縮的,記憶體使用率就對應提高了不少。能載入更多索引,而Innodb是索引和資料是緊密捆綁的,沒有使用壓縮從而會造成Innodb比MyISAM體積龐大不小。
3、從平臺角度來說,經常隔1,2個月就會發生應用開發人員不小心update一個表where寫的範圍不對,導致這個表沒法正常用了,這個時候MyISAM的優越性就體現出來了,隨便從當天拷貝的壓縮包取出對應表的檔案,隨便放到一個資料庫目錄下,然後dump成sql再導回到主庫,並把對應的binlog補上。如果是Innodb,恐怕不可能有這麼快速度,別和我說讓Innodb定期用匯出xxx.sql機制備份,因為我平臺上最小的一個資料庫例項的資料量基本都是幾十G大小。
4、從我接觸的應用邏輯來說,select count(*) 和order by 是最頻繁的,大概能佔了整個sql總語句的60%以上的操作,而這種操作Innodb其實也是會鎖表的,很多人以為Innodb是行級鎖,那個只是where對它主鍵是有效,非主鍵的都會鎖全表的。
5、還有就是經常有很多應用部門需要我給他們定期某些表的資料,MyISAM的話很方便,只要發給他們對應那表的frm.MYD,MYI的檔案,讓他們自己在對應版本的資料庫啟動就行,而Innodb就需要匯出xxx.sql了,因為光給別人檔案,受字典資料檔案的影響,對方是無法使用的。
6、如果和MyISAM比insert寫操作的話,Innodb還達不到MyISAM的寫效能,如果是針對基於索引的update操作,雖然MyISAM可能會遜色Innodb,但是那麼高併發的寫,從庫能否追的上也是一個問題,還不如通過多例項分庫分表架構來解決。
7、如果是用MyISAM的話,merge引擎可以大大加快應用部門的開發速度,他們只要對這個merge表做一些select count(*)操作,非常適合大專案總量約幾億的rows某一型別(如日誌,調查統計)的業務表。
當然Innodb也不是絕對不用,用事務的專案如模擬炒股專案,我就是用Innodb的,活躍使用者20多萬時候,也是很輕鬆應付了,因此我個人也是很喜歡Innodb的,只是如果從資料庫平臺應用出發,我還是會首選MyISAM。
另外,可能有人會說你MyISAM無法抗太多寫操作,但是我可以通過架構來彌補,說個我現有用的資料庫平臺容量:主從資料總量在幾百T以上,每天十多億 pv的動態頁面,還有幾個大專案是通過資料介面方式呼叫未算進pv總數,(其中包括一個大專案因為初期memcached沒部署,導致單臺資料庫每天處理 9千萬的查詢)。而我的整體資料庫伺服器平均負載都在0.5-1左右。
7.Mysql的儲存型別有哪幾種?什麼是聚簇索引非聚簇索引?
1、B+樹索引(O(log(n))):關於B+樹索引,可以參考 MySQL索引背後的資料結構及演算法原理
2、hash索引:
a 僅僅能滿足”=”,”IN”和”<=>”查詢,不能使用範圍查詢
b 其檢索效率非常高,索引的檢索可以一次定位,不像B-Tree 索引需要從根節點到枝節點,最後才能訪問到頁節點這樣多次的IO訪問,所以 Hash 索引的查詢效率要遠高於 B-Tree 索引
c 只有Memory儲存引擎顯示支援hash索引
3、FULLTEXT索引(現在MyISAM和InnoDB引擎都支援了)
4、R-Tree索引(用於對GIS資料型別建立SPATIAL索引)
從物理儲存角度
1、聚集索引(clustered index)
2、非聚集索引(non-clustered index)
從邏輯角度
1、主鍵索引:主鍵索引是一種特殊的唯一索引,不允許有空值
2、普通索引或者單列索引
3、多列索引(複合索引):複合索引指多個欄位上建立的索引,只有在查詢條件中使用了建立索引時的第一個欄位,索引才會被使用。使用複合索引時遵循最左字首集合
4、唯一索引或者非唯一索引
5、空間索引:空間索引是對空間資料型別的欄位建立的索引,MYSQL中的空間資料型別有4種,分別是GEOMETRY、POINT、LINESTRING、POLYGON。MYSQL使用SPATIAL關鍵字進行擴充套件,使得能夠用於建立正規索引型別的語法建立空間索引。建立空間索引的列,必須將其宣告為NOT NULL,空間索引只能在儲存引擎為MYISAM的表中建立
CREATE TABLE table_name[col_name data type]
unique|fulltext|spatialindex_name[asc|desc]
1、unique|fulltext|spatial為可選引數,分別表示唯一索引、全文索引和空間索引;
2、index和key為同義詞,兩者作用相同,用來指定建立索引
3、col_name為需要建立索引的欄位列,該列必須從資料表中該定義的多個列中選擇;
4、index_name指定索引的名稱,為可選引數,如果不指定,MYSQL預設col_name為索引值;
5、length為可選引數,表示索引的長度,只有字串型別的欄位才能指定索引長度;
6、asc或desc指定升序或降序的索引值儲存
8.Memcache和Redis的過期機制是什麼?什麼是一致性雜湊?
資料儲存方式:Slab Allocation
資料過期方式:Lazy Expiration + LRU
Slab Allocator的基本原理是按照預先規定的大小,將分配的記憶體分割成特定長度的塊,以完全解決記憶體碎片問題。
Slab Allocation的原理相當簡單。 將分配的記憶體分割成各種尺寸的塊(chuk),並把尺寸相同的塊分成組(chunk的集合)
Page:分配給Slab的記憶體空間,預設是1MB。分配給Slab之後根據slab的大小切分成chunk。
Chunk:用於快取記錄的記憶體空間。
Slab Class:特定大小的chunk的組。
memcached根據收到的資料的大小,選擇最適合資料大小的slab。
memcached中儲存著slab內空閒chunk的列表,根據該列表選擇chunk,然後將資料快取於其中。
Slab Alloction 缺點
這個問題就是,由於分配的是特定長度的記憶體,因此無法有效利用分配的記憶體。例如,將100位元組的資料快取到128位元組的chunk中,剩餘的28位元組就浪費了。
資料過期方式
Lazy Expiration
memcached內部不會監視記錄是否過期,而是在get時檢視記錄的時間戳,檢查記錄是否過期。這種技術被稱為lazy(惰性)expiration。因此,memcached不會在過期監視上耗費CPU時間
LRU
memcached會優先使用已超時的記錄的空間,但即使如此,也會發生追加新記錄時空間不足的情況,此時就要使用名為 Least Recently Used(LRU)機制來分配空間。這是刪除“最近最少使用”的記錄的機制。因此,當memcached的記憶體空間不足時(無法從slab class 獲取到新的空間時),就從最近未被使用的記錄中搜尋,並將其空間分配給新的記錄
大家常常說 memcached命中率低也是LRU策略引起的。大家可能常常遇到當我的記憶體足夠大的時候,為何還會觸發LRU那。因為LRU 是針對SLAB 來說的。
例如:我儲存的資料在100K 左右。內部會選擇適合大小的SLAB,這時候他會選擇合適他大小的,他會選擇上圖的SLBA CLASS 2. 如果這時候SLAB CLASS 2 滿了或者不足100K。他就會呼叫LRU機制。會把SLAB CLASS 2 中chunck中最近很少使用的資料清理掉,導致資料被清理掉,即使它沒有過期。
所以使用memcached 時候 一定要注意資料大小匹配模式和增長因子。
REDIS 過期時間機制
1.volatile-lru:從設定了過期時間的資料集中,選擇最近最久未使用的資料釋放
2.allkeys-lru:從資料集中(包括設定過期時間以及未設定過期時間的資料集中),選擇最近最久未使用的資料釋放
3.volatile-random:從設定了過期時間的資料集中,隨機選擇一個資料進行釋放
4.allkeys-random:從資料集中(包括了設定過期時間以及未設定過期時間)隨機選擇一個資料進行入釋放
5.volatile-ttl:從設定了過期時間的資料集中,選擇馬上就要過期的資料進行釋放操作
6.noeviction:不刪除任意資料(但redis還會根據引用計數器進行釋放呦~),這時如果記憶體不夠時,會直接返回錯誤
預設的記憶體策略是noeviction,在Redis中LRU演算法是一個近似演算法,預設情況下,Redis隨機挑選5個鍵,並且從中選取一個最近最久未使用的key進行淘汰,在配置檔案中可以通過maxmemory-samples的值來設定redis需要檢查key的個數,但是檢查的越多,耗費的時間也就越久,但是結構越精確(也就是Redis從記憶體中淘汰的物件未使用的時間也就越久~), 設定多少,具體業務權衡吧一般都是按照預設。
REDIS 還有定期策略,定期刪除過期的快取資料,來節省記憶體。這種方式還是蠻好的。這種策略優先於LRU。
目前對比MEMCACHED 和REDIS 過期時間機制對比。
REDIS 命中率明顯高於MEMCACHED,對於業務適合哪種場景,大家各自匹配吧!目前來說 我認為REDIS 是 MEMCACHED 補充的一款NOSQL 產品。
一致性雜湊,一種分散式節點key分佈演算法,可選;
9.MySQL索引底層資料結構是怎樣儲存的,為什麼使用索引會查詢的快?
資料結構及演算法基礎
索引的本質
B-Tree和B+Tree
特殊的儲存結構,尋道成本低;
MySQL索引實現
MyISAM索引實現
非聚簇索引
InnoDB索引實現
聚簇索引
第一個重大區別是InnoDB的資料檔案本身就是索引檔案。
第二個與MyISAM索引的不同是InnoDB的輔助索引data域儲存相應記錄主鍵的值而不是地址。
聚集索引這種實現方式使得按主鍵的搜尋十分高效,但是輔助索引搜尋需要檢索兩遍索引:首先檢索輔助索引獲得主鍵,然後用主鍵到主索引中檢索獲得記錄。
10.優化mysql的方法
避免複查查詢
避免模糊查詢
避免資料庫內運算
避免大量吞吐
儘可能縮小檢索範圍
儘可能使用索引,唯一或者接近唯一的索引
聯查中儘量使用const欄位
11.find 和 grep的區別
find是查詢檔案
grep是查詢檔案內的內容
12.寫出下列的服務的用途和預設埠
FTP: | 21/tcp | 依照FTP協議提供服務,專門用來傳輸檔案的協議。
SSH: | 22/tcp | 專為遠端登入會話和其他網路服務提供安全性的協議。利用 SSH 協議可以有效防止遠端管理過程中的資訊洩露問題。
HTTP: | 80/tcp | 是網際網路上應用最為廣泛的一種網路協議。所有的WWW檔案都必須遵守這個標準。
telnet:| 23/tcp | Telnet協議是TCP/IP協議族中的一員,是Internet遠端登陸服務的標準協議和主要方式,它為使用者提供了在本地計算機上完成遠端主機工作的能力
https:| 443/tcp 443/udp | 是以安全為目標的HTTP通道,簡單講是HTTP的安全版。即HTTP下加入SSL層,HTTPS的安全基礎是SSL,因此加密的詳細內容就需要SSL
13.給text.txt檔案除所有者之外增加執行許可權,最終以數字寫出檔案許可權
chmod g+x,o+x text.txt