面試10家公司,收穫9個offer,2020年PHP 面試問題

職場 發佈 2020-08-08T21:28:29+00:00

出於一些原因近期做了一次工作變動,在職交接近一個半月時間大概面試了十家公司,並且得到了自己比較滿意的offer,最後基本上無縫銜接了新工作。

出於一些原因近期做了一次工作變動,在職交接近一個半月時間大概面試了十家公司,並且得到了自己比較滿意的offer,最後基本上無縫銜接了新工作。總體來說,雖然準備的很充分,但面試期間還是暴露了許多問題,所以做下總結,供大家和自己以後參考,主要分四部分講述: 簡歷方面,格式內容包括七個板塊,個人簡介,求職意向,工作經歷,項目經歷,技能描述,學歷背景,自我評價。如果自己或公司沒有其他特殊要求,這些一般就夠了,具體格式不再贅述。

如果喜歡我的文章,想與一群資深開發者一起交流學習的話,獲取更多相關大廠面試諮詢和指導,點擊此處中間位置有獲取地址

總結幾個要素:

  1. 個人簡介名字大寫,內容需要詳實,一是可以給人留下映像,二是減少不必要的與面試官交換個人信息的時間。準備一份好的口頭自我介紹是很有必要的,畢竟準備一次能用很久,時間花在上面很實用,面外企英文版的最好也提前準備下。
  2. 簡歷上不要寫上期望薪資,能夠根據面試情況變化是最好的,如果寫上建議高於自身期望,詳細參考錨定效應。
  3. 簡歷要簡潔,最好不要超過兩頁。項目經歷要突出重點(可以具體到某次解決線上問題,某次優化效率提升),兩到三個為宜,不重要的可以放在工作經歷中一筆帶過。這樣有個好處,即面試官根據項目問的問題就會很集中,在你的預料之中,如果你的項目誇誇    其談寫了很多,那面試官發揮起來,你就容易被帶著走。
  4. 很多人不重視個人評價欄目,我的技巧是評價最後中帶上自己的博客,個人項目,因為在尾部還是很容易被看到並當做加分項的。

面試流程,其實每個公司大同小異,電話面試,筆試,技術面(可能兩面),Hr面,部門經理面,可能不同公司有稍微做調整。

這裡需要強調兩點:

  1.電話面試,很多大公司都會有電話面試,有些朋友接到面試不管當前情況如何,環境如何都會爭取這個機會,而我想說的是,如果身邊環境尚可接了也就接了,但是如果身處鬧市,或者下班回家地鐵上信號不好,或者自己完全沒有準備,建議直接回復面試官目前不   合適,改約其他時間,這麼做好處一是沒有環境影響,二是自己有心理準備。

  2.抓住機會問問題,如果對技術有追求一定要向技術官問清楚項目所使用技術,問開發人員上下班時間。向HR問清楚公司的薪酬福利體系,決定自己開價。向管理層問清楚項目目前所處的階段,以及規劃方向。 面試題概覽,基本上匯總了這次面試中遇到的所有問題,中間也有一些是自己當時沒有答上來的,這裡只做羅列:

1.get,post 的區別

1、GET在瀏覽器回退時是無害的,而POST會再次提交請求。
2、GET產生的URL地址可以被Bookmark,而POST不可以。
3、GET請求會被瀏覽器主動cache,而POST不會,除非手動設置。
4、GET請求只能進行url編碼,而POST支持多種編碼方式。
5、GET請求參數會被完整保留在瀏覽器歷史記錄里,而POST中的參數不會被保留。
6、GET請求在URL中傳送的參數是有長度限制的,而POST沒有。
7、對參數的數據類型,GET只接受ASCII字符,而POST沒有限制。
8、GET比POST更不安全,因為參數直接暴露在URL上,所以不能用來傳遞敏感信息。
9、GET參數通過URL傳遞,POST放在Request body中。
10、GET產生一個TCP數據包,POST產生兩個TCP數據包

2.require,include 區別

require是無條件包含也就是如果一個流程里加入require,無論條件成立與否都會先執行require include有返回值,而require沒有(可能因為如此require的速度比include快) 包含文件不存在或者語法錯誤的時候require是致命的錯誤終止執行,include不是

3.PHP 的垃圾回收機制

PHP 可以自動進行內存管理,清除不需要的對象。
PHP 使用了引用計數 (reference counting) GC 機制。
每個對象都內含一個引用計數器 refcount,每個 reference 連接到對象,計數器加 1。當 reference 離開生存空間或被設為 NULL,計數器減 1。當某個對象的引用計數器為零時,PHP 知道你將不再需要使用這個對象,釋放其所占的內存空間。

4.常見的排序算法

1. 冒泡排序

思路分析:在要排序的一組數中,對當前還未排好的序列,從前往後對相鄰的兩個數依次進行比較和調整,讓較大的數往下沉,較小的往上冒。即,每當兩相鄰的數比較後發現它們的排序與排序要求相反時,就將它們互換。

代碼實現:

$arr=array(1,43,54,62,21,66,32,78,36,76,39);  
function bubbleSort($arr)
{  
  $len=count($arr);
  //該層循環控制 需要冒泡的輪數
  for($i=0;$i<$len-1;$i++)
  { //該層循環用來控制每輪 冒出一個數 需要比較的次數
    for($k=0;$k<$len-$i-1;$k++)
    {
       if($arr[$k]>$arr[$k+1])
        {
            $tmp=$arr[$k+1];
            $arr[$k+1]=$arr[$k];
            $arr[$k]=$tmp;
        }
    }
  }
  return $arr;
}

2. 選擇排序思路分析:在要排序的一組數中,選出最小的一個數與第一個位置的數交換。然後在剩下的數當中再找最小的與第二個位置的數交換,如此循環到倒數第二個數和最後一個數比較為止。

代碼實現:

function selectSort($arr) {
//雙重循環完成,外層控制輪數,內層控制比較次數
 $len=count($arr);
    for($i=0; $i<$len-1; $i++) {
        //先假設最小的值的位置
        $p = $i;

        for($j=$i+1; $j<$len; $j++) {
            //$arr[$p] 是當前已知的最小值
            if($arr[$p] > $arr[$j]) {
            //比較,發現更小的,記錄下最小值的位置;並且在下次比較時採用已知的最小值進行比較。
                $p = $j;
            }
        }
        //已經確定了當前的最小值的位置,保存到$p中。如果發現最小值的位置與當前假設的位置$i不同,則位置互換即可。
        if($p != $i) {
            $tmp = $arr[$p];
            $arr[$p] = $arr[$i];
            $arr[$i] = $tmp;
        }
    }
    //返回最終結果
    return $arr;
}

3.插入排序思路分析:在要排序的一組數中,假設前面的數已經是排好順序的,現在要把第n個數插到前面的有序數中,使得這n個數也是排好順序的。如此反覆循環,直到全部排好順序。

代碼實現:

function insertSort($arr) {
    $len=count($arr); 
    for($i=1, $i<$len; $i++) {
        $tmp = $arr[$i];
        //內層循環控制,比較並插入
        for($j=$i-1;$j>=0;$j--) {
            if($tmp < $arr[$j]) {
                //發現插入的元素要小,交換位置,將後邊的元素與前面的元素互換
                $arr[$j+1] = $arr[$j];
                $arr[$j] = $tmp;
            } else {
                //如果碰到不需要移動的元素,由於是已經排序好是數組,則前面的就不需要再次比較了。
                break;
            }
        }
    }
    return $arr;
}

4.快速排序

思路分析:選擇一個基準元素,通常選擇第一個元素或者最後一個元素。通過一趟掃描,將待排序列分成兩部分,一部分比基準元素小,一部分大於等於基準元素。此時基準元素在其排好序後的正確位置,然後再用同樣的方法遞歸地排序劃分的兩部分。

代碼實現:

function quickSort($arr) {
    //先判斷是否需要繼續進行
    $length = count($arr);
    if($length <= 1) {
        return $arr;
    }
    //選擇第一個元素作為基準
    $base_num = $arr[0];
    //遍歷除了標尺外的所有元素,按照大小關係放入兩個數組內
    //初始化兩個數組
    $left_array = array();  //小於基準的
    $right_array = array();  //大於基準的
    for($i=1; $i<$length; $i++) {
        if($base_num > $arr[$i]) {
            //放入左邊數組
            $left_array[] = $arr[$i];
        } else {
            //放入右邊
            $right_array[] = $arr[$i];
        }
    }
    //再分別對左邊和右邊的數組進行相同的排序處理方式遞歸調用這個函數
    $left_array = quick_sort($left_array);
    $right_array = quick_sort($right_array);
    //合併
    return array_merge($left_array, array($base_num), $right_array);
}

5、給出一個字符串,返回裡面連續字母的個數,比如:abbcddde,返回 1a2b1c3de;代碼實現:

public function str($str)
    {
        $re = '';
        $arr = str_split($str);//把字符串變成數組,開始我想到的是用for循環來處理,這個函數同事提醒了才發現
        $key = 0; //key 用來記錄下標,為了方便計算前面的數字
        for ($i = 0; $i < count($arr); $i++) {
            $v = $arr[$i];
            if ($arr[$i] == $arr[$i + 1]) {
                continue;//如果當前的值和下一個值相等,跳出當前循環,進入下一個
            } else {
                $re  .= ($i - $key + 1) . $v; //不相等時計算出前面的數字,
                $key = $i + 1;// 同時 key 下標重新複製
            }
        }

        return $re;
    }

6、約瑟夫環問題,猴子選大王

一群猴子排成一圈,按1,2,…,n依次編號。然後從第1隻開始數,數到第m只,把它踢出圈,從它後面再開始數,再數到第m只,在把它踢出去…,如此不停的進行下去,直到最後只剩下一隻猴子為止,那隻猴子就叫做大王。要求編程模擬此過程,輸入m、n, 輸出最後那個大王的編號。用程序模擬該過程。

unction mk($n ,$m){
        $arr = range(1,$n);//構造一個數組
        $i = 1; //從第一個開始循環
        while(count($arr)>1){ //如果總數大於1
            ($i % $m != 0) && array_push($arr,$arr[$i-1]);//不被踢出則壓入數組尾部
            unset($arr[$i-1]);//壓入數組然後刪除
            $i++;//繼續循環
        }  
        return $arr[$i-1]; //直至最後剩下一個為大王 
}
print_r(mk(6,8));   //第3隻為大王


一.什麼是 CGI?什麼是 FastCGI?php-fpm,FastCGI,Nginx 之間是什麼關係?

CGI,通用網關接口,用於WEB伺服器和應用程式間的交互,定義輸入輸出規範,用戶的請求通過WEB伺服器轉發給FastCGI進程,FastCGI進程再調用應用程式進行處理,如php解析器,應用程式的處理結果如html返回給FastCGI,FastCGI返回給Nginx 進行輸出。假設這裡WEB伺服器是Nginx,應用程式是 PHP,而 php-fpm 是管理 FastCGI 的,這也就是 php-fpm,FastCGI,和 Nginx 之間的關係。
FastCGI 用來提高 cgi 程序性能,啟動一個master,再啟動多個 worker,不需要每次解析 php.ini. 而 php-fpm 實現了 FastCGI 協議,是 FastCGI 的進程管理器,支持平滑重啟,可以啟動的時候預先生成多個進程。

二.memcache 和 Redis 的區別

數據結構:memcache僅支持簡單的key-value形式,Redis支持的數據更多(string字符串,set集合,list列表,hash散列,zset有序集合);

多線程:memcache支持多線程,Redis支持單線程

持久化:Redis支持持久化,memcache不支持持久化

分布式:Redis做主從結構,memcache伺服器需要通過hash一致化來支撐主從結構

實際運用中可以redis,memcache結合,memcache可作為session存儲的方式,session都是KV類型鍵值對。

1. Redis中,並不是所有的數據都一直存儲在內存中的,這是和Memcache相比一個最大的區別。

2. Redis在很多方面具備資料庫的特徵,或者說就是一個資料庫系統,而Memcache只是簡單的K/V緩存。

3. 他們的擴展都需要做集群;實現方式:master-slave、Hash。

4. 在100k以上的數據中,Memcache性能要高於Redis。

5. 如果要說內存使用效率,使用簡單的key-value存儲的話,Memcached的內存利用率更高,而如果Redis採用hash結構來做key-value存儲,由於其組合式的壓縮,其內存利用率會高於Memcache。當然,這和你的應用場景和數據特性有關。

6. 如果你對數據持久化和數據同步有所要求,那麼推薦你選擇Redis,因為這兩個特性Memcache都不具備。即使你只是希望在升級或者重啟系統後緩存數據不會丟失,選擇Redis也是明智的。

7. Redis和Memcache在寫入性能上面差別不大,讀取性能上面尤其是批量讀取性能上面Memcache更強

8.Redis 提供了多種不同級別的持久化方式:

RDB 持久化可以在指定的時間間隔內生成數據集的時間點快照(point-in-time snapshot)。

AOF 持久化記錄伺服器執行的所有寫操作命令,並在伺服器啟動時,通過重新執行這些命令來還原數據集。 AOF 文件中的命令全部以 Redis 協議的格式來保存,新命令會被追加到文件的末尾。 Redis 還可以在後台對 AOF 文件進行重寫(rewrite),使得 AOF 文件的體積不會超出保存數據集狀態所需的實際大小。

Redis 還可以同時使用 AOF 持久化和 RDB 持久化。 在這種情況下, 當 Redis 重啟時, 它會優先使用 AOF 文件來還原數據集, 因為 AOF 文件保存的數據集通常比 RDB 文件所保存的數據集更完整。

你甚至可以關閉持久化功能,讓數據只在伺服器運行時存在。

三.什麼是 Redis 穿透和雪崩

**緩存穿透**:就是訪問redis中一個不存在的key的時候,會直接穿過緩存,去資料庫中進行查詢.

如果是黑客,進行惡意攻擊的時候,每次都請求超過2000個/秒的時候,這個時候mysql基本上就掛了.

解決辦法是:每次從資料庫中查詢到一個不存在的key的時候,就寫一個空值到緩存庫中,有惡意攻擊的時候,直接從緩存中取到這個空值.

**緩存雪崩**:就是每秒有5000個請求過來時候,redis緩存庫崩了,然後這些請求瞬間落在了mysql資料庫上,直接導致資料庫死機.

解決方案就是:  事前:提高緩存庫的高可用, 使用主從結構加哨兵 cluster集群,

事中:使用ehcache+hystrix限流組件(當請求量非常巨大的時候,就調用自己開發好的一個降級餓組件,返回一些默認值,如友情提示,或者空白值)

事後:做持久化,儘快恢復緩存集群,一旦恢復,自動從磁碟上讀取數據,恢復內存中的數據.

四.redis 消息隊列先進先出需要注意什麼?

通常使用一個list來實現隊列操作,這樣有一個小限制,所以的任務統一都是先進先出,如果想優先處理某個任務就不太好處理了,這就需要讓隊列有優先級的概念,我們就可以優先處理高級別的任務,實現方式有以下幾種方式:

1)單一列表實現:隊列正常的操作是 左進右出(lpush,rpop)為了先處理高優先級任務,在遇到高級別任務時,可以直接插隊,直接放入隊列頭部(rpush),這樣,從隊列頭部(右側)獲取任務時,取到的就是高優先級的任務(rpop)

2)使用兩個隊列,一個普通隊列,一個高級隊列,針對任務的級別放入不同的隊列,獲取任務時也很簡單,redis的BRPOP命令可以按順序從多個隊列中取值,BRPOP會按照給出的 key 順序查看,並在找到的第一個非空 list 的尾部彈出一個元素,redis> BRPOP list1 list2 0

`list1 做為高優先級任務隊列`

`list2 做為普通任務隊列`

`這樣就實現了先處理高優先級任務,當沒有高優先級任務時,就去獲取普通任務`

`方式1最簡單,但實際應用比較局限,方式3可以實現複雜優先級,但實現比較複雜,不利於維護`

`方式2是推薦用法,實際應用最為合適`

五.Redis 如何防止高並發?

其實redis是不會存在並發問題的,因為他是單進程的,再多的命令都是一個接一個地執行的。我們使用的時候,可能會出現並發問題,比如獲得和設定這一對。Redis的為什麼 有高並發問題?Redis的的出身決定

Redis是一種單線程機制的nosql資料庫,基於key-value,數據可持久化落盤。由於單線程所以redis本身並沒有鎖的概念,多個客戶端連接並不存在競爭關係,但是利用jedis等客戶端對redis進行並發訪問時會出現問題。發生連接超時、數據轉換錯誤、阻塞、客戶端關閉連接等問題,這些問題均是由於客戶端連接混亂造成。

同時,單線程的天性決定,高並發對同一個鍵的操作會排隊處理,如果並發量很大,可能造成後來的請求超時。在遠程訪問redis的時候,因為網絡等原因造成高並發訪問延遲返回的問題。

解決辦法在客戶端將連接進行池化,同時對客戶端讀寫Redis操作採用內部鎖synchronized。

伺服器角度,利用setnx變向實現鎖機制。

六.說說對 SQL 語句優化有哪些方法?

(1)Where子句中:where表之間的連接必須寫在其他Where條件之前,那些可以過濾掉最大數量記錄的條件必須寫在Where子句的末尾.HAVING最後。

(2)用EXISTS替代IN、用NOT EXISTS替代NOT IN。

(3) 避免在索引列上使用計算

(4)避免在索引列上使用IS NULL和IS NOT NULL

(5)對查詢進行優化,應儘量避免全表掃描,首先應考慮在 where 及 order by 涉及的列上建立索引。  

(6)應儘量避免在 where 子句中對欄位進行 null 值判斷,否則將導致引擎放棄使用索引而進行全表掃描

(7)應儘量避免在 where 子句中對欄位進行表達式操作,這將導致引擎放棄使用索引而進行全表掃描

一.資料庫三範式

第一範式:1NF是對屬性的原子性約束,要求屬性具有原子性,不可再分解;

第二範式:2NF是對記錄的惟一性約束,要求記錄有惟一標識,即實體的惟一性;

第三範式:3NF是對欄位冗餘性的約束,即任何欄位不能由其他欄位派生出來,它要求欄位沒有冗餘。

範式化設計優缺點:

優點:

可以儘量得減少數據冗餘,使得更新快,體積小

缺點:對於查詢需要多個表進行關聯,減少寫得效率增加讀得效率,更難進行索引優化

反範式化:

優點:可以減少表得關聯,可以更好得進行索引優化

缺點:數據冗餘以及數據異常,數據得修改需要更多的成本

二.Mysql 中有哪幾種鎖

- MyISAM支持表鎖,InnoDB支持表鎖和行鎖,默認為行鎖
- 表級鎖:開銷小,加鎖快,不會出現死鎖。鎖定粒度大,發生鎖衝突的機率最高,並發量最低
- 行級鎖:開銷大,加鎖慢,會出現死鎖。鎖力度小,發生鎖衝突的機率小,並發度最高

三.什麼是存儲過程

我們常用的操作資料庫語言SQL語句在執行的時候需要要先編譯,然後執行,而存儲過程(Stored Procedure)是一組為了完成特定功能的SQL語句集,經編譯後存儲在資料庫中,用戶通過指定存儲過程的名字並給定參數(如果該存儲過程帶有參數)來調用執行它。

一個存儲過程是一個可編程的函數,它在資料庫中創建並保存。它可以有SQL語句和一些特殊的控制結構組成。當希望在不同的應用程式或平台上執行相同的函數,或者封裝特定功能時,存儲過程是非常有用的。資料庫中的存儲過程可以看做是對編程中面向對象方法的模擬。它允許控制數據的訪問方式。

優點:(1).存儲過程增強了SQL語言的功能和靈活性。存儲過程可以用流控制語句編寫,有很強的靈活性,可以完成複雜的判斷和較複雜的運算。

(2).存儲過程允許標準組件是編程。存儲過程被創建後,可以在程序中被多次調用,而不必重新編寫該存儲過程的SQL語句。而且資料庫專業人員可以隨時對存儲過程進行修改,對應用程式原始碼毫無影響。

(3).存儲過程能實現較快的執行速度。如果某一操作包含大量的Transaction-SQL代碼或分別被多次執行,那麼存儲過程要比批處理的執行速度快很多。因為存儲過程是預編譯的。在首次運行一個存儲過程時查詢,優化器對其進行分析優化,並且給出最終被存儲在系統表中的執行計劃。而批處理的Transaction-SQL語句在每次運行時都要進行編譯和優化,速度相對要慢一些。

(4).存儲過程能過減少網絡流量。針對同一個資料庫對象的操作(如查詢、修改),如果這一操作所涉及的Transaction-SQL語句被組織程存儲過程,那麼當在客戶計算機上調用該存儲過程時,網絡中傳送的只是該調用語句,從而大大增加了網絡流量並降低了網絡負載。

(5).存儲過程可被作為一種安全機制來充分利用。系統管理員通過執行某一存儲過程的權限進行限制,能夠實現對相應的數據的訪問權限的限制,避免了非授權用戶對數據的訪問,保證了數據的安全。

四.如何處理負載、高並發

1、HTML靜態化其實大家都知道,效率最高、消耗最小的就是純靜態化的html頁面,所以我們儘可能使我們的 網站上的頁面採用靜態頁面來實現,這個最簡單的方法其實也是最有效的方法。

2、圖片伺服器分離把圖片單獨存儲,儘量減少圖片等大流量的開銷,可以放在一些相關的平台上,如七牛等。

3、資料庫集群和庫表散列及緩存

資料庫的並發連接為100,一台資料庫遠遠不夠,可以從讀寫分離、主從複製,資料庫集群方面來著手。另外儘量減少資料庫的訪問,可以使用緩存資料庫如memcache、redis。

4、鏡像儘量減少下載,可以把不同的請求分發到多個鏡像端。

5、負載均衡:Apache的最大並發連接為1500,只能增加伺服器,可以從硬體上著手,如F5伺服器。當然硬體的成本比較高,我們往往從軟體方面著手。

負載均衡 (Load Balancing) 建立在現有網絡結構之上,它提供了一種廉價有效透明的方法擴展網絡設備和伺服器的帶寬、增加吞吐量、加強網絡數據處理能力,同時能夠提高網絡的靈活性和可用性。目前使用最為廣泛的負載均衡軟體是Nginx、LVS、HAProxy。我分別來說下三種的優缺點:

**Nginx的優點是:**

工作在網絡的7層之上,可以針對http應用做一些分流的策略,比如針對域名、目錄結構,它的正則規則比HAProxy更為強大和靈活,這也是它目前廣泛流行的主要原因之一,Nginx單憑這點可利用的場合就遠多於LVS了。

Nginx對網絡穩定性的依賴非常小,理論上能ping通就就能進行負載功能,這個也是它的優勢之一;相反LVS對網絡穩定性依賴比較大,這點本人深有體會;

Nginx安裝和配置比較簡單,測試起來比較方便,它基本能把錯誤用日誌列印出來。LVS的配置、測試就要花比較長的時間了,LVS對網絡依賴比較大。

可以承擔高負載壓力且穩定,在硬體不差的情況下一般能支撐幾萬次的並發量,負載度比LVS相對小些。

Nginx可以通過埠檢測到伺服器內部的故障,比如根據伺服器處理網頁返回的狀態碼、超時等等,並且會把返回錯誤的請求重新提交到另一個節點,不過其中缺點就是不支持url來檢測。比如用戶正在上傳一個文件,而處理該上傳的節點剛好在上傳過程中出現故障,Nginx會把上傳切到另一台伺服器重新處理,而LVS就直接斷掉了,如果是上傳一個很大的文件或者很重要的文件的話,用戶可能會因此而不滿。

Nginx不僅僅是一款優秀的負載均衡器/反向代理軟體,它同時也是功能強大的Web應用伺服器。LNMP也是近幾年非常流行的web架構,在高流量的環境中穩定性也很好。

Nginx現在作為Web反向加速緩存越來越成熟了,速度比傳統的Squid伺服器更快,可以考慮用其作為反向代理加速器。

Nginx可作為中層反向代理使用,這一層面Nginx基本上無對手,唯一可以對比Nginx的就只有 lighttpd了,不過 lighttpd目前還沒有做到Nginx完全的功能,配置也不那麼清晰易讀,社區資料也遠遠沒Nginx活躍。

Nginx也可作為靜態網頁和圖片伺服器,這方面的性能也無對手。還有Nginx社區非常活躍,第三方模塊也很多。

**Nginx的缺點是:**

Nginx僅能支持http、https和Email協議,這樣就在適用範圍上面小些,這個是它的缺點。

對後端伺服器的健康檢查,只支持通過埠來檢測,不支持通過url來檢測。不支持Session的直接保持,但能通過ip_hash來解決。

LVS:使用Linux內核集群實現一個高性能、高可用的負載均衡伺服器,它具有很好的可伸縮性(Scalability)、可靠性(Reliability)和可管理性(Manageability)。

**LVS的優點是:**

抗負載能力強、是工作在網絡4層之上僅作分發之用,沒有流量的產生,這個特點也決定了它在負載均衡軟體里的性能最強的,對內存和cpu資源消耗比較低。

配置性比較低,這是一個缺點也是一個優點,因為沒有可太多配置的東西,所以並不需要太多接觸,大大減少了人為出錯的幾率。

工作穩定,因為其本身抗負載能力很強,自身有完整的雙機熱備方案,如LVS+Keepalived,不過我們在項目實施中用得最多的還是LVS/DR+Keepalived。

無流量,LVS只分發請求,而流量並不從它本身出去,這點保證了均衡器IO的性能不會受到大流量的影響。

應用範圍比較廣,因為LVS工作在4層,所以它幾乎可以對所有應用做負載均衡,包括http、資料庫、在線聊天室等等。

**LVS的缺點是:**

軟體本身不支持正則表達式處理,不能做動靜分離;而現在許多網站在這方面都有較強的需求,這個是Nginx/HAProxy+Keepalived的優勢所在。

如果是網站應用比較龐大的話,LVS/DR+Keepalived實施起來就比較複雜了,特別後面有 Windows Server的機器的話,如果實施及配置還有維護過程就比較複雜了,相對而言,Nginx/HAProxy+Keepalived就簡單多了。

**HAProxy的特點是:**

HAProxy也是支持虛擬主機的。

HAProxy的優點能夠補充Nginx的一些缺點,比如支持Session的保持,Cookie的引導;同時支持通過獲取指定的url來檢測後端伺服器的狀態。

HAProxy跟LVS類似,本身就只是一款負載均衡軟體;單純從效率上來講HAProxy會比Nginx有更出色的負載均衡速度,在並發處理上也是優於Nginx的。

HAProxy支持TCP協議的負載均衡轉發,可以對MySQL讀進行負載均衡,對後端的MySQL節點進行檢測和負載均衡,大家可以用LVS+Keepalived對MySQL主從做負載均衡。

HAProxy負載均衡策略非常多,HAProxy的負載均衡算法現在具體有如下8種:

① roundrobin,表示簡單的輪詢,這個不多說,這個是負載均衡基本都具備的;

② static-rr,表示根據權重,建議關注;

③ leastconn,表示最少連接者先處理,建議關注;

④ source,表示根據請求源IP,這個跟Nginx的IP_hash機制類似,我們用其作為解決session問題的一種方法,建議關注;

⑤ ri,表示根據請求的URI;

⑥ rl_param,表示根據請求的URl參數』balance url_param』 requires an URL parameter name;

⑦ hdr(name),表示根據HTTP請求頭來鎖定每一次HTTP請求;

⑧ rdp-cookie(name),表示根據據cookie(name)來鎖定並哈希每一次TCP請求。

**Nginx和LVS對比的總結:**

Nginx工作在網絡的7層,所以它可以針對http應用本身來做分流策略,比如針對域名、目錄結構等,相比之下LVS並不具備這樣的功能,所以Nginx單憑這點可利用的場合就遠多於LVS了;但Nginx有用的這些功能使其可調整度要高於LVS,所以經常要去觸碰觸碰,觸碰多了,人為出問題的幾率也就會大。

Nginx對網絡穩定性的依賴較小,理論上只要ping得通,網頁訪問正常,Nginx就能連得通,這是Nginx的一大優勢!Nginx同時還能區分內外網,如果是同時擁有內外網的節點,就相當於單機擁有了備份線路;LVS就比較依賴於網絡環境,目前來看伺服器在同一網段內並且LVS使用direct方式分流,效果較能得到保證。另外注意,LVS需要向託管商至少申請多一個ip來做Visual IP,貌似是不能用本身的IP來做VIP的。要做好LVS管理員,確實得跟進學習很多有關網絡通信方面的知識,就不再是一個HTTP那麼簡單了。

Nginx安裝和配置比較簡單,測試起來也很方便,因為它基本能把錯誤用日誌列印出來。LVS的安裝和配置、測試就要花比較長的時間了;LVS對網絡依賴比較大,很多時候不能配置成功都是因為網絡問題而不是配置問題,出了問題要解決也相應的會麻煩得多。

Nginx也同樣能承受很高負載且穩定,但負載度和穩定度差LVS還有幾個等級:Nginx處理所有流量所以受限於機器IO和配置;本身的bug也還是難以避免的。

Nginx可以檢測到伺服器內部的故障,比如根據伺服器處理網頁返回的狀態碼、超時等等,並且會把返回錯誤的請求重新提交到另一個節點。目前LVS中 ldirectd也能支持針對伺服器內部的情況來監控,但LVS的原理使其不能重發請求。比如用戶正在上傳一個文件,而處理該上傳的節點剛好在上傳過程中出現故障,Nginx會把上傳切到另一台伺服器重新處理,而LVS就直接斷掉了,如果是上傳一個很大的文件或者很重要的文件的話,用戶可能會因此而惱火。

Nginx對請求的異步處理可以幫助節點伺服器減輕負載,假如使用 apache直接對外服務,那麼出現很多的窄帶連結時apache伺服器將會占用大 量內存而不能釋放,使用多一個Nginx做apache代理的話,這些窄帶連結會被Nginx擋住,apache上就不會堆積過多的請求,這樣就減少了相當多的資源占用。這點使用squid也有相同的作用,即使squid本身配置為不緩存,對apache還是有很大幫助的。

Nginx能支持http、https和email(email的功能比較少用),LVS所支持的應用在這點上會比Nginx更多。在使用上,一般最前端所採取的策略應是LVS,也就是DNS的指向應為LVS均衡器,LVS的優點令它非常適合做這個任務。重要的ip地址,最好交由LVS託管,比如資料庫的 ip、webservice伺服器的ip等等,這些ip地址隨著時間推移,使用面會越來越大,如果更換ip則故障會接踵而至。所以將這些重要ip交給 LVS託管是最為穩妥的,這樣做的唯一缺點是需要的VIP數量會比較多。Nginx可作為LVS節點機器使用,一是可以利用Nginx的功能,二是可以利用Nginx的性能。當然這一層面也可以直接使用squid,squid的功能方面就比Nginx弱不少了,性能上也有所遜色於Nginx。Nginx也可作為中層代理使用,這一層面Nginx基本上無對手,唯一可以撼動Nginx的就只有lighttpd了,不過lighttpd目前還沒有能做到 Nginx完全的功能,配置也不那麼清晰易讀。另外,中層代理的IP也是重要的,所以中層代理也擁有一個VIP和LVS是最完美的方案了。具體的應用還得具體分析,如果是比較小的網站(日PV小於1000萬),用Nginx就完全可以了,如果機器也不少,可以用DNS輪詢,LVS所耗費的機器還是比較多的;大型網站或者重要的服務,機器不發愁的時候,要多多考慮利用LVS。

更多面試題系列:

面試官三年經驗PHP知識點匯總

分享一波騰訊PHP面試題

2020年PHP面試題附答案(實戰經驗)

2020年PHP最新面試題(含答案)

php面試題之PHP核心技術


很多人在剛接觸這個行業的時候或者是在遇到瓶頸期的時候,總會遇到一些問題,比如學了一段時間感覺沒有方向感,不知道該從那裡入手去學習,對此我整理了一些資料,需要的可以免費分享給大家(10年架構師帶你解讀年薪50萬面試通關秘籍。)


這套精品PHP教程絕不是市場上的那些妖艷賤貨可比,作為web開發的佼佼者PHP並不遜色其他語言,加上Swoole後更加是如虎添翼!進軍通信 、物聯網行業開發百度地圖、百度訂單中心、虎牙、戰旗TV等!寒冬裁員期過後正是各大企業擴大招人的時期,現在市場初級程式設計師泛濫,進階中高級程式設計師絕對是各大企業急需的人才,這套學習教程適合那些1-7年以內的PHP開發者正處於瓶頸期,想要突破自己進階中高級、架構師!名額有限,先到先得!

點擊此處中間位置有獲取地址

部分進階到架構資料截圖:


還有限時精品福利:

★騰訊高級PHP工程師筆試題目

★億級PV高並發場景訂單的處理

★laravel開發天貓商城組件服務

★戰旗TV視頻直播的架構項目實戰


點擊此處中間位置有獲取地址

本課程深度對標騰訊T3-T4標準,貼身打造學習計劃為web開發人員進階中高級、架構師提升技術,為自己增值漲薪!加入BAT特訓營還可以獲得內推大廠名額以及GO語言學習權限!!!

關鍵字: