1.請問一下你使用過swoole嗎,使用過,怎么設置心跳?
$this->serv->set([
'heartbeat_check_interval' => 5,
'heartbeat_idle_time' => 10
]);
//上面的設置就是每5秒偵測一次心跳,一個TCP連接如果在10秒內(nèi)未向服務器端發(fā)送數(shù)據(jù),將會被切斷。
2.如果一個訪問量達到100萬,選擇緩存,你會選擇redis還memchache?
我會選擇memchache,因為它只有一種類型,key-value,而redis的類型比memchache多,導致它的并發(fā)沒有memchache好。
3.psr2和psr4的區(qū)別?
意思:psr指的是php standards recommendatiion,意思PHP標準建議。
psr2:編碼風格向?qū)?/p>
<?phpnamespace Vendor\Package;
use FooClass;use BarClass as Bar;use OtherVendor\OtherPackage\BazClass;// ... additional PHP code ...
psr4:自動加載。
psr4:#完整的類名為\a\b\c\Log#命名空間前綴前綴為:a\b#前綴對應的基礎目錄為:./vendor#文件實際目錄為:./vendor/c/Log.php#注:即把去掉最前面的命名空間分隔符后的a\b\c\Log中的命名空間前綴替換成基礎目錄,然后把命名空間分隔符替換成目錄分隔符,并把文件名補上后綴 .php 。
4.mb_strlen和str_len的區(qū)別?
<?php
$a = '中國';
echo strlen($a)."\n";//6
echo mb_strlen($a);//2
5.下面會輸出什么?
<?php
$str = 'abc';
$res = strpos($str,'a');
if ($res){
echo '找到了';
}
else {
echo '未找到';
}
//答案是:未找到未找到,因為strpos是查找首字母出現(xiàn)的位置,并且索引是從0開始的,并且PHPs是弱類型的,所以會輸出:未找到
6.使用二分法查找50出現(xiàn)的位置?
//第一種方法
$arr = [1,3,5,12,34,45,50];
function binary(array &$arr,int $low,int $top,int $target){
while($low<=$top){
$mid = floor(($low+$top)/2);
if($arr[$mid] === $target){
return $mid;
} elseif($arr[$mid]>$target){
$top= $mid-1;
} else if($arr[$mid]<$target){
$low= $mid+1;
}
}
return -1;
}
$arr = [1,3,5,12,34,45,50];
echo binary($arr,0,count($arr),50);//6
//第二種方法
function binaryRecursive(array &$arr,int $low,int $top,int $target){
$mid = floor(($low+$top)/2);
if ($arr[$mid]>$target){
return binaryRecursive($arr,$low,$mid-1,$target);
} elseif ($arr[$mid]<$target){
return binaryRecursive($arr,$mid+1,$top,$target);
} else if ($arr[$mid]===$target){
return $mid;
} else {
return -1;
}
}
$arr = [1,3,5,12,34,45,50];
echo binaryRecursive($arr,0,count($arr),50);//6
7.將上面的數(shù)組進行翻轉(zhuǎn),不使用內(nèi)置函數(shù)?
$arr = [1,3,5,12,34,45,50];
function overturn(array &$arr){
$temp = [];
for ($i = count($arr)-1;$i>=0;$i--){
$temp[] = $arr[$i];
}
// print_r($temp);
return $temp;
}
$arr = [1,3,5,12,34,45,50];
//Array
(
[0] => 50
[1] => 45
[2] => 34
[3] => 12
[4] => 5
[5] => 3
[6] => 1
)
8.請寫出nginx負載均衡的算法?怎么檢查配置用沒有問題,如果有問題,怎么查看出現(xiàn)是問題,修改了配置文件,怎么生效?
1.round robin(默認)
? 解釋:輪詢方式,依次將請求分配到各個后臺服務器中,默認的負載均衡方式,是否機器性能一致的情況下。
2.weight(權重)`
upstream bakend {
server 192.168.0.14 weight=10;
server 192.168.0.15 weight=10;
}
? 解釋:根據(jù)權重來分發(fā)請求到不同的機器中,指定輪詢幾率,weight和訪問比率成正比,用于后端服務器性能不均的情況。
3.IP_hash
解釋:根據(jù)請求者ip的hash值將請求發(fā)送到后臺服務器中,可以保證來自同一ip的請求被打到固定的機器上,可以解決session問題。
upstream bakend {
ip_hash;
server 192.168.0.14:88;
server 192.168.0.15:80;
}
4.url_hash
解釋:根據(jù)請求的url的hash值將請求分到不同的機器中,當后臺服務器為緩存的時候效率高。
upstream backend {
server squid1:3128;
server squid2:3128;
hash $request_uri;
hash_method crc32;
}
5.fair(第三方)
解釋:根據(jù)后臺響應時間來分發(fā)請求,響應時間短的分發(fā)的請求多。
upstream backend {
server server1;
server server2;
fair;
}
tips:
upstream bakend{#定義負載均衡設備的Ip及設備狀態(tài)
ip_hash;
server 127.0.0.1:9090 down;
server 127.0.0.1:8080 weight=2;
server 127.0.0.1:6060;
server 127.0.0.1:7070 backup;
}
//每個設備的狀態(tài)設置為:
1.down 表示單前的server暫時不參與負載
2.weight 默認為1.weight越大,負載的權重就越大。
3.max_fails :允許請求失敗的次數(shù)默認為1.當超過最大次數(shù)時,返回proxy_next_upstream 模塊定義的錯誤
4.fail_timeout:max_fails次失敗后,暫停的時間。
5.backup: 其它所有的非backup機器down或者忙的時候,請求backup機器。所以這臺機器壓力會最輕。
nginx支持同時設置多組的負載均衡,用來給不用的server來使用。
client_body_in_file_only 設置為On 可以講client post過來的數(shù)據(jù)記錄到文件中用來做debug
client_body_temp_path 設置記錄文件的目錄 可以設置最多3層目錄
location 對URL進行匹配.可以進行重定向或者進行新的代理 負載均衡
9.優(yōu)化下面的代碼?
$arr = [1,2,3,...n+1];
$userName = [];
foreach ($arr as $v){
$userName = $this->getUserNameFromyDb($v);
}
//優(yōu)化代碼如下:
$arr = [1,2,3,...n+1];
$userName = [];
$userName = this->getUserNameFromyDb(implode(',',$arr))
10.請實現(xiàn)一個單列模式。
<?php
class Singleton
{
//1.創(chuàng)建私有變量保存該對象
private static $interface;
//2.禁止使用new
public function __construct()
{
}
//3.禁止克隆
public function __clone()
{
// TODO: Implement __clone() method.
}
//4.判斷對象是否存在
public static function getInstance()
{
if (!self::$interface instanceof self) {
self::$interface = new self();
}
return self::$interface;
}
public function test(){
echo '測試單列模式';
}
}
$singleton = Singleton::getInstance();
$singleton->test();
//實現(xiàn)單列模式的意義,減少資源的占用
11.docker內(nèi)部配置php+mysql+nginx怎么在內(nèi)部進行連接。
? 沒有配置過
12.請簡述一下觀察者模式?
簡單的一句話就是,多個不同類去執(zhí)行方法名相同的代碼。
實現(xiàn):1.定義一個觀察接口,第二實現(xiàn)該接口里的方法。
生活中的例子:
小明觀察者),狗(被觀察者),貓(被觀察者),牛(被觀察者)
當小明看見狗,就知道它喜歡吃骨頭。
當小明看見貓,就知道它喜歡吃魚。
當小明看見牛,就知道它喜歡吃青草。
代碼如下
?php
//觀察者接口
interface ObjectTest {
public function register(ObServerTest $obServerTest);//注冊觀察者對象
public function detach(ObServerTest $obServerTest);//刪除觀察者對象
public function notify();//通知所有的被觀察者
}
//被觀察者接口
interface ObServerTest{
public function eat();
}
class Action implements ObjectTest{
private $_obServersTest = [];
public function register(ObServerTest $obServerTest)//注冊對象
{
$this->_obServersTest[] = $obServerTest;
}
public function detach(ObServerTest $obServerTest)
{
$index = array_search($obServerTest,$this->_obServersTest);
if(false === $index || !array_key_exists($index,$this->_obServersTest)){
throw new \Exception('該對象不存在');
}
unset($this->_obServersTest[$index]);
}
public function notify()//通知所有的對象
{
foreach ($this->_obServersTest as $k=>$v){
$v->eat();
}
}
}
class Dog implements ObServerTest{
public function eat()
{
echo '狗吃骨頭'."\n";
}
}
class Cat implements ObServerTest{
public function eat()
{
echo '貓吃魚'."\n";
}
}
class Pink implements ObServerTest{
public function eat()
{
echo '豬吃了睡,睡了吃'."\n";
}
}
$action = new Action();
$action->register(new Dog());
$action->register(new Cat());
$action->register(new Pink());
$action->notify();
//結(jié)果:
狗吃骨頭
貓吃魚
豬吃了睡,睡了吃
13.請寫出怎么獲取請求頭的信息?
Apache:
getallheaders();
nginx:
function nginxGetAllHeaders(){//獲取請求頭
$headers = [];
foreach ($_SERVER as $name => $value){
if (substr($name, 0, 5) == 'HTTP_'){
$headers[str_replace(' ', '-', ucwords(strtolower(str_replace('_', ' ', substr($name, 5)))))] = $value;
}
}
return $headers;
}
14.高訪問量的網(wǎng)站怎么優(yōu)化?
1.軟件
? 1)將不經(jīng)常變化的數(shù)據(jù),直接靜態(tài)化。
? 2)使用redis和memcha,減少數(shù)據(jù)庫的訪問。
? 3)控制大文件的下載。
? 4)圖片、視頻服務器分離。
? 5)禁止外部的盜鏈。(可以通過refer去實現(xiàn))
? 6)統(tǒng)計流量的使用情況。
2.硬件
? 1)不考慮成本,服務器可以考慮負載均衡,mysql主從復制、讀寫分離。
15.請說一下websoket原理?
? 參照:https://www.cnblogs.com/nnngu/p/9347635.html
16.redis默認有多少個庫?
? 16個庫
17.linux進程之間怎么通信?
? 1.管道
ls -al /etc | less
? 2.信號量(沒有使用過)
? 3.消息隊列(沒有使用過)
? 4.信號(沒有使用過)
? 5.共享內(nèi)容(沒有使用過)
? 6.套接字(unix socket)
18.如果用戶git,請問一下git怎么合并分支?
? git checkout master
? git merche 分支名
19.laravel外面引入路由.
? 1.在route文件夾中添php文件,并且設置路由。
? 2.在app/Providers/RouteServiceProvider中對應的文件路徑。
? 3.然后laravel啟動就會加載該文件。
20.請求用沒有使用過隊列?
#redis的隊列
//server.php
<?php
$redis = new Redis();
$redis->connect('127.0.0.1',6379);
$password = '123456';
$redis->auth($password);
$arr = array('list1','list2');
foreach($arr as $k=>$v){
$redis->rpush("mylist",$v);
}
//client.php
<?php
$redis = new Redis();
$redis->connect('127.0.0.1',6379);
$password = '123456';
$redis->auth($password);
//list類型出隊操作
$value = $redis->lpop('mylist');
if($value){
if($value === 'list1'){
echo '執(zhí)行l(wèi)ist1的代碼';
}
if($value === 'list2'){
echo '執(zhí)行l(wèi)ist2的代碼';
}
}else{
echo "出隊完成";
}
//執(zhí)行兩次
#第一次
執(zhí)行l(wèi)ist1的代碼
#第二次
執(zhí)行l(wèi)ist2的代碼
//rabbitmq
#等不忙的時候再寫
21.怎么防止商品不會超賣?
? 采用redis的隊列,去實現(xiàn)。
22.單引號和雙引號的區(qū)別?
? 1.單引號比雙引號執(zhí)行速度快。
? 2.雙引號會解析變量、換行,而單引號不會。
23.微信支付、支付寶回調(diào),如果在回調(diào)區(qū)間服務器崩潰了,有沒有解決辦法?
? 1.確定那些單是沒有收到回調(diào)。
? 2.通過訂單號,去查詢支付寶和微信的訂單狀態(tài),確定是否支付成功。
24.在瀏覽器輸入網(wǎng)址,點回車,經(jīng)歷了什么,才能將數(shù)據(jù)顯示在瀏覽器上?

25.請說一下php常見的字符串處理函數(shù)和數(shù)組?
字符串函數(shù)
mb_substr()//截取字符串(中文的)
substr()//·········(英文)
ucfirst()//將字符串首字母變?yōu)榇髮?str_replace()//替換字符串
#這里參數(shù)就不做詳細的說明(自行去百度哈)
數(shù)組:
array_chunk(array $array , int $size [, bool $preserve_keys = false ])//將一個數(shù)組分割成多個
/*
array
操作的數(shù)組
size
每個數(shù)組的單元數(shù)目
preserve_keys
設為 TRUE,可以使 PHP 保留輸入數(shù)組中原來的鍵名。如果你指定了 FALSE,那每個結(jié)果數(shù)組將用從零開始的新數(shù)字索引。默認值是 FALSE
*/
//代碼如下
<?php
$arr = [1,3,45,50];
print_r(array_chunk($arr,1));
/**
Array
(
[0] => Array
(
[0] => 1
)
[1] => Array
(
[0] => 3
)
[2] => Array
(
[0] => 45
)
[3] => Array
(
[0] => 50
)
)
*/
array_diff_key ( array $array1 , array $array2 [, array $... ] ) : array#使用鍵名比較計算數(shù)組的差集
/**
array1
從這個數(shù)組進行比較
array2
針對此數(shù)組進行比較
...
更多比較數(shù)組
*/
//代碼如下:
<?php
$array1 = ['blue' => 1, 'red' => 2, 'green' => 3, 'purple' => 4];
$array2 = ['green' => 5, 'blue' => 6, 'yellow' => 7, 'cyan' => 8];
print_r(array_diff_key($array1, $array2));
/**
Array
(
[red] => 2
[purple] => 4
)
*/
array_diff ( array $array1 , array $array2 [, array $... ] ) : array# 計算數(shù)組的差集
/**
rray1
要被對比的數(shù)組
array2
和這個數(shù)組進行比較
...
更多相比較的數(shù)組
*/
<?php
$array1 = array("a" => "green", "red", "blue", "red");
$array2 = array("b" => "green", "yellow", "red");
$result = array_diff($array1, $array2);
print_r($result);
/**
Array
(
[1] => blue
)
*/
array_walk ( array &$array , callable $callback [, mixed $userdata = NULL ] ) : bool#使用用戶自定義函數(shù)對數(shù)組中的每個元素做回調(diào)處理
/**
array
輸入的數(shù)組。
callback
典型情況下 callback 接受兩個參數(shù)。array 參數(shù)的值作為第一個,鍵名作為第二個。
userdata
如果提供了可選參數(shù) userdata,將被作為第三個參數(shù)傳遞給 callback funcname。
*/
//代碼如下:
<?php
$fruits = array('a' => 'lemon', 'b' => 'orange');
function testPrint(string $k,string $v){
echo $k.$v."\n";
}
print_r(array_walk($fruits,'testPrint'));
/**
lemona
orangeb
1
*/
//1是返回值哦
compact ( mixed $varname1 [, mixed $... ] ) : array# 建立一個數(shù)組,包括變量名和它們的值
/*
對每個參數(shù),compact() 在當前的符號表中查找該變量名并將它添加到輸出的數(shù)組中,變量名成為鍵名而變量的內(nèi)容成為該鍵的值
**/
//代碼如下:
<?php
$city = "San Francisco";
$state = "CA";
$event = "SIGGRAPH";
$location_vars = array("city", "state");
$res = compact('event','xxx',$location_vars);
print_r($res);
/**
Array
(
[event] => SIGGRAPH
[city] => San Francisco
[state] => CA
)
*/
array_key_exists ( mixed $key , array $array ) : bool#檢查數(shù)組里是否有指定的鍵名或索引
//代碼如下
$searchArray = array('TEST1' => 1);
var_dump(array_key_exists('test1', $searchArray));
/**
bool(false)
*/
//區(qū)分大小寫
//更多數(shù)組函數(shù):https://www.php.net/manual/zh/function.array-change-key-case.php
26.為什么要減少數(shù)據(jù)庫的訪問次數(shù)?
因為方法數(shù)據(jù)庫,會有大量io、事務、網(wǎng)絡傳輸操作,所有要減少數(shù)據(jù)庫的訪問次數(shù)。
27.require和include的區(qū)別?
include在引入不存文件時產(chǎn)生一個警告且腳本還會繼續(xù)執(zhí)行,
require則會導致一個致命性錯誤且腳本停止執(zhí)行。
28.php7和php5的區(qū)別?
php7新特性:
? 1.支持標量和返回類型。
class Test
{
private $age;
/**
* @return mixed
*/
public function getAge()
{
return $this->age;
}
/**
* @param mixed $age
*/
public function setAge(int $age): void
{
$this->age = $age;
}
}
$test = new Test();
$test->setAge('1233ddsaf');
echo $test->getAge();//1233,內(nèi)部進行了轉(zhuǎn)換
? 3.太空船運算符號。
$var = $i??1;//判斷變量是否存在,存在將該值給$var,不存在,將1給$var
echo $var;
//1
? 4.可以使用一個 use 從同一個 namespace 中導入類、函數(shù)和常量.
? 5.可以通過 define() 來定義數(shù)組。
define('test',['12',23]);
echo test[1];
//23
? 6.可用使用new class來實現(xiàn)一個匿名類。
<?php
interface Logger{
public function log(string $log);
}
class App {
private $logger;
/**
* @return mixed
*/
public function getLogger()
{
return $this->logger;
}
/**
* @param mixed $logger
*/
public function setLogger($logger): void
{
$this->logger = $logger;
}
}
$app = new App();
$app->setLogger(new class implements Logger{
public function log(string $log)
{
echo $log;
}
});
$app->getLogger()->log('這是一條日志');
//這是一條日志
29.數(shù)據(jù)庫優(yōu)化策略?
1.合理的表設計。
? 1).依據(jù)三范式,設計表.
? 三范式:1.原子性,每個字段都是不可在分的。
? 2.在1方式的基礎上,表中每一列必須有唯一性,其他字段依賴主鍵。
? 3.在2方式的基礎上,表中的每一列只與主鍵直接相關,而不是間接相關。
? 2).選擇合適的字段。
? I.盡量使用TYPEINT、SMALLINT、MEDIUM_INT代替INT的使用,一般索引,并且是字段遞增,可以考慮設置為UNSIGNED.
? II.使用枚舉代替字符串類型。
? III.將少null的使用,null很難優(yōu)化,并且還占用額外的空間。
? iv.varchar長度分配給真正需要的空間。
? v.建立合適的索引。
3)選擇合適的引擎。
2.sql優(yōu)化
? 1).減少*的使用,只查詢需要的字段。
? 2).使用關聯(lián)查詢,代替子查詢。
? 3).like使用后匹配。
? 4).合理使用索引。
? 5)減少對null字段的判斷、否則引擎放棄索引,對全表進行掃描。
? 6)減少!=,<>的使用。
? 7)減少where 條件中使用or來連接條件
select id from t where num=10 or Name = ‘a(chǎn)dmin’
#可以這樣查詢:
select id from t where num = 10
union
select id from t where Name = ‘a(chǎn)dmin’
3.減少數(shù)據(jù)庫訪問的次數(shù)。
? 1).將不經(jīng)常變化的數(shù)據(jù),進行緩存(分類、權限等),可以使用redis和mememcha,我個人建議,不要使用文件緩存,它也是對iO進行操作。
4.硬件方面。
? 1).可以考慮分庫、分表。
? 2)可以采用主從復制,讀寫分離.(mysql服務器根據(jù)sql,去判斷是讀還是寫)。
30.laravel保存session。
$request->session()->put('admin',$res);
$request->session()->save();//要加這一句,如果不加,不會保存session
//如果要保存session,都要調(diào)用save方法