八年phper的高級工程師面試之路八年phper的高級工程師面試之路

這是一篇反面教材,希望也能引起部分程序員的警惕。

最近半個月時間,經過幾次面試,差不多已經對自己有了定位————距離騰訊T3崗位還是有一點距離。

因爲在一家小公司呆的習慣了(6年),公司沒有人在技術層面超過我,作爲技術核心,感覺自己很牛,活在一個小圈子裏面,幾乎不會主動去了解新技術,甚至對php以及js本身都不能算精通。

所以變故出現的時候,我才發現自己的技術脫節有多厲害,雖然之前的面試並沒有做專門的準備,但是與6年前找工作的情形相比,差距非常的大。

下面是我整理的一部分遇到的面試題,我儘量用我所知道的知識來進行陳述,肯定會有很多誤解以及遺漏,希望大家能夠指正。

公司1:

1、mysql_real_escape_string mysql_escape_string有什麼本質的區別,有什麼用處,爲什麼被棄用?

答:mysql_real_escape_string需要預先連接數據庫,並可在第二個參數傳入數據庫連接(不填則使用上一個連接)

兩者都是對數據庫插入數據進行轉義,但是mysql_real_escape_string轉義時,會考慮數據庫連接的字符集。

它們的用處都是用來能讓數據正常插入到數據庫中,並防止sql注入,但是並不能做到100%防止sql注入。

再問:爲什麼不能100%防止?

答;因爲客戶端編碼以及服務器端編碼不同,可能產生注入問題,但是其實這種場景不多見。

繼續答:被棄用的原因是官方不再建議使用mysql_xx的數據庫操作方式,建議使用pdo和mysqli,因爲不管從性能跟安全來看,mysqli都比mysql要好。

衍生出來的問題是mysqli的連接複用(持久化)問題,這一塊我並沒有答好。

2、什麼是內存泄漏,js內存泄漏是怎麼產生的?

答:內存泄漏是因爲一塊被分配內存既不能被使用,也不能被回收,直到瀏覽器進程結束。

產生泄漏的原因是閉包維持函數內局部變量,不能被釋放,尤其是使用閉包並存在外部引用還setInterval的時候危害很大。

備註:我覺得這塊回答並不好,因爲肯定不是閉包的原因。

我查了一下資料,從比較淺的方位來再回答一下這個問題:

產生泄漏的原因有好幾種:

(1) 頁面元素被刪除,但是綁定在該元素上的事件未被刪除;

(2) 閉包維持函數內局部變量(外部不可控),使其得不到釋放;

(3) 意外的全局變量;

(4) 引用被刪除,但是引用內的引用,還存在內存中。

從上述原因上看,內存泄漏產生的根本原因是引用無法正確回收,值類型並不能引發內存泄漏。

對於每個引用,都有自己的引用計數,當引用計數歸零或被標記清除時,js垃圾回收器會認爲該引用可以回收了。

3、什麼是閉包,跟原型鏈、作用域鏈有什麼關聯

答:閉包是指存在於一個作用域鏈分支的函數域內的函數,該函數可以向上逐級訪問作用域鏈上的變量,直到找到爲止。當閉包存在外部引用時,js會維持閉包自身以及所在函數作用域鏈的內存狀態。

備註:這個是我自己瞎說的。

繼續答:跟原型鏈沒有什麼關聯,函數的原型(prototype)主要用於實現繼承,原型鏈可用於追溯繼承關係,與作用域鏈類似,都是向上逐級訪問屬性,直到被找到,原型鏈的頂層是null,可以理解爲所有的object都繼承至null,所以null的類型是object。

繼續答:作用域鏈可以看作是一個樹形結構,由根節點window向下擴散,下層節點可以訪問上層節點,但是上層節點無法訪問下層節點,產生閉包的函數作用域屬於節點中的一個,向下擴散後閉包函數產生葉子節點,葉子節點之間可以互相訪問,當訪問的變量在葉子節點中無法找到時,向上層節點查找,直到被找到爲止,這個概念有點類似原型鏈上的屬性查找。

4、一臺電腦配置無限好,可以同時打開多少個網頁

答:65535-1000 = 64535(端口數)

5、ip地址能被僞造嗎?

答:http頭部可以被篡改,但是隻能修改X_FORWARDED_FOR,真實ip地址(REMOTE_ADDR)很難修改(除非是路由器去修改),因爲真實ip是底層會話ip地址,而且因爲TCP 3次握手的存在,連接無法建立,僞造的意義不大,至於UDP的話,一般是內網才使用UDP通信。

6、有100萬個獎品,每個人可以中獎3次,先到先得,怎麼控制併發,不能發超,並保證完全的先到先得模式

答:百萬獎品在打亂後預先insert到數據庫,所有中獎操作,均只能update,不能insert。進來抽獎的用戶使用memcahe原子加鎖,實現抽獎次數自增,當抽獎次數到達3時,返回不中獎。

再問:預先插入需要很多資源,如果獎品數量上了1億怎麼辦?

答:使用redis隊列存儲請求,跑守護進程異步發獎,產生的問題是用戶無法實時看到中獎情況。

再問:這樣肯定不行。

再答:使用全局內存加鎖確保抽獎過程是單進程在跑,但是會面臨大併發阻塞問題。

再問:內存比較寶貴,在不用內存加鎖的情況下怎麼辦,並且如果碰到1億獎池的情況,預先插入數據庫肯定不好,怎麼辦?

答:設置獎品概率,分三張表,都使用innodb引擎,一張存中獎記錄(預先插入一行),一張存獎品發放概況,一張存用戶抽獎情況(uin唯一索引),大併發情況下,利用mysql的排他鎖進行併發控制。流程如下:

begin

查詢用戶抽獎次數,加排他鎖

對用戶抽獎次數的更新/插入

鎖行查詢發放情況

獲得抽獎結果(某些獎品發完之後,動態變更概率)

更新發放表

插入中獎記錄

commit

再問:遇到髒讀怎麼辦?

答:這方面不是很瞭解

再問:innodb的master線程在什麼情況下fork其他子線程?

答:不知道

7、數據鏈路層的數據是怎麼校驗的,有哪些校驗方式

答:crc32,別的校驗可能是取模校驗奇偶數吧。

備註:答個crc校驗就行了。

8、b+樹的查詢時間複雜度是多少,哈希表是多少,爲什麼數據庫索引用b+樹存儲,而不是哈希表,數據庫索引存儲還有其他數據結構嗎

答:O(log(n)),O(1)

因爲哈希表是散列的,在遇到`key`>'12'這種查找條件時,不起作用,並且空間複雜度較高。

備註:b+數根據層數決定時間複雜度,數據量多的情況下一般4-5層,然後用二分法查找頁中的數據,時間複雜度遠小於log(n)。

9、apache是怎麼跟php通訊的,sapi是什麼

答:使用sapi通訊,sapi是php封裝的對外數據傳遞接口,通常有cgi/fastcgi/cli/apache2handler四種運行模式。

10、php的垃圾回收機制?

答:垃圾回收是指當php運行狀態結束時,比如遇到了exit/die/致命錯誤/腳本運行結束時,php需要回收運行過程中創建的變量、資源的內存。

ZEND引擎維護了一個棧zval,每個創建的變量和資源都會壓入這個棧中,每個壓入的數組結構都類似:[refcount => int, is_ref => 0|1, value => union, type => string],變量被unset時,ref_count如果變成0,則被回收。

當遇到變量循環引用自身時,使用同步回收算法回收。

備註:PHP7已經重寫了zal的結構體。

11、jquery的sizzle引擎工作原理

答:除了直到是DOM元素查找引擎之外,一無所知。

12、seajs的工作原理,如何解決重複加載庫的問題,如何進行資源的同步加載

答:建立映射關係並緩存起來;資源並不能真正同步加載,只是返回一個回調。

13、memcache跟redis的區別

答:可存儲數據結構不同;redis支持持久化存儲。

14、md5逆向原理

答:先用字典查找,再嘗試暴力破解。

再問:沒有更好的方法了嗎?

答:沒有了。

備註:嗯,事實上也確實沒有特別好的辦法,只能使用TB級的海量特徵庫用數據庫存起來,然再分片查找。

15、父類方法是protected,子類重構爲private,會發生什麼?

答:會發生fatal錯誤,因爲繼承的方法或屬性只能維持或放大權限,不能縮小,比如protected重載爲public是可行的。

16、一個網頁從輸入地址回車,到完整展示網頁內容這段時間裏,做了哪些工作,越詳細越好。

答:

0、瀏覽器本地緩存匹配;

1、本地hosts映射對比;

2、本地dns緩存解析;

3、遠程dns解析獲得服務器ip地址;

4、瀏覽器發送tcp連接請求包(syn);

5、請求包經過傳輸層、網絡層、數據鏈路層封裝通過網卡到達路由器;

6、路由器轉發數據包到所屬運營商服務器;

7、運營商服務器通過尋址最短路徑通過中繼節點到達指定ip地址;

8、服務器端可能存在反向代理或者負載均衡,都是直接轉發請求至上游服務器,當然也可以制定安全防禦規則直接丟棄請求包;

9、上游服務器收到連接請求,在自身可用的情況下,返回(syn+ack);

10、瀏覽器校驗ack,再次發送(syn+ack);

11、服務器校驗ack切換連接狀態至established,然後根據請求傳輸數據包;

12、當transform-encoding爲chunked時,瀏覽器開始渲染頁面;

13、四次揮手,連接關閉;

14、渲染數據完成。

備註:還有很多東西不懂,一些東西完全是自己瞎蒙的,因爲時間原因,以後有時間詳細畫一下。

17、keep-alive的概念

答:長連接機制,表示keep-alive-timeout時間內,如果連接沒有closed,再次傳輸數據不再需要三次握手了。

備註:這裏也有很多疑問,需要好好捋一捋。

18、linux文件壓縮操作命令,shell腳本等

備註:因爲平時開發都是在windows環境,對linux瞭解不足,這一塊幾乎是0分。

公司2:

這個是被鄙視最慘的一家了,首先會有筆試,相對來說並不複雜,但是有些坑,很多已經忘記了。

印象深刻的是我說自己熟悉常用設計模式,然後讓我畫UML類圖,我就懵逼了,所以在寫簡歷的時候,最好是寫自己非常熟悉的,如果只是一知半解,並沒有必要放到簡歷中。

公司3:

這裏僅列舉幾個問到的問題:

1、設計一箇中繼服務器,轉發客戶A->客戶B的請求;

2、myisam跟innodb有什麼區別;

3、php進程死鎖產生的原因是什麼?怎麼自動排查與自動恢復?

4、有class A { public function b($a, $b, $c){}};

怎麼使用['b' => 2, 'a' => 1, 'c' => 3],對進行A::b進行調用,並順利賦值?

5、php5.2->php7.1的各版本演進歷史,新增特性等?

6、畫一個tcp三次握手圖

在我看來8年的程序員怎麼也不應該是這樣子的,溫水煮青蛙的教訓非常慘痛,招招打在要害才知道疼,好在現在認識到問題還不晚,等到了35歲這個年紀,可能就真的晚了.

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