2019PHP 面試彙總(code happy)

vio_xiaohei發表於2019-07-16

點關注,不迷路。。。。
持續更新ing
摘自:https://blog.csdn.net/weixin_39815001/arti...

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

一、秒殺(商品超賣,高併發,同一使用者多次搶購)
後端:redis+佇列
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/articl...

二十六、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/det...

三十八、兩臺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/5b7f0b662b717767...

雜項:
獲取客戶端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();
上面的方式會使用同一個資料庫連線,第二個引數為資料庫的連線引數,留空表示採用資料庫配置檔案的配置。

https://blog.csdn.net/weixin_39815001/arti...

    未完待續...................

相關文章