最新PHP 面試、筆試題彙總(code happy)

點關注,不迷路。。。。
持續更新ing

讀在前面:
面向對象編程和麪向對象設計的五個基本原則「SOLID」
單一職責原則(Single Responsibility Principle)
開放封閉原則(Open Closed Principle)
里氏替換原則(Liskov Substitution Principle)
接口隔離原則(Interface Segregation Principle)
依賴反轉原則(Dependency Inversion Principle)
1.單一職責原則規定一個類有且僅有一個理由使其改變。換句話說,一個類的邊界和職責應當是十分狹窄且集中的。我很喜歡的一句話"在類的職責問題上,無知是福"。一個類應當做它該做的事,並且不應當被它的任何依賴的變化所影響。
2.開放封閉原則,又稱開閉原則,規定代碼對擴展是開放的,對修改是封閉的。
3.里氏替換原則規定對象可以被其子類的實例所替換,並且不會影響到程序的正確性。
4.接口隔離原則規定,不應該強制接口的實現依賴於它不使用的方法。
5.依賴反轉原則,它規定高層次的代碼不應該依賴低層級的代碼。換句話說,高層次的代碼應該依賴抽象接口,抽象接口就像是「中間人」一樣,負責連接着高層次和低層次代碼。這個原則的另一層意思是,抽象接口不應該依賴具體實現,但具體實現應該依賴抽象接口

一、秒殺(商品超賣,高併發,同一用戶多次搶購)
後端:redis+隊列
Redis相關知識點彙總:https://blog.csdn.net/weixin_39815001/article/details/99586988
redis隊列實現,三個隊列(庫存隊列,排隊隊列,搶購結果隊列)
用戶先進入排隊隊列,先進先出,判斷是否已經在搶購結果隊列,如果在,則直接下一個,如果不在,將用戶信息加入搶購結果隊列,庫存-1,等待數據庫空閒時,將搶購結果寫入數據庫
前端:
面對高併發的搶購活動,前端常用的三板斧是【擴容】【靜態化】【限流】
擴容:加機器,這是最簡單的方法,通過增加前端池的整體承載量來抗峯值。
靜態化:將活動頁面上的所有可以靜態的元素全部靜態化,並儘量減少動態元素。通過CDN來抗峯值。
限流:一般都會採用IP級別的限流,即針對某一個IP,限制單位時間內發起請求數量。或者活動入口的時候增加遊戲或者問題環節進行消峯操作。
有損服務:在接近前端池承載能力的水位上限的時候,隨機拒絕部分請求來保護活動整體的可用性。

二、訂單模塊(同一訂單,多家商戶結算問題)
訂單拆分:用戶支付後,將訂單拆分,生成子訂單

三、用戶下單
先判斷有沒有登錄
點擊下單,生成唯一訂單號,狀態爲未支付

四、接口安全
使用HTTP的POST方式,對固定參數+附加參數進行數字簽名,使用的是md5加密,比如:我想通過標題獲取一個信息,在客戶端使用 信息標題+日期+雙方約定好的一個key通過md5加密生成一個簽名(sign),然後作爲參數傳遞到服務器端,服務器端使用同樣的方法進行校驗,如何接受過來的sign和我們通過算法算的值相同,證明是一個正常的接口請求,我們纔會返回相應的接口數據。

五、如何處理負載、高併發
1、HTML靜態化
其實大家都知道,效率最高、消耗最小的就是純靜態化的html頁面,所以我們儘可能使我們的 網站上的頁面採用靜態頁面來實現,這個最簡單的方法其實也是最有效的方法。
2、圖片服務器分離
把圖片單獨存儲,儘量減少圖片等大流量的開銷,可以放在一些相關的平臺上,如七牛雲
3、數據庫集羣和庫表散列及緩存
數據庫的併發連接爲100,一臺數據庫遠遠不夠,可以從讀寫分離、主從複製,數據庫集羣方面來着手。另外儘量減少數據庫的訪問,可以使用緩存數據庫如memcache、redis。
4、鏡像:
儘量減少下載,可以把不同的請求分發到多個鏡像端。
5、負載均衡:
Apache的最大併發連接爲1500,只能增加服務器,可以從硬件上着手,如F5服務器。當然硬件的成本比較高,我們往往從軟件方面着手。
負載均衡 (Load Balancing) 建立在現有網絡結構之上,它提供了一種廉價有效透明的方法擴展網絡設備和服務器的帶寬、增加吞吐量、加強網絡數據處理能力,同時能夠提高網絡的靈活性和可用性。目前使用最爲廣泛的負載均衡軟件是Nginx、LVS、HAProxy。我分別來說下三種的優缺點:
ps: 負載均衡 Nginx、LVS、HAProxy

六、修改會話的生存時間

1.在php.ini中 設置 session.gc_maxlifetime = 1440 //默認時間
2.代碼實現;
	$lifeTime = 24 * 3600; //保存一天
	session_set_cookie_params($lifeTime); 
	session_start();

七、PHP的垃圾收集機制
PHP可以自動進行內存管理,清除不再需要的對象。PHP使用了引用計數(referencecounting)這種單純的垃圾回收(garbagecollection)機制。每個對象都內含一個引用計數器,每個reference連接到對象,計數器加1。當reference離開生存空間或被設爲NULL,計數器減1。當某個對象的引用計數器爲零時,PHP知道你將不再需要使用這個對象,釋放其所佔的內存空間

八、正則的引擎
正則引擎主要可以分爲兩大類:一種是DFA,一種是NFA。
一般而論,DFA引擎則搜索更快一些。但是NFA以表達式爲主導,更容易操縱,因此一般程序員更偏愛NFA引擎!
可以使用是否支持忽略優先量詞和分組捕獲來判斷引擎類型:支持 NFA,不支持 DFA

九、對一個大文件進行逐行遍歷,如下方法性能較高的是?
寫一個實現了IteratorAggregate 接口的類,通過該類使用foreach遍歷。
(使用 IteratorAggregate 可將文件打開後通過移動指針的方式逐行遍歷,不受文件大小影響。使用 file_get_contents 處理大文件很容易導致PHP內存溢出;調用exec 會產生額外的進程,影響性能;其他人寫的類庫質量不一定高。)

十、讀取文件加鎖和解鎖

$fp = fopen("lock.txt","w+");
    if (flock($fp,LOCK_EX)) {
        //獲得寫鎖,寫數據
        fwrite($fp, "write something");
        // 解除鎖定
        flock($fp, LOCK_UN);
    } else {
        echo "file is locking...";
    }
    fclose($fp);

十一、array_merge() 數組合並函數
定義:array_merge() 函數把一個或多個數組合併爲一個數組。(您可以向函數輸入一個或者多個數組。)
註釋:如果兩個或更多個數組元素有相同的鍵名,則最後的元素會覆蓋其他元素。
如果兩個數組都是索引數組,則不會覆蓋
如果您僅向 array_merge() 函數輸入一個數組,且鍵名是整數,則該函數將返回帶有整數鍵名的新數組,其鍵名以 0 開始進行重新索引。
該函數與 array_merge_recursive() 函數之間的不同是在處理兩個或更多個數組元素有相同的鍵名的情況。array_merge_recursive() 不會進行鍵名覆蓋,而是將多個相同鍵名的值遞歸組成一個數組。
示例;

	 $a1=array("red","green");
    $a2=array("blue","yellow");
    $a3=array("CC","DD");

    $b1=array("a"=>"sa","b"=>"sb");
    $b2=array("a"=>"qa","b"=>"qb");
    $b3=array("a"=>"wa","c"=>"ww");
    
    print_r(array_merge($a1,$a2)); //Array ( [0] => red [1] => green [2] => blue [3] => yellow )
    print_r(array_merge($a1,$a2,$a3));  //Array ( [0] => red [1] => green [2] => blue [3] => yellow [4] => CC [5] => DD )
    print_r(array_merge($b1,$b2));  //Array ( [a] => qa [b] => qb )
    print_r(array_merge($b1,$b2,$a3));  // Array ( [a] => qa [b] => qb [0] => CC [1] => DD )
    print_r(array_merge($b1,$b2,$b3));  // Array ( [a] => wa [b] => qb [c] => ww )

十二、獲取文件擴展名

//plan A
function  get_ext(string $url){
	//$url = 'http://www.sina.com.cn/abc/de/fg.html?id=1&ajksfg&aakzsdfj';
	$a = parse_url($url); //Array ( [scheme] => http [host] => www.sina.com.cn [path] => /abc/de/fg.html [query] => id=1&ajksfg&aakzsdfj )
	$file = basename($a['path']);  //fg.html
	$b = explode('.',$file);
	return array_pop($b);
}
//plan B
function  get_ext(string $url){
	//$url = 'http://www.sina.com.cn/abc/de/fg.html?id=1&ajksfg&aakzsdfj';
	$a = basename($url); //fg.html?id=1&ajksfg&aakzsdfj
	$b = explode('?',$a);;  //Array ( [0] => fg.html [1] => id=1&ajksfg&aakzsdfj )
	$ext = explode('.',$b[0]);
	return array_pop($ext);
}

十三、遍歷一個文件夾下的所有文件和子文件夾

function my_scandir($dir){
	$files = array();
	if(is_dir($dir)){
		if ($handle = opendir($dir)){
			while (($file = readdir($handle))!= false){
				if ($file != "." && $file != "..") {
					if (is_dir($dir."/".$file)){
						$files[$file] = my_scandir($dir."/".$file);
					} else{
						$files[] = $dir."/".$file;
					}
				}
			}
			closedir($handle);
			return $files;
		}
	}
}

十四、編寫一個函數,遞歸遍歷,實現無限分類

function tree($arr,$pid=0,$level=0){
		static $list = array();
		foreach ($arr as $v) {
			//如果是頂級分類,則將其存到$list中,並以此節點爲根節點,遍歷其子節點
			if ($v['parent_id'] == $pid) {
				$v['level'] = $level;
				$list[] = $v;
				tree($arr,$v['cat_id'],$level+1);
			}
		}
		return $list;
	}

十五、獲取上月的最後一天

function get_last_month_last_day($date = ''){
		if ($date != '') {
			$time = strtotime($date);
		} else {
			$time = time();
		}
		$day = date('j',$time);//獲取該日期是當前月的第幾天
		return date('Y-m-d',strtotime("-{$day} days",$time));
	}

十六、php中WEB上傳文件的原理是什麼,如何限制上傳文件的大小?
上傳文件的表單使用post方式,並且要在form中添加enctype=‘multipart/form-data’。
一般可以加上隱藏域:,位置在file域前面。
value的值是上傳文件的客戶端字節限制。可以避免用戶在花時間等待上傳大文件之後才發現文件過大上傳失敗的麻煩。
使用file文件域來選擇要上傳的文件,當點擊提交按鈕之後,文件會被上傳到服務器中的臨時目錄,在腳本運行結束時會被銷燬,所以應該在腳本結束之前,將其移動到服務器上的某個目錄下,可以通過函數move_uploaded_file()來移動臨時文件,要獲取臨時文件的信息,使用$_FILES。
限制上傳文件大小的因素有:
客戶端的隱藏域MAX_FILE_SIZE的數值(可以被繞開)。
服務器端的upload_max_filesize,post_max_size和memory_limit。這幾項不能夠用腳本來設置。
自定義文件大小限制邏輯。即使服務器的限制是能自己決定,也會有需要個別考慮的情況。所以這個限制方式經常是必要的。

十七、雙引號和單引號的區別
雙引號解釋變量,單引號不解釋變量
雙引號裏插入單引號,其中單引號裏如果有變量的話,變量解釋
雙引號的變量名後面必須要有一個非數字、字母、下劃線的特殊字符,或者用{}講變量括起來,否則會將變量名後面的部分當做一個整體,引起語法錯誤
雙引號解釋轉義字符,單引號不解釋轉義字符,但是解釋’\和\
能使單引號字符儘量使用單引號,單引號的效率比雙引號要高(因爲雙引號要先遍歷一遍,判斷裏面有沒有變量,然後再進行操作,而單引號則不需要判斷)

十八、常用的超全局變量
$_GET ----->get傳送方式
$_POST ----->post傳送方式
$_REQUEST ----->可以接收到get和post兩種方式的值
$GLOBALS ----->所有的變量都放在裏面
$_FILES ----->上傳文件使用
$_SERVER ----->系統環境變量
$_SESSION ----->會話控制的時候會用到
$_COOKIE ----->會話控制的時候會用到

十九、echo、print_r、print、var_dump之間的區別
* echo、print是php語句,var_dump和print_r是函數
* echo 輸出一個或多個字符串,中間以逗號隔開,沒有返回值是語言結構而不是真正的函數,因此不能作爲表達式的一部分使用
* print也是php的一個關鍵字,有返回值 只能打印出簡單類型變量的值(如int,string),如果字符串顯示成功則返回true,否則返回false
* print_r 可以打印出複雜類型變量的值(如數組、對象)以列表的形式顯示,並以array、object開頭,但print_r輸出布爾值和NULL的結果沒有意義,因爲都是打印"\n",因此var_dump()函數更適合調試
* var_dump() 判斷一個變量的類型和長度,並輸出變量的數值

二十、對於大流量網站,採用什麼方法來解決訪問量的問題
確認服務器硬件是否能夠支持當前的流量
數據庫讀寫分離,優化數據表
優化SQL語句
禁止外部盜鏈
控制大文件的下載
使用不同主機分流主要流量
使用流量分析統計

二十一、語句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不支持
ps:https://cloud.tencent.com/developer/article/1004377

二十六、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這種方式做進程通信的

三十四、HTTP Header 詳解

三十五、TCP 三次握手和四次揮手

三十六、 Select、Poll、Epoll
大話 Select、Poll、Epoll

三十七、海量數據處理相關總結
1、海量日誌數據,提取出某日訪問百度次數最多的那個IP。
算法思想:分而治之+Hash
IP地址最多有2^32=4G種取值情況,所以不能完全加載到內存中處理
可以考慮採用“分而治之”的思想,按照IP地址的Hash(IP)%1024值,把海量IP日誌分別存儲到1024個小文件中。這樣,每個小文件最多包含4MB個IP地址
對於每一個小文件,可以構建一個IP爲key,出現次數爲value的Hash map,同時記錄當前出現次數最多的那個IP地址
可以得到1024個小文件中的出現次數最多的IP,再依據常規的排序算法得到總體上出現次數最多的IP
2… PS:https://blog.csdn.net/v_JULY_v/article/details/6279498

三十八、兩臺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

四十九、找出數組中出現一次的元素。10 10 11 11 12 13 12 13 16 只出現一次的數字。要求時間複雜度儘可能低

// 方法一
function onlyOne($arr) {
	$res = 0;
	for ($i = 0; $i < count($arr); $i++) {
		$res ^= $arr[$i];
	}
	
   return $res;
}
// 方法二
function onlyOne2($arr) {
	$m = array_count_values($arr);
	foreach ($m as $k => $v) {
	  if ($v == 1) {
		return $k;
	  }
	}
	return 0;
}

五十、LRU算法
如果一個 數據在最近一段時間沒有被訪問到,那麼在將來它被訪問的可能性也很小(https://www.twblogs.net/a/5b7f0b662b717767c6ad6c42/zh-cn)

雜項:
獲取客戶端IP
沒有使用代理
$_SERVER[‘REMOTE_ADDR’] 或者 getenv(‘REMOTE_ADDR’)
使用透明代理
$_SERVER[‘HTTP_X_FORWARDED_FOR’];

獲取服務端IP
$_SERVER[‘SERVER_ADDR’] 或者 gethostbyname(‘www.baidu.com’);

將IP地址轉換成int

ip2long($ip);  

好處:存儲時可以直接存有符號int型,只需要4字節(節約空間)
存char類型需要15個字節
int轉換成ip

long2ip($int);

獲取當前時間戳

time()

打印前一天的時間

date('Y-m-d H:i:s',strtotime('-1 day'))

GB2312格式的字符串裝換成UTF-8格式

iconv('GB2312','UTF-8','悄悄是別離的笙簫');

字符串轉數組

explode(',',$str)

創建一個每週三01:00~04:00每3分鐘執行執行一次的crontab指令

*/3 1-4 * * 3 /bin/bash /home/sijiaomao/ok.sh

php兩數組相加
兩個數組相加,若數組中存在相同鍵值的元素,則只保留第一個數組的元素

設置時區

	date_default_timezone_set("Asia/Shanghai");

在url中用get傳值的時候,若中文出現亂碼,應該用哪個函數對中文進行編碼?
urlencode() 解碼用urldecode()

PHP常用擴展
curl、iconv、json、mbstring、mysqli、PDO、hash、openssl、sockets、redis

php八種數據類型
數據類型分爲三種:
標量數據類型:boolean、string、integer、double
複合數據類型:array、object
特殊數據類型:resource、null

php進程模型,php怎麼支持多個併發
守護進程模型:https://www.jianshu.com/p/542935a3bfa8

nginx的進程模型,怎麼支持多個併發
https://www.zhihu.com/question/22062795

php-fpm各配置含義,fpm的daemonize模式
http://www.4wei.cn/archives/1002061

查看PHP進程當前使用的內存
memory_get_usage()

查看系統分配的內存
memory_get_peak_usage()
unset()可以釋放內存,當處理完數據後 unset 掉,只能釋放當前使用的內存,系統分配的內存並不會變小
內存被分劃爲, “已使用” 和 “空閒”, unset 只會把 “已使用” 變爲 “空閒”, 下次內存請求時會先去"空閒"裏取,
程序結束, GC 纔會釋放全部內存

參數綁定可以避免 SQL 注入攻擊

		例如:$users = DB::select('select * from users where username = ? and passwd = ?', [$username,$passwd]);

除了使用 ? 佔位符來代表參數綁定外,還可以使用命名綁定來執行查詢:

		$results = DB::select('select * from users where id = :id', ['id' => 1]);

thinkphp5.0鏈接數據庫
使用db助手函數默認每次都會重新連接數據庫,而使用Db::name或者Db::table方法的話都是單例的
db函數如果需要採用相同的鏈接,可以傳入第三個參數,例如:
db(‘user’,[],false)->where(‘id’,1)->find();
db(‘user’,[],false)->where(‘status’,1)->select();
上面的方式會使用同一個數據庫連接,第二個參數爲數據庫的連接參數,留空表示採用數據庫配置文件的配置。

PHP預定義變量(詳見:https://www.php.net/manual/zh/reserved.variables.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 — 傳遞給腳本的參數數目
	$argv — 傳遞給腳本的參數數組

count()和sizeof()的區別
兩個函數都是用於獲取數組的長度,sizeof()用法和count()完全一致
在這裏插入圖片描述
沒有區別,count()是sizeof()的別名

mysql中INT和BIGINT的區別?
如果使用INT自增類型,那麼當一張表的記錄數超過2147483647(約21億)時,會達到上限而出錯。使用BIGINT自增類型則可以最多約922億億條記錄。
mysql聚合函數返回值?
如果聚合查詢的WHERE條件沒有匹配到任何行,COUNT()會返回0,而SUM()、AVG()、MAX()和MIN()會返回NULL
SELECT AVG(score) average FROM students WHERE gender = ‘X’;
總共十條記錄,每頁3條記錄,如何通過聚合查詢獲得總頁數?
SELECT CEILING(COUNT(*) / 3) FROM students; //CEILING()向上取整
使用一條SELECT查詢查出每個班級的平均分(四捨五入取整): ceiling(),四捨五入取整
SELECT class_id,ceiling(AVG(score)) from students GROUP BY class_id;
請使用一條SELECT查詢查出每個班級男生和女生的平均分:
select class_id,gender,AVG(score) as avgr from students GROUP BY class_id,gender ORDER BY avgr;

相關優秀文章:
從B樹、B+樹、B*樹談MySQL索引
排序——讀《數據結構與算法分析》有感
Redis知識點(redis面試,一文足矣)
MySQL優化之——查詢優化
PHP MYSQL 優秀文章 彙總

未完待續…

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章