某公司後端開發工程師面試題學習

最近看到的某公司後端開發工程師面試題,拿來研究學習一下,感受提升技術,看面試題也是一個挺好的方法:(php

 1.redis有幾種使用場景,除了使用字符串型還使用過redis哪些存儲類型?
 2.redis如何實現鎖?
 3.php有哪些實現鎖的機制?
 4.myisam和inodb的區別?
 5.什麼是ddos攻擊?如何防範ddos攻擊?
 6.http和https有什麼不一樣?http包是如何泄露的? 
 7.php7有什麼新特性?
 8.如何防止SQL注入?
 9.mysql主、從數據庫如何保持一致?
10.php如何實現異步機制?
 
 
1.redis的使用場景包括:
   1)緩存數據。一些訪問量大的熱點數據,首頁數據,搜索數據均可以經過redis緩存起來。根本目的是減小數據庫的訪問壓力,提升頁面響應速度和用戶體驗度。極端的作法是,只要能夠減輕數據庫壓力,數據均可以緩存。本質是空間換時間。弊端是用戶獲得的數據不是實時最新的數據,有必定的延遲(取決於緩存時設置的過時時間);
   2)實現鎖機制。redis實現鎖的方式包括incr,set.setnx。考慮場景,網站提供 將用戶帳戶餘額轉帳到用戶支付寶的功能,若是同時併發有多個請求,在帳戶操做和遠程請求支付寶的過程當中可能出現數據不一致問題。以incr舉例,加鎖實現單線程阻塞操做:

  Redis Incr 命令將 key 中儲存的數字值增一。html

        若是 key 不存在,那麼 key 的值會先被初始化爲 0 ,而後再執行 INCR 操做。(incr具備原子性。)前端

//先獲取相關用戶參數而且驗證

$redis_lock = $Redis::incr($user_id."alipay_lock");
if($redis_lock <= 1){
	$redis::expire($redis_lock,10);//設置超時時間

	//數據庫操做
	//向支付寶發送轉帳請求操做

	$Redis::del($redis_lock);
}else{
	//返回提示信息,表示轉帳正在進行
}  
 這裏的一個細節是,必須設置超時時間,防止在轉帳相關操做中,出現超時或其餘錯誤,鎖沒有解除。其餘併發請求永遠沒法執行轉帳操做。
  3)會話緩存。web請求的session數據能夠存在redis中。把 session 默認的存儲方式由 file 改成  redis 會提升速度,因爲redis是在內存中讀取的,其讀取速度必然比在文件中讀取速度快,同時解決了session共享的問題。
參考:https://yann0917.github.io/2017/05/01/PHP-session-%E5%AD%98%E5%85%A5-Redis/
  https://blog.csdn.net/Dennis_ukagaka/article/details/78072274
  4)計數器。數據統計的需求很是廣泛,經過原子遞增保持計數。例如,點贊數、收藏數、分享數等。 
  5)排行榜功能,例如,展現最近、最熱、點擊率最高、活躍度最高等等條件的top list 。 利用redis的有序集合實現(sorted set);
  6)簡單的隊列實現。使用list功能。
  參考:https://juejin.im/post/58330053570c350059e0bb08
 
  除了string類型,還用過list數據類型。當時是維護python寫的程序,之前的同窗使用list存儲從數據表中查詢出來的數據,感受這樣不是很好,仍是序列化存儲成字符串型較好。
 
 2.前面的答案已經解答了這個問題。
 
 3.1)php能夠用文件鎖來實現。參考代碼:
$fp=fopen('/tmp/lock.txt','w+');
if (flock($fp,LOCK_EX)){
   //do something flock($fp,LOCK_UN); }else{ echo 'Couldn't lock the file !'; } fclose($fp);

  打開文件後,先對文件加鎖。加鎖後,意味着只有這個進程能夠訪問lock.txt文件 。在操做完成後,打開鎖。這個方法操做比較簡易,對於須要同步執行的程序出錯機率低的狀況,較爲適用;但是它的缺點是沒有超時時間的限制,一旦在do something的時候出現什麼問題。這個鎖就解不開了。會佔用cpu。其餘進程也沒法執行該操做了。python

      2)能夠用redis緩存實現鎖。前面答案已經描述。這個適用於隨機響應的狀況,若是須要響應每個請求,且按請求的前後順序進行依次處理。則不太適合,應當構建隊列。mysql

      3)使用隊列來響應併發請求(隊列依然依賴redis的list數據結構實現)。來一個排隊一個,依次處理。處理程序能夠用php寫一個守護程序。按順序去redis裏的list去取請求處理,若是list爲空,則等待1秒再去取。(大概邏輯是這樣)。git

  4.這個網上答案不少。github

      區別:1)myisam的text支持索引,innodb不支持;web

                 2)innodb支持事務,myisam不支持,對於InnoDB每一條SQL語言都默認封裝成事務,自動提交,這樣會影響速度,因此最好把多條SQL語言放在begin和commit之間,組成一個事務;面試

                3)innodb有行鎖,myisam只是表鎖;ajax

                4)myisam的查詢效率高於innodb;

                 5)InnoDB不保存表的具體行數,執行select count(*) from table時須要全表掃描。而MyISAM用一個變量保存了整個表的行數,執行上述語句時只須要讀出該變量便可,速度很快;

                 6)InnoDB支持外鍵,而MyISAM不支持。對一個包含外鍵的InnoDB錶轉爲MYISAM會失敗;

                7)InnoDB是彙集索引,數據文件是和索引綁在一塊兒的,必需要有主鍵,經過主鍵索引效率很高。可是輔助索引須要兩次查詢,先查詢到主鍵,而後再經過主鍵查詢到數據。所以,主鍵不該該過大,由於主鍵太大,其餘索引也都會很大。而MyISAM是非彙集索引,數據文件是分離的,索引保存的是數據文件的指針。主鍵索引和輔助索引是獨立的。

參考:https://www.zhihu.com/question/20596402

5.分佈式拒絕服務(DDoS:Distributed Denial of Service)攻擊指藉助於客戶/服務器技術,將多個計算機聯合起來做爲攻擊平臺,對一個或多個目標發動DDoS攻擊,從而成倍地提升拒絕服務攻擊的威力。(來源百度百科)

       如何防範:1)關閉沒必要要的服務,如只開放80端口響應Http請求;2)獲取可疑攻擊ip,加入黑名單,禁止訪問;3)使用cdn服務,將流量分散到網絡各個節點,減小對服務器的壓力等等。(具體的方法網絡上不少,有各類的總結和攻防的案例)。

6. 簡單來講,http是明文傳輸的協議,客戶端和服務器通信的全部內容都明文暴露在公共的互聯網上,一旦http包被截獲,信息就會被別人獲取;https則是加密傳輸的協議,客戶端和服務器通信的關鍵內容都是有密匙加密過的,雖然也是在公共的網絡上傳遞,可是通信的包被截獲,別人拿到加密後的內容也沒法解密獲取到通信的內容。具體的介紹能夠參考前端牛人小卡的一篇介紹,寫的很詳細。雖然https的瀏覽器私人密匙怎麼生成我仍是不太瞭解,是否是能夠窮舉?  

2018/5/9  服務器發給客戶端的證書的數字簽名,須要客戶端用CA的公匙解密。這個CA的公匙是保存在瀏覽器或者操做系統中的。因此使用php的時候依然能夠作https請求!

 

  http包泄露的方式: 1)本身的電腦被入侵,接受和發送的http包都會被黑客監聽獲取到;2)電腦所在的局域網關被黑客入侵,http包也會被截獲;3)在公共互聯網上也有不少節點(如代理服務器)可能被截獲。

7. php7的新特性有不少,最實惠的是性能(不管是服務器的cpu佔用率,響應請求數量仍是請求處理時間)提升了至少一倍。參考http://hansionxu.blog.163.com/blog/static/24169810920158704014772/,和鳥哥的我的網站。有空我須要再把php的底層實現再看看吧。

8. 防止sql注入的方法:1)嚴格限制用戶輸入(長度,類型,特殊字符);2)使用mysql_escape_string轉義特殊字符;3)使用pdo模式操做數據庫,預編譯語句,參數化查詢,分開的發送到數據庫服務端進行解析。

 具體的php綁定和分預編譯語句,變量參數化兩次傳遞給msql服務器的細節內容能夠參考月影無痕的分析。至於將SQL模板和變量是分兩次發送給MySQL後,mysql的處理細節,我繼續使用google。查詢到文章:預編譯語句(Prepared Statements)介紹,以MySQL爲例 。裏面介紹了預編譯語句在mysql端是如何實現的,可是仍是沒有解決個人核心問題,預編譯語句爲何能防止sql注入? 知乎相關問題中,不二的回答提到了佔位符的概念頗有意思,sql語句在包含佔位符的狀況下編譯,理論上來講,之後就不會再改變了。這是否決定了該語句的運行結果被限制在必定的範圍內了,後面用參數代替佔位符(會將參數字符串轉義)後的結果也會限定在這個範圍內? 有待於進一步研究吧。

 9.MySQL之間數據複製的基礎是二進制日誌文件(binary log file)。一臺MySQL數據庫一旦啓用二進制日誌後,其做爲master,它的數據庫中全部操做都會以「事件」的方式記錄在二進制日誌中,其餘數據庫做爲slave經過一個I/O線程與主服務器保持通訊,並監控master的二進制日誌文件的變化,若是發現master二進制日誌文件發生變化,則會把變化複製到本身的中繼日誌中,而後slave的一個SQL線程會把相關的「事件」執行到本身的數據庫中,以此實現從數據庫和主數據庫的一致性,也就實現了主從複製。

具體參考:http://www.javashuo.com/article/p-xcrglajm-cw.html

 10.php自己並無異步處理的機制。若是須要實現異步機制,能夠變着法用一些加超時的請求或ajax來完成。
      1)服務器返回的html中插入Ajax 代碼或 img 標記,img的src爲須要執行的程序;2)使用popen;3)使用curl,超時設爲1秒;4)使用 fsockopen,本身拼參數,能夠當即返回不在乎超時時間。參考: http://www.jb51.net/article/76909.htm  

 這個時候我又腦洞大開,既然已經想到了php的異步調用了。那麼會不會有像其餘語言裏面同樣的回調函數存在呢,好比js裏面的call這樣的。因而google了同樣還真有這樣的東西。不過它是同步文件中的,若是異步調用非得要回調,能夠把回調的一些參數放在請求參數中,這樣在請求的文件中調用回調的內容就能夠了。

關於php的回調函數實現,能夠參考:http://www.cnitblog.com/CoffeeCat/archive/2009/04/21/56541.html

相關文章
相關標籤/搜索