常用演算法、問答、設計模式

JaneWorld發表於2019-06-11

PHP試題:
https://mp.weixin.qq.com/s/ilEVTX6M7BtWapA...
PHP相關知識
https://www.cnblogs.com/jackieron/p/650476...

氣泡排序:
常用演算法
二分查詢:遞迴方式
$array = [1,3,6,9,13,18,19,29,38,47,51,56,58,59,60,63,65,69,70,71,73,75,76,77,79,89];
$target = 73;
$low = 0;
$high = count($array)-1;
function bin_search($array, $low, $high, $target){
if ( $low <= $high){
var_dump($low, $high);echo “\n”;
$mid = intval(($low+$high)/2 );
if ($array[$mid] == $target){
return true;
}elseif ( $target < $array[$mid]){
return bin_search($array, $low, $mid-1, $target);
}else{
return bin_search($array, $mid+ 1, $high, $target);
}
}
return false;
}
$find = bin_search($array, $low, $high, $target);
var_dump($find);

分散式解決方案-分散式session一致性問題?
https://www.jianshu.com/p/b889f9a49fec

1.Cookie禁用了,Session還能用嗎?
對應的伺服器Session,Session ID是通過Cookie來傳遞的,禁用Cookie相當於失去了Session ID,就得不到Session
php.ini檔案中的”session.use_trans_sid = 1“,或者編譯時開啟開啟了”–enable-trans-sid選項”
a.$sn=session_id();
session_id($_GET–>url傳過來的引數)
b.fopen w+ 寫入session_id()
fread 取出sesson_id

session與cookie的區別?
session:儲存使用者訪問的全域性唯一變數,儲存在伺服器上的php指定的目錄中的(session_dir)的位置進行的存放
cookie:用來儲存連續訪問一個頁面時所使用,是儲存在客戶端,對於Cookie來說是儲存在使用者WIN的Temp目錄中的。

如何實現session的共享?
  為什麼要實現共享,如果網站是存放在一個機器上,那麼是不存在這個問題的,因為會話資料就在這臺機器,但是如果使用了負載均衡把請求分發到不同的機器呢?這個時候會話id在客戶端是沒有問題的,但是如果使用者的兩次請求到了兩臺不同的機器,而它的session資料可能存在其中一臺機器,這個時候就會出現取不到session資料的情況,於是session的共享就成了一個問題。
  php支援把會話資料儲存到某臺memcache伺服器,你也可以手工把session檔案存放的目錄改為nfs網路檔案系統,從而實現檔案的跨機器共享。
一般的解決方案是存入資料庫,memcache或者redis這種快取伺服器,當然用預設的檔案儲存方式也可以,用NFS統一儲存。

2.GET、POST傳輸最大容量是多少?
GET傳送http協議通過url方式傳遞,受瀏覽器或者伺服器的設定限制
POST實體資料,表單傳送,通過php.conf的post_max_size可以設定傳輸大小
3.抓取遠端圖片到本地,會用什麼函式?
file_get_contents() file_put_contents()
4.CGI是什麼?什麼是FastCGI?php-fpm、FastCGI、Nginx之間是什麼關係?
server收到一個php的請求時,會啟動一個程式去處理當前的請求,而這個程式就是CGI
通用閘道器介面(返回標準html資料的服務)
FastCGI 是一個協議,是應用程式和 WEB 伺服器連線的橋樑。Nginx 並不能直接與 PHP-FPM 通訊,而是將請求通過 FastCGI 交給 PHP-FPM 處理。
php-fpm是fastcgi程式的管理器,用來管理fastcgi程式的。
5.函式內部static和global關鍵字的作用?
stattic(靜態區域性變數)作用於函式內,不能用在函式外
global(靜態全域性變數)可以作用任何地方
6.memcache和Redis的區別及優缺點?
memcache把資料存到記憶體中,讀取速度快。
Redis支援的資料型別更多,資料也可以存到硬碟,斷電不會掛掉,資料持久化,memcache一旦斷電資料就沒了。
都可以一主多從。
7.Include require include_once require_once 的區別?
處理失敗方式不同:
require 失敗時會產生一個致命級別錯誤,並停止程式執行。
include 失敗時只產生一個警告級別錯誤,程式繼續執行。

include_once/require_once和include/require 處理錯誤方式一樣,
唯一區別在於當所包含的檔案程式碼已經存在時候,不在包含。

8.php魔幻(術)方法及預定義變數;
__construct() 例項化類時自動呼叫。
__destruct() 類物件使用結束時自動呼叫。
__set() 在給未定義的屬性賦值的時候呼叫。
__get() 呼叫未定義的屬性時候呼叫。
__isset() 使用isset()或empty()函式時候會呼叫。
__unset() 使用unset()時候會呼叫。
__sleep() 使用serialize序列化時候呼叫。
__wakeup() 使用unserialize反序列化的時候呼叫。
__call() 呼叫一個不存在的方法的時候呼叫。
__callStatic()呼叫一個不存在的靜態方法是呼叫。
__toString() 把物件轉換成字串的時候會呼叫。比如 echo。
__invoke() 當嘗試把物件當方法呼叫時呼叫。
__set_state() 當使用var_export()函式時候呼叫。接受一個陣列引數。
__clone() 當使用clone複製一個物件時候呼叫。

預定義變數(超級全域性變數)
$GLOBALS
$_SERVER
$_GET
$_POST
$_COOKIE
$_SESSION
$_REQUEST
$_ENV

魔術變數
LINE
FILE
DIR
CLASS
FUNCTION
METHOD
NAMESPACE

9.一些編譯php時的configure 引數
–prefix=/usr/local/php php安裝目錄
–with-config-file-path=/usr/local/php/etc 指定php.ini位置
–with-mysql=/usr/local/mysql mysql安裝目錄,對mysql的支援
–with-mysqli=/usr/local/mysql/bin/mysql_config mysqli檔案目錄,優化支援
–enable-safe-mode 開啟安全模式
–enable-ftp 開啟ftp的支援
–enable-zip 開啟對zip的支援
–with-bz2 開啟對bz2檔案的支援
–with-jpeg-dir 開啟對jpeg圖片的支援
–with-png-dir 開啟對png圖片的支援
–with-freetype-dir 開啟對freetype字型庫的支援
–without-iconv關閉iconv函式,種字符集間的轉換
–with-libxml-dir 開啟libxml2庫的支援
–with-xmlrpc 開啟xml-rpc的c語言
–with-zlib-dir 開啟zlib庫的支援
–with-gd 開啟gd庫的支援
更多可以使用 ./configure help 檢視

10.寫程式碼來解決多程式/執行緒同時讀寫一個檔案的問題。
PHP是不支援多執行緒的,可以使用php的flock加鎖函式實現。
$fp = fopen(“/tmp/lock.txt”, “w+”);
if (flock($fp, LOCK_EX)) { // 進行排它型鎖定
fwrite($fp, “Write something here\n”);
flock($fp, LOCK_UN); // 釋放鎖定
} else {
echo “Couldn’t lock the file !”;
}
fclose($fp);

11.Mysql 的儲存引擎,myisam和innodb的區別。
a. MyISAM型別不支援事務處理等高階處理,而InnoDB型別支援.
b. MyISAM型別的表強調的是效能,其執行數度比InnoDB型別更快.
c. InnoDB不支援FULLTEXT型別的索引.
d. InnoDB 中不儲存表的具體行數,也就是說,
執行select count(*) from table時,InnoDB要掃描一遍整個表來計算有多少行,
但是MyISAM只要簡單的讀出儲存好的行數即可.
e. 對於AUTO_INCREMENT型別的欄位,InnoDB中必須包含只有該欄位的索引,但是在MyISAM表中,可以和其他欄位一起建立聯合索引。
f. DELETE FROM table時,InnoDB不會重新建立表,而是一行一行的刪除。
g. LOAD TABLE FROM MASTER操作對InnoDB是不起作用的,解決方法是首先把InnoDB表改成MyISAM表,匯入資料後再改成InnoDB表,
但是對於使用的額外的InnoDB特性(例如外來鍵)的表不適用.
h. MyISAM支援表鎖,InnoDB支援行鎖。

MyIsam 的儲存檔案有三個,字尾名分別是 .frm、.MYD、MYI,其中 .frm 是表的定義檔案,.MYD 是資料檔案,.MYI 是索引檔案。
InnoDB 的儲存檔案有兩個,字尾名分別是 .frm 和 .idb,其中 .frm 是表的定義檔案,而 idb 是資料檔案。
InnoDB 支援事務,且支援四種隔離級別(讀未提交、讀已提交、可重複讀、序列化),預設的為可重複讀。

12.MySQL資料庫作釋出系統的儲存,一天五萬條以上的增量,預計運維三年,怎麼優化?
a. 設計良好的資料庫結構,允許部分資料冗餘,儘量避免join查詢,提高效率。
b. 選擇合適的表欄位資料型別和儲存引擎,適當的新增索引。
c. mysql庫主從讀寫分離。
d. 找規律分表,減少單表中的資料量提高查詢速度。
e。新增快取機制,比如memcached,apc等。
f. 不經常改動的頁面,生成靜態頁面。
g. 書寫高效率的SQL。比如 SELECT * FROM TABEL 改為 SELECT field_1, field_2, field_3 FROM TABLE.

13.對於大流量的網站,您採用什麼樣的方法來解決各頁面訪問量統計問題
a. 確認伺服器是否能支撐當前訪問量。
b. 優化資料庫訪問。
c. 禁止外部訪問連結(盜鏈), 比如圖片盜鏈。
d. 控制檔案下載。
e. 使用不同主機分流。
f. 使用瀏覽統計軟體,瞭解訪問量,有針對性的進行優化。

14.是否用過模板引擎? 如果有您用的模板引擎的名字是?
Smarty

15.PHP中this和self的區別
this:物件
self:類

16.如何防止SQL隱碼攻擊,XSS攻擊和CSRF攻擊
SQL隱碼攻擊:mysqli_real_escape_string()轉義關鍵字元;
XSS攻擊:alert把一些cookie資訊列印出來;過濾掉<>等關鍵字串
CSRF攻擊:跨站攻擊。防止:token,驗證碼

17.Nosql 資料庫 MemCache、Redis、MongoDB 的區別
1.memcached:單一鍵值對記憶體快取的,做物件快取無可替代的分散式快取;
2.redis:是演算法和資料結構的集合,快速的資料結構操作是他最大的特點,支援資料持久化;
3.mongodb是bson結構、介於rdb和nosql之間的,更鬆散更靈活的,但是不支援事務,只用作非重要資料儲存。

應用場景:
Memcached:動態系統中減輕資料庫負載,提升效能;做快取,適合多讀少寫,大資料量的情況(如人人網大量查詢使用者資訊、好友資訊、文章資訊等)。
Redis:適用於對讀寫效率要求都很高,資料處理業務複雜和對安全性要求較高的系統(如新浪微博的計數和微博釋出部分系統,對資料安全性、讀寫要求都很高)。
  MongoDB:主要解決海量資料的訪問效率問題。

18.PHP 記憶體回收機制

19.MySQL的只讀模式
設定命令:
mysql> set global read_only=1; #1是隻讀,0是讀寫
mysql> show global variables like “%read_only%”;
1、對於資料庫讀寫狀態,主要靠 “read_only”全域性引數來設定;
2、預設情況下,資料庫是用於讀寫操作的,所以read_only引數也是0或faluse狀態,這時候不論是本地使用者還是遠端訪問資料庫的使用者,都可以進行讀寫操作;
3、如需設定為只讀狀態,將該read_only引數設定為1或TRUE狀態,但設定 read_only=1 狀態有兩個需要注意的地方:
1)read_only=1只讀模式,不會影響slave同步複製的功能,所以在MySQL slave庫中設定了read_only=1後,通過 show slave status\G ,命令檢視salve狀態,可以看到salve仍然會讀取master上的日誌,並且在slave庫中應用日誌,保證主從資料庫同步一致;
2)read_only=1只讀模式,可以限定普通使用者進行資料修改的操作,但不會限定具有super許可權的使用者的資料修改操作;在MySQL中設定read_only=1後,普通的應用使用者進行insert、update、delete等會產生資料變化的DML操作時,都會報出資料庫處於只讀模式不能發生資料變化的錯誤,但具有super許可權的使用者,例如在本地或遠端通過root使用者登入到資料庫,還是可以進行資料變化的DML操作;

20.談談對閉包的理解。
使用閉包來解決如何訪問函式內部變數的問題。
function foo() {
var num = 123;
function fn() {
return num;//
}
return fn;
}
var m=foo();
var f=m();
console.log(f);//輸出的值為123,這樣就可以訪問到函式內部變數num。

21.如何解決 PHP 記憶體溢位問題?
1.上傳excel檔案時,出現記憶體溢位的情況,在檔案中分配大點的記憶體設定記憶體治標不治本,而且伺服器php.ini(memory_limit =128M)有時候是很難改的。所以在檔案中設定。但是隻有php.ini中的安全模式safe_mode開啟時才可以設定。
2.使用sql查詢資料,查出來很多,導致記憶體溢位
sql語句在mysql中可以查詢,但是使用php程式查詢就報php記憶體溢位
(1)這個問題在php的官方網站叫緩衝查詢和非緩衝查詢。php的查詢預設模式是緩衝模式。也就是,查詢資料結果一次全部提取到記憶體裡供php程式額外的功能,比如說,計算行數,將指標指向某一行等。更重要的是程式對資料集反覆進行二次查詢和過濾操作。但這種緩衝查詢模式的缺陷是消耗記憶體,也就是用空間換速度。
(2)另外一種查詢模式是非緩衝查詢,資料庫伺服器會一條一條的返回資料,而不是一次全部返回,這樣的結果是php程式消耗較少的記憶體,但卻增加了資料庫伺服器的壓力,因為資料庫會一直等待php來取資料,一直到資料全部取完。
1.首先查詢資料庫需要進行limit進行分頁查詢
2.如果不使用limit,使用非緩衝查詢
3.處理陣列時出現記憶體溢位
(1)使用迭代生成器,可以通過繼承Iterator介面實現
(2)使用關鍵詞yield

22.如何處理 MySQL 死鎖?
https://www.jb51.net/article/159737.htm

foreach 中 &的用法

laravel:
laravel的生命週期(框架執行原理)
Laravel 的生命週期從public\index.php開始,從public\index.php結束。
composer自動載入需要的類:
第一步:Laravel框架所有請求入口統一進入/public/index.php檔案,請求通過Ngxin/Apache指向該檔案。
index.php檔案是載入其他檔案入口,本身程式碼不多。index.php檔案載入通過Composer生產的自動載入配置,然後從bootstrap/app.php獲取應用例項,建立服務容器。
第二步:Http/Console核心
HTTP核心 繼承自Illuminate\Foundation\Http\Kernel類,該類定義了一個bootstrappers陣列,該陣列中的類在請求被執行前執行,bootstrappers配置了錯誤處理、日誌、檢測應用環境、其他在請求被處理前需要處理的任務。
HTTP核心還定義請求處理前需要經過HTTP中介軟體,該中介軟體處理HTTP會話的讀寫、判斷應用是否處於維護模式,驗證CSRF令牌(防止CSRF攻擊)等。
HTTP核心標籤方法handle:獲取一個Request,返回一個Response,輸入HTTP請求,返回HTTP響應。
第三步:核心啟動會為應用載入服務提供者,服務提供者都被配置在config/app.php配置檔案的providers陣列中。服務提供者被註冊後,boot方法被呼叫。
服務提供者負責啟動框架的所有元件,如資料庫、佇列、驗證器、路由元件等。因他們啟動並配置框架提供的所有特性,服務提供者是整個Laravel啟動過程中最重要部分。
第四步:將請求傳遞給路由(一旦應用被啟動且所有服務提供者被註冊,Request將會被交給路由器進行分發,路由器將會分發請求到路由或控制器,同時執行所有路由指定的中介軟體)。

PHP 設計模式
工廠模式:
建立一個工廠(一個函式或一個類方法)來製造新的物件。
工廠模式 是一種類,它具有為您建立物件的某些方法。您可以使用工廠類建立物件,而不直接使用 new。這樣,如果您想要更改所建立的物件型別,只需更改該工廠即可。使用該工廠的所有程式碼會自動更改。

單例模式:
某些應用程式資源是獨佔的,因為有且只有一個此型別的資源。例如,通過資料庫控制程式碼到資料庫的連線是獨佔的。您希望在應用程式中共享資料庫控制程式碼,因為在保持連線開啟或關閉時,它是一種開銷,在獲取單個頁面的過程中更是如此。
單元素模式可以滿足此要求。
PHP 中的單例模式(singleton pattern):指的是在 PHP 的應用程式的範圍內只對指定的類建立一個例項。

在 PHP 中使用單例模式的類通常擁有一個私有建構函式和一個私有克隆函式,以防 止使用者通過建立物件或者克隆對其進行例項化。還有一個靜態私有成員變數 $instance 與靜態方法 getInstance。getInstance 負責對其本身例項化,然後將這個物件儲存在 $instance 靜態成員變數中,以確保只有一個例項被建立。

觀察者模式
命令鏈模式
策略模式

單例模式:
class SingleInstance
{
private function _construct(){
}
private static $instance;
private function _clone(){
}
public static function getInstance(){
self::$instance instanceof SingleInstance){
self::$instance=new SingleInstance();
}
return self ::$instance;
}
}

短連線:例如普通的web請求,在三次握手之後建立連線,傳送資料包並得到伺服器返回的結果之後,通過客戶端和服務端的四次握手進行關閉斷開。

長連線:區別於短連線,由於三次握手鍊接及四次握手斷開,在請求頻繁的情況下,連結請求和斷開請求的開銷較大,影響效率。採用長連線方式,執行三次握手鍊接後,不斷開連結,保持客戶端和服務端通訊,直到伺服器超時自動斷開連結,或者客戶端主動斷開連結。

適用場景:
短連線:適用於網頁瀏覽等資料重新整理頻度較低的場景。
長連線:適用於客戶端和服務端通訊頻繁的場景,例如聊天室,實時遊戲等。

PHP向第三方伺服器傳送post請求
function post($url, $post_data, $timeout=10)
{
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, 1);
if ($post_data != ‘’) {
curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);
}
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, ‘POST’);

curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
curl_setopt($ch, CURLOPT_HEADER, false);
$file_contents = curl_exec($ch);
curl_close($ch);
return $file_contents;
}

php獲取位元組流介面資料
$body_str = @file_get_contents(‘php://input’);
$body = json_decode($body_str, true);
php傳送位元組流資料
function HttpPost($url, $data)
{
$ch = curl_init();
curl_setopt($ch,CURLOPT_URL,$url);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
$res = curl_exec($ch);
curl_close($ch);

return $res;
}

獲取access_token,並快取
// 獲取基本access_token,並且快取(基本access_token每天只能呼叫2000次)
function get_access_token($APPID, $APPSECRET){
$URL = “https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=".$APPID."&secret=".$APPSECRET;
$result = get($URL);
session(array(‘cache_name’=>’access_token’,’expire’=>7200));
$_SESSION[‘token_expire’] = time() + 7200;
$_SESSION[‘access_token’] = $result[‘access_token’];
$ACCESS_TOKEN = $result[‘access_token’];
return $ACCESS_TOKEN;
}

// 判斷基本access_token是否還有效
function token($APPID, $APPSECRET){
if (time() < $_SESSION[‘token_expire’]) {
// if (!empty($_SESSION[‘access_token’])) {
$TOKEN = $_SESSION[‘access_token’];
}else{
$TOKEN = get_access_token($APPID,$APPSECRET);
}
// dump($TOKEN);
return $TOKEN;
}

//獲取票據憑證
function get_ticket($ACCESS_TOKEN){
// 獲取ticket
$url = “https://api.weixin.qq.com/cgi-bin/ticket/getticket?type=jsapi&access_token=".$ACCESS_TOKEN;
$res = get($url);
session(array(‘name’=>’ticket’,’expire’=>7200));
$_SESSION[‘ticket_expire’] = time() + 7200;
$_SESSION[‘ticket’] = $res[‘ticket’];
$TICKET = $_SESSION[‘ticket’];
return $TICKET;
}
//判斷票據是否有效
function ticket($ACCESS_TOKEN){
if (time() < $_SESSION[‘ticket_expire’]) {
// if (!empty($_SESSION[‘ticket’])) {
$TICKET = $_SESSION[‘ticket’];
}else{
$TICKET = get_ticket($ACCESS_TOKEN);
}
// dump($TICKET);
return $TICKET;
}

本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章