本教程是本人基于 360大牛:全面解读PHP面试的课程所作的笔记,加上我我的对一些其余知识的补充,聚集了一些其余教程聚集。众人智慧结晶,我的总结所得
转载请注明出处 PHP面试复习知识点(超级全面,由浅入深)
字符串和数字用等于模糊判断时,字符串会被先转换成数字再进行对比
示例代码eq.phpphp
<?php $arr = [ "'0e123' == ''" => '0e123' == '', "'0e123' == '0'" => '0e123' == '0', "'0e123' == 0" => '0e123' == 0, "'0e123' == 'e'" => '0e123' == 'e', "'0e123' == '000'" => '0e123' == '000', "'1e123' == '1'" => '1a000e123' == '1', "'1e123' == 1" => '1a000e123' == 1, "'000e123' == '0'" => '000e123' == '0', "'e123' == 0" => 'a123' == 0, "'e123' == '0'" => 'a123' == '0', "null == 0" => null == 0, "null == '0'" => null == '0', "null == false" => null == false, "[] == 0" => [] == 0, "[] == '0'" => [] == '0', "[] == false" => [] == false, "false == 0" => false == 0, "false == '0'" => false == '0', ]; foreach ($arr as $key => $value) { echo '( ' . $key . ' ) => ' . ($value === true ? 'true' : 'false') . PHP_EOL; }
输出结果css
( '0e123' == '' ) => false ( '0e123' == '0' ) => true ( '0e123' == 0 ) => true ( '0e123' == 'e' ) => false ( '0e123' == '000' ) => true ( '1e123' == '1' ) => false ( '1e123' == 1 ) => true ( '000e123' == '0' ) => true ( 'e123' == 0 ) => true ( 'e123' == '0' ) => false ( null == 0 ) => true ( null == '0' ) => false ( null == false ) => true ( [] == 0 ) => false ( [] == '0' ) => false ( [] == false ) => true ( false == 0 ) => true ( false == '0' ) => true
$_SERVER['SERVER_ADDR'] //服务器地址 $_SERVER['SERVER_NAME'] //服务名称 $_SERVER['REQUEST_TIME'] //请求时间 $_SERVER['QUERY_STRING'] //请求地址中问号后的内容 $_SERVER['HTTP_REFERER'] //上次请求地址 $_SERVER['HTTP_USER_AGENT'] //浏览器信息 $_SERVER['REMOTE_ARRR'] //客户端请求ip $_SERVER['REQUEST_URI'] // 请求中脚本名称 $_SERVER['PATH_INFO'] // 请求中路径
必定定义,不可删除和修改html
用不一样名字访问同一个变量内容,用『&』符号表示前端
示例代码abstract_class.phpmysql
<?php abstract class Animal { protected $name = 'animal'; abstract public function call(); abstract public function run(); public function getName() { return $this->name; } } class Cat extends Animal { protected $name = 'cat'; public function call() { echo $this->getName() . ': 喵喵叫~' . PHP_EOL; } public function run() { echo $this->getName() . '在跑~' . PHP_EOL; } } class Dog extends Animal { protected $name = 'dog'; public function call() { echo $this->getName() . ': 汪汪叫~' . PHP_EOL; } public function run() { echo $this->getName() . '在跑~' . PHP_EOL; } } $cat = new Cat; $cat->call(); $cat->run(); $dog = new Dog; $dog->call(); $dog->run();
运行结果:react
cat: 喵喵叫~ cat在跑~ dog: 汪汪叫~ dog在跑~
示例代码interface_class.phpnginx
<?php interface Animal { public function call(); public function run(); } class HasName { protected $name = 'name'; public function getName() { return $this->name; } } class Cat extends HasName implements Animal { protected $name = 'cat'; public function call() { echo $this->getName() . ': 喵喵叫~' . PHP_EOL; } public function run() { echo $this->getName() . '在跑~' . PHP_EOL; } } class Dog extends HasName implements Animal { protected $name = 'dog'; public function call() { echo $this->getName() . ': 汪汪叫~' . PHP_EOL; } public function run() { echo $this->getName() . '在跑~' . PHP_EOL; } }
输出结果laravel
cat: 喵喵叫~ cat在跑~ dog: 汪汪叫~ dog在跑~
implements
,抽象类使用extends
interface
,抽象类定义用abstract
优先级由高到低排序
缘由:由于计算机存储是二进制,准换进制时会有精度丢失git
解决方案:先将浮点字符串化,再进行整数获取,输出可经过printgithub
$f = 0.57; $f = $f * 100; // 输入可经过print printf('%d', $f); // 用于存储或二次计算,先将浮点字符串化,再进行整数获取 $f = strval($f); var_dump($f); echo floor($f); echo intval($f); echo (int)($f);
global
定义,能够在局部域调用全局变量,可经过$GLOBAL['XXX']
读取变量的值static
定义,仅在局部域中存在,执行函数离开做用域,其值也不会消失示例代码ip.php
<?php $ip = '192.168.1.1'; echo $ip. ' => ' . ip2long($ip) . ' => ' . long2ip(ip2long($ip)); // 输出 // 192.168.1.1 => 3232235777 => 192.168.1.1
示例代码print.php
<?php print('aaaaaa'); echo PHP_EOL; printf("%s:%2.2f", 'sada', 111.222); echo PHP_EOL; print_r([1, 2]); echo PHP_EOL; echo 11; echo PHP_EOL; echo sprintf("%s:%2.2f", 'sada', 111.222); echo PHP_EOL; var_dump([1, 2]); echo PHP_EOL; var_export([1, 2]); echo PHP_EOL; echo var_export([1, 2], true); echo PHP_EOL;
输出结果
aaaaaa sada:111.22 Array ( [0] => 1 [1] => 2 ) 11 sada:111.22 array(2) { [0]=> int(1) [1]=> int(2) } array ( 0 => 1, 1 => 2, ) array ( 0 => 1, 1 => 2, )
示例代码serialize.php
<?php $a = 'klinson'; echo $a . ' =>' . serialize($a) . ' => ' . unserialize(serialize($a));
输出结果
klinson => s:7:"klinson"; => klinson
示例代码string.php
<?php $str = 'klinson'; $array = explode('n', $str); var_dump($array, join('n', $array), implode('n', $array)); echo 'strrev(\'klinson\') => ' . strrev($str) . PHP_EOL; $str = ' klinson '; var_dump(trim($str), ltrim($str), rtrim($str)); echo 'strstr(\'klinson\', \'n\') => '.strstr($str, 'n') . PHP_EOL; echo 'number_format(100000000000) => ' . number_format(100000000000) . PHP_EOL;
输出结果
array(3) { [0]=> string(3) "kli" [1]=> string(2) "so" [2]=> string(0) "" } string(7) "klinson" string(7) "klinson" strrev('klinson') => nosnilk string(7) "klinson" string(8) "klinson " string(8) " klinson" strstr('klinson', 'n') => nson number_format(100000000000) => 100,000,000,000
php.ini
中打开allow_url_fopen
配置,http协议只能使用只读,ftp协议,只能只读或只写
示例代码fileinfo.php
<?php $filepath = __FILE__; echo '__FILE__ => ' . $filepath . PHP_EOL; echo 'basename(__FILE__) => ' . basename($filepath) . PHP_EOL; echo 'dirname(__FILE__) => ' . dirname($filepath) . PHP_EOL; echo 'pathinfo(__FILE__) => ' . PHP_EOL; var_dump(pathinfo($filepath));
输出结果
__FILE__ => /home/wwwroot/default/public/index0.php basename(__FILE__) => index0.php dirname(__FILE__) => /home/wwwroot/default/public pathinfo(__FILE__) => array(4) { ["dirname"]=> string(28) "/home/wwwroot/default/public" ["basename"]=> string(10) "index0.php" ["extension"]=> string(3) "php" ["filename"]=> string(6) "index0" }
目录必须为空
工厂模式
工厂模式能够将对象的生产从直接new 一个对象,改为经过调用一个工厂方法生产。这样的封装,代码若需修改new的对象时,不需修改多处new语句,只需更改生产对象方法
示例代码factory.php
<?php /*** Interface people 人类 */ interface people { public function say(); } /*** Class man 继承people的男人类 */ class man implements people { // 实现people的say方法 function say() { echo '我是男人-hi' . PHP_EOL; } } /* Class women 继承people的女人类 */ class women implements people { // 实现people的say方法 function say() { echo '我是女人-hi' . PHP_EOL; } } /* Interface createPeople 建立人物类 */ interface createPeople { public function create(); } /* Class FactoryMan 继承createPeople的工厂类-用于实例化男人类 */ class FactoryMan implements createPeople { // 建立男人对象(实例化男人类) public function create() { return new man(); } } /* Class FactoryMan 继承createPeople的工厂类-用于实例化女人类 */ class FactoryWomen implements createPeople { // 建立女人对象(实例化女人类) function create() { return new women(); } } class Client { // 具体生产对象并执行对象方法测试 public function test() { $factory = new FactoryMan(); $man = $factory->create(); $man->say(); $factory = new FactoryWomen(); $man = $factory->create(); $man->say(); } } // 执行 $demo = new Client; $demo->test();
输出结果
我是男人-hi 我是女人-hi
单例模式
用于为一个类生成一个惟一的对象
示例代码singleton.php
<?php class Db { protected static $instance; public static function getInstance($config = []) { if (is_null(self::$instance)) { self::$instance = new self($config); } return self::$instance; } public function __construct($config = []) { // TODO:: 数据库链接操做 echo '这里已经完成数据库的链接!' . PHP_EOL; } public function getData($table) { // TODO:: 数据库读取数据操做 echo "这里获取了表 [ {$table} ] 的数据了!" . PHP_EOL; } } Db::getInstance()->getData('klinson0'); Db::getInstance()->getData('klinson1'); Db::getInstance()->getData('klinson2');
输出结果
已经完成数据库的链接! 这里获取了表 [ klinson0 ] 的数据了! 这里获取了表 [ klinson1 ] 的数据了! 这里获取了表 [ klinson2 ] 的数据了!
适配器模式
适配器模式将一个类的接口转换成客户但愿的另一个接口,使得本来因为接口不兼容而不能一块儿工做的那些类能够在一块儿工做
示例代码adapter.php
<?php /* 微博提供的登陆类
*/ class Weibo { public function myLogin($username,$password){ echo $username.' is logining weibo with password '. $password. PHP_EOL; } } /* 微信提供的登陆类 */ class Weixin { public function login2($config){ echo $config['username'].' is logining weixin with password '. $config['password']. PHP_EOL; } } /* 咱们设计的适配器接口 */ interface Adapter { public function login($username, $password); } /* 微博的适配器 */ class WeiboAdapter extends Weibo implements Adapter { public function login($username, $password) { $this->myLogin($username, $password); } } /* 微信的适配器类 */ class WeixinAdapter extends WeiXin implements Adapter { public function login($username, $password) { $this->login2(['username'=>$username, 'password'=> $password]); } } /* 主业务类 */ class User { private $adapter; public function setAdapter(Adapter $adapter) { $this->adapter = $adapter; } public function login($username, $password){ $this->adapter->login($username, $password); } } $weiboUser = new User(); // 实例化微博适配器 $adapter = new WeiboAdapter(); // 设置适配器 $weiboUser->setAdapter($adapter); $weiboUser->login('klinson', '123456'); $Wxuser = new User(); // 实例化微博适配器 $adapter = new WeixinAdapter(); // 设置适配器 $Wxuser->setAdapter($adapter); $Wxuser->login('klinson', '123456'); ``` 输出结果 ``` klinson is logining weibo with password 123456 klinson is logining weixin with password 123456 ```
观察者模式有时也被称做发布/订阅模式,该模式用于为对象实现发布/订阅功能:一旦主体对象状态发生改变,与之关联的观察者对象会收到通知,并进行相应操做。
将一个系统分割成一个一些类相互协做的类有一个很差的反作用,那就是须要维护相关对象间的一致性。咱们不但愿为了维持一致性而使各种紧密耦合,这样会给维护、扩展和重用都带来不便。观察者就是解决这类的耦合关系的。
消息队列系统、事件都使用了观察者模式。
PHP 为观察者模式定义了两个接口:SplSubject 和 SplObserver。SplSubject 能够看作主体对象的抽象,SplObserver 能够看作观察者对象的抽象,要实现观察者模式,只需让主体对象实现 SplSubject ,观察者对象实现 SplObserver,并实现相应方法便可。
定义一系列算法,将每个算法封装起来,并让它们能够相互替换。策略模式让算法独立于使用它的客户而变化,也称为政策模式(Policy)
注册树模式
注册模式(Registry)也叫作注册树模式,注册器模式。注册模式为应用中常用的对象建立一个中央存储器来存放这些对象 —— 一般经过一个只包含静态方法的抽象类来实现(或者经过单例模式)。参考laravel
框架的app()
定义
示例代码register.php
<?php class Register { // 树的枝干-用于储存树上的果实(实例) public static $objects; /** 将实例插入注册树中 * ** @param $alias 对象别名-注册树中的名称 ** @param $object 对象实例 */ public static function set($alias, $object) { self::$objects[$alias] = $object; } /** ** 从注册树中读取实例 * ** @param $alias 对象别名-注册树中的名称 * ** @return mixed 返回的对象实例 */ public static function get($alias) { if (isset(self::$objects[$alias])) { return self::$objects[$alias]; } else { echo '您要找的对象实例不存在哦' . PHP_EOL; return false; } } /** ** 销毁注册树中的实例 * ** @param $alias 对象别名-注册树中的名称 */ public static function unset($alias) { unset(self::$objects[$alias]); } } /** ** Class demo 演示类 */ class demo { /* ** 测试方法 */ public function test() { echo '看这里看这里' . PHP_EOL; } } // 实例化测试类,获取对象实例 $demo = new demo(); // 注册到树上 $tree = Register::set('demo', $demo); // 取出来 $de_true = Register::get('demo'); // 测试 $de_true->test(); // 销毁 Register::unset('demo'); // 尝试再次取出来 $de_true_two = Register::get('de'); // 尝试再次测试 var_dump($de_true_two);
输出结果
看这里看这里 您要找的对象实例不存在哦 bool(false)
对称加密又叫作私钥加密,即信息的发送方和接收方使用同一个密钥去加密和解密数据
对称加密的特色是算法公开、加密和解密速度快,适合于对大数据量进行加密
常见的对称加密算法有DES、3DES、TDEA、Blowfish、RC5和IDEA。
其加密过程以下:明文 + 加密算法 + 私钥 => 密文
解密过程以下:密文 + 解密算法 + 私钥 => 明文
对称加密中用到的密钥叫作私钥,私钥表示我的私有的密钥,即该密钥不能被泄露。
其加密过程当中的私钥与解密过程当中用到的私钥是同一个密钥,这也是称加密之因此称之为“对称”的缘由。因为对称加密的算法是公开的,因此一旦私钥被泄露,那么密文就很容易被破解,因此对称加密的缺点是密钥安全管理困难。
非对称加密也叫作公钥加密。
非对称加密与对称加密相比,其安全性更好。对称加密的通讯双方使用相同的密钥,若是一方的密钥遭泄露,那么整个通讯就会被破解。而非对称加密使用一对密钥,即公钥和私钥,且两者成对出现。私钥被本身保存,不能对外泄露。
公钥指的是公共的密钥,任何人均可以得到该密钥。用公钥或私钥中的任何一个进行加密,用另外一个进行解密。
被公钥加密过的密文只能被私钥解密,过程以下:
明文 + 加密算法 + 公钥 => 密文, 密文 + 解密算法 + 私钥 => 明文
被私钥加密过的密文只能被公钥解密,过程以下:(私钥加密,公钥解密通常被用于数字签名。数字签名是用于防篡改和防止假冒的,由于只有一人拥有私钥。甲方经过私钥对数据进行签名,乙方经过甲方的公钥验证签名,若是成功,说明确实是甲方发来的,而且数据没有被修改。一旦相反,公钥是公开的,你们都能作签名,就没意义了)
明文 + 加密算法 + 私钥 => 密文, 密文 + 解密算法 + 公钥 => 明文
因为加密和解密使用了两个不一样的密钥,这就是非对称加密“非对称”的缘由。
非对称加密的缺点是加密和解密花费时间长、速度慢,只适合对少许数据进行加密。
在非对称加密中使用的主要算法有:RSA、Elgamal、Rabin、D-H、ECC(椭圆曲线加密算法)等。
工做特色:
工做原理:
客户端发送请求给服务器,创建一个TCP链接,指定端口号,默认80,链接到服务器,服务器监听到浏览器的请求,一旦监听到客户端的请求,分析请求类型后,服务器会向客户端发送状态信息和数据内容
HTTPS是一种基于SSL/TLS的HTTP协议,全部的HTTP数据都是SSL/TLS协议封装之上传输的
HTTPS是在HTTP协议的基础上,添加了SSL/TLS握手一级数据加密传输,也属于应用层协议
HTTPS为了兼顾安全与效率,同时使用了对称加密(快)和非对称加密(慢)。数据是被对称加密传输的,对称加密过程须要客户端的一个密钥,为了确保能把该密钥安全传输到服务器端,采用非对称加密对该密钥进行加密传输,总的来讲,对数据进行对称加密,对称加密所要使用的密钥经过非对称加密传输。
如下图片来源 图解HTTPS
HTTPS在传输的过程当中会涉及到三个密钥:
服务器端的公钥和私钥,用来进行非对称加密
客户端生成的随机密钥,用来进行对称加密
一个HTTPS请求实际上包含了两次HTTP传输,能够细分为8步。
8.客户端收到服务器发送来的密文,用客户端密钥对其进行对称解密,获得服务器发送的数据。这样HTTPS中的第二个HTTP请求结束,整个HTTPS传输完成。
默认事务型引擎,最重要最普遍的存储引擎,性能很是优秀
数据存储在共享表空间,可经过配置分开
对主键查询的性能高于其余类型的存储引擎
内部作了不少优化,从磁盘读取数据时自动在内存构建hash索引,插入数据时自动构建插入缓冲区
经过一些机制和工具支持真正的热备份
支持崩溃后的安全恢复
支持行级锁
支持外键
5.1版本前是默认引擎
拥有全文索引、压缩、空间函数
不支持事务和行级锁,不支持奔溃后安全恢复
表存储在两个文件,MYD和MYI
设计简单,某些场景下性能很好
Archive、Blackhole、CSV、Memory
当多个查询同一时刻进行数据修改时,会产生并发控制的问题
系统性能开销最小,会锁定整张表,myisam使用表锁
最大程度的支持并发处理,可是也带来了最大的锁开销,innodb实现行级锁
char是定长的,根据定义的字符串长度分配足量空间 char会根据须要采用空格进行填充以方便比较 char适合存储很短的字符串,或者全部值都接近同一个长度 char长度超过设定的长度,会被截断
varchar用于存储可变长字符串,比定长类型更加节省空间 varchar使用1或2个额外字节记录字符串的长度,列长度小于255字节用1个字节表示,不然用2个 varchar长度超过设定的长度,会被截断
对于常常变动的数据,char比varchar更好,char不容易产生碎片 对于很是短的列,char比varchar在存储空间上更有效率 只分配真正须要的空间,更长的列会消耗更多的内存
set profiling=1;
开启,服务器上执行的全部语句消耗时间都会记录到临时表。show profile for query QUERY_ID
查询指定查询count(*)
会忽略全部列,直接统计全部列数,所以不要用count(列名)
GROUP BY
和ORDER BY
中只有一个表的列,这样MySQL才有可能使用索引GROUP BY
和DISTINCT
,创建索引进行优化LIMIT
分页,能够经过记录上次查询的最大ID,若是根据id排序时,下次查询根据该ID来查询(如:ID > maxID)UNION
查询,UNION ALL
性能比UNION
高对用户而言,分区表是一个独立的逻辑表,可是底层MySQL将其分红了多个物理子表,对于用户来讲是透明的,每个分区表都会使用一个独立的表文件。
建立表的时候使用partition by
子句定义每一个分区存放的数据,执行查询时,优化器会根据分区定义过滤那些没有咱们须要数据的分区,这样查询只须要查询所需数据在的分区便可
分区的主要目的是将数据按照一个较粗的粒度分在不一样的表中,这样能够将相关的数据存放在一块儿,并且若是想一次性删除整个分区的数据也很方便
经过一些HASH算法或者工具实现将一张数据表垂直或者水平物理切分
使用场景: 1. 表中数据自己就有独立性,例如表中分别记录各个地区的数据或者不一样时期的数据,特别是有些数据经常使用,有些不经常使用 2. 须要把数据存放在多个介质 缺点: 1. 给应用增长复杂度,一般查询时须要多个表名,查询全部数据都须要UNION操做 2. 在许多数据库应用中,这种复杂性会超过他带来的优势,查询时会增长读一个索引层的磁盘次数
使用场景: 1. 若是一个表中某些列经常使用,而另一些列不经常使用 2. 可使数据行变小,一个数据页能存储更多数据,查询时减小I/O次数 缺点: 1. 管理冗余列,查询全部数据须要JOIN操做 2. 有些分表的策略基于应用层的逻辑算法,一旦逻辑算法改变,整个分表逻辑都会改变,扩展性较差 3. 对于应用层来讲,逻辑算法无疑增长开发成本
用一个处理程序文件处理全部的HTTP请求,根据请求时的参数的不一样区分不一样的模块和操做请求
PHP是一种HTML内嵌式在服务端执行的脚本语言,可是PHP又不少可使PHP代码和HTML代码分开的模板引擎,例如:smarty
模板引擎就是庞大的完善的正则表达式替换库
示例代码sort.php
原理:两两相邻的数进行比较,若是反序就交换,不然不交换
时间复杂度:最坏(O(n^2)), 平均(O(n^2))
空间复杂度:O(1)
function bubbling_sort($arr) { $len = count($arr); if ($len <= 1) return $arr; for ($i = 0; $i < $len - 1; $i++) { for ($j = 0; $j < $len - $i -1; $j++) { if ($arr[$j] > $arr[$j+1]) { $tmp = $arr[$j+1]; $arr[$j+1] = $arr[$j]; $arr[$j] = $tmp; } } } return $arr; }
原理:经过一趟排序将要排序的数据分割成独立的两部分,其中一部分的全部数据和另外一部分的全部数据都要笑,而后按照此方法对这两部分数据分别进行快速排序,整个排序过程能够递归完成
时间复杂度:最坏(O(n^2)), 平均(O(nlog2n))
空间复杂度:最差(O(n)),平均(O(log2n))
function quick_sort($arr) { $len = count($arr); if ($len <= 1) return $arr; $base = $arr[0]; $left = []; $right = []; for ($i = 1; $i < $len; $i++) { if ($arr[$i] > $base) $right[] = $arr[$i]; else $left[] = $arr[$i]; } $left = quick_sort($left); $right = quick_sort($right); return array_merge($left, [$base], $right); }
原理:每次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,知道所有待排序的数据元素排外
时间复杂度:最坏(O(n^2)), 平均(O(n^2))
空间复杂度:O(1)
function select_sort($arr) { $len = count($arr); if ($len <= 1) return $arr; for ($i = 0; $i < $len - 1; $i++) { $min = $i; for ($j = $i+1; $j < $len; $j ++) { if ($arr[$min] > $arr[$j]) { $min = $j; } } if ($min !== $i) { $tmp = $arr[$i]; $arr[$i] = $arr[$min]; $arr[$min] = $tmp; } } return $arr; }
原理:每次从无序表中取出第一个元素,把他插入到有序表的合适位置,使有序表仍然有序
时间复杂度:最坏(O(n^2)), 平均(O(n^2))
空间复杂度:O(1)
原理:把待排序的数据根据增量分红几个子序列,对子序列进行插入排序,知道增量为1,直接插入进行插入排序;增量的排序,通常是数组的长度的一半,再变为原来增量的一半,直到增量为1
时间复杂度:最坏(O(n^2)), 平均(O(nlog2n))
空间复杂度:O(1)
原理:把待排序的元素按照大小在二叉树位置上排序,排序好的元素要知足:父节点的元素要大于子节点;这个过程叫作堆化过程,若是根节点存放的最大的数,则叫作大根堆,若是是最小,就叫小跟堆,能够把根节点拿出来,而后再堆化,循环到最后一个节点
时间复杂度:最坏(O(nlog2n)), 平均(O(nlog2n))
空间复杂度:O(1)
原理:将两个(或两个以上)有序表合并成一个新的有序表,即把待排序序列分为若干个有序的子序列,再把有序的子序列合并为总体有序序列
时间复杂度:最坏(O(nlog2n)), 平均(O(nlog2n))
空间复杂度:O(n)
原理:从数组的中间元素开始,若是中间元素正好是要查找的元素,搜索结果,若是某一个特定元素大于或者小于中间元素的那一半中查找,并且跟开始同样从中间开始比较,若是某一步骤数组为空,表明找不到
时间复杂度:最坏(O(nlog2n)), 平均(O(nlog2n))
空间复杂度:迭代(O(1)), 递归(O(log2n))
原理:按必定的顺序检查数组中每个元素,直到要找到锁要寻找的特定指为止
时间复杂度:最坏(O(n)), 平均(O(n))
空间复杂度:O(1)
B-Tree是为磁盘等外存储设备设计的一种平衡查找树
一棵m阶的B-Tree有以下特性:
B+Tree是在B-Tree基础上的一种优化,使其更适合实现外存储索引结构,InnoDB存储引擎就是用B+Tree实现其索引结构。
B+Tree相对于B-Tree有几点不一样:
ab,wrk,Apache JMeter, http_load, Web Bench, Siege
# 模拟并发请求100次,总请求5000次 ab -c 100 -n 5000 http://example.com
防止别人经过一些技术手段绕过本站的资源展现页面,盗用本站的资源,让绕开本站资源展现页面的资源连接失效,能够大大减轻服务器及带宽的压力
valid_referers none|blocked|server_names|string...;
配置例子:
location ~.*\.(gif|jpg|png|flv|swf|rar}zip)$ { valid_referers none blocked imooc.com *.imooc.com; if ($invalid_referer) { #return 403; rewrite ^/ http://www.imooc.com/403.jpg; } }
优先级:Pragma > Cache-Control > Expires
add_header name value [always];
,能够设置Pragma、Expires、Cache-Control,能够继承expires time;
etag on|off
,默认ongzip on|off; #是否开启gzip gzip_buffers 32 4K|16 8K; #缓冲(在内存中缓存几块?每块多大) gzip_comp_level [1-9] #推荐6,压缩级别(级别越高,压得越小,越浪费CPU计算资源) gzip_disable #正则匹配UA,什么样的Uri不进行gzip gzip_min_length 200 #开始压缩的最小长度 gzip_http_version 1.0|1.1 #开始压缩的http协议版本 gzip_proxied #设置请求者代理服务器,该如何缓存内容 gzip_types text/plain application/xml image/png #对哪些类型的文件压缩,如txt、xml、css gzip_vary on|off #是否传输gzip压缩标志
将现有的PHP等动态语言的逻辑代码生成为静态的HTML文件,用户访问动态脚本重定向到静态HTML文件的过程。对实时性要求不高
ob_start();//打开输出控制缓冲 ob_get_content();//返回输出缓冲区内容 ob_clean();//清空输出缓冲区 ob_end_flush();//冲刷出(送出)输出缓冲区内容并关闭缓冲
是计算机中程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单元,是操做系统结构的基础。进程是一个执行中的程序
进程的三态模型:运行、就绪、阻塞
进程的五态模型:新建态、活跃就绪/静止就绪、运行、活跃阻塞/静止阻塞、终止态
线程是进程中的一个实体,是被系统独立调度和分派的基本单位,线程本身不拥有系统资源,只拥有一点儿在运行中必不可少的资源但它可与同属一个进程的其它线程共享进程所拥有的所有资源。
一个线程能够建立和撤消另外一个线程,同一进程中的多个线程之间能够并发执行。
线程是程序中一个单一的顺序控制流程。进程内一个相对独立的、可调度的执行单元,是系统独立调度和分派CPU的基本单位指运行中的程序的调度单位。
在单个程序中同时运行多个线程完成不一样的工做,称为多线程。
协程是一种用户态的轻量级线程,协程的调度彻底由用户控制。协程拥有本身的寄存器上下文和栈。协程调度切换时,将寄存器上下文和栈保存到其余地方,在切回来的时候,恢复先前保存的寄存器上下文和栈,直接操做栈则基本没有内核切换的开销,能够不加锁的访问全局变量,因此上下文的切换很是快。
如今各类高并发异步IO的服务器程序都是基于epoll实现的
IO复用异步非阻塞程序使用经典的Reactor模型,Reactor顾名思义就是反应堆的意思,它自己不处理任何数据收发。只是能够监视一个 socket句柄的事件变化
常见reactor模型
查询缓存能够看作是SQL文本和查询结果的映射,第二次查询的SQL和第一次查询的SQL全相同,则会使用缓存
表的结构或数据发生改变时,查询缓存中的数据再也不有效
query_cache_type
查询缓存类型,有0、一、2三个取值。0则不使用查询缓存。1表示始终使用查询缓存。2表示按需使用查询缓存。
query_cache_size
默认状况下 query_cache_size
为0,表示为查询缓存预留的内存为0,则没法使用查询缓存
SET GLOBAL query_cache_size= 134217728
querycache_type
为1时,亦可关闭查询缓存
SELECT SQL_NO_CACHE FROM my_table WHERE condition;
query_cache_type
为2时,可按需使用查询缓存
SELECT SQL_CACHE FROM my_table WHERE condition;
查看命中次数
SHOW STATUS LIKE'Qcache_hits';
清理缓存
FLUSH QUERY CACHE∥清理查询缓存内存碎片 RESET QUERY CACHE∥从查询缓存中移出全部查询 FLUSH TABLES;//关闭全部打开的表,同时该操做将会清空查询 缓存中的内容
redis
/memcache
缓存参考资料[关于Redis的一些思考和总结
](https://www.jianshu.com/p/b88...
对cpu会成为Redis的性能瓶颈的担心是能够理解的,可是在实际使用过程当中cpu或许不是制约Redis的关键因素,网络io可能才是最大的瓶颈。
由于CPU并非Redis的瓶颈,Redis的瓶颈最有多是机器内存或者网络带宽。既然单线程容易实现,并且CPU不会成为瓶颈,那么久瓜熟蒂落的采用了单线程的方案。
no-enviction(驱逐):禁止驱逐数据
尽可能使用 Inno DB存储引擎
基于URL等应用层信息的负载均衡
Nginx的 proxy是它一个很强大的功能,实现了7层负载均衡
功能强大,性能卓越,运行稳定
配置简单灵活
可以自动剔除工做不正常的后端服务器
上传文件使用异步模式
支持多种分配策略,能够分配权重,分配方式灵活
内置策略: IP Hash、加权轮询
扩展策略:fair策略、通用hash、一致性hash
首先将请求都分给高权重的机器,直到该机器的权值降到了比其余机器低,才开始将请求分给下一个高权重的机器
当全部后端机器都down掉时,Ngnx会当即将全部机器的标志位清成初始状态,以免形成全部的机器都处在 timeout的状态
Nginx内置的另外一个负载均衡的策略,流程和轮询很相似,只是其中的算法和具体的策略有些变化
IP Hash算法是一种变相的轮询算法
根据后端服务器的响应时间判断负载状况,从中选出负载最轻的机器进行分流
通用hash比较简单,能够以 Nginx内置的变量为key进行hash,
一致性hash采用 Nginx了内置的一致性hash环,支持 memcache
http { upstream cluster { server srvl; server srv2; server srv3; } server { listen 80; location / proxy_pass http: //cluster; } }
经过报文中的目标地址和端口,再加上负载均衡设备设置的服务器选择方式,决定最终选择的内部服务器
LvS实现服务器集群负载均衡有三种方式,NAT,DR和TUN
通过特殊构造的键值, 使得PHP每一次插入都会形成Hash冲突, 从而使得PHP中array的底层Hash表退化成链表
哈希表是经过特定的哈希算法将索引转换成特定的index而后映射到对应的槽中,而后采用拉链法,在一个槽中使用链表将数据进行存储,链表的时间复杂度为O(n)。
这样在每次插入的时候须要遍历一遍这个链表, 你们能够想象, 第一次插入, 须要遍历0个元素, 第二次是1个, 第三次是3个, 第65536个是65535个, 那么总共就须要65534*65535/2=2147385345次遍历….
PHP的Hash算法是开源的, 已知的, 因此有心人也能够作到
示例攻击数据
{ "format": "json", "list": { "v1" : 1, "攻击数据":{ "0":0, "65536":0, "131072":0, ………… "234553344":0 } } }
php示例代码hash.php
<?php $size = pow(2, 16); $startTime = microtime(true); $array = array(); for ($key = 0, $maxKey = ($size - 1) * $size; $key <= $maxKey; $key += $size) { $array[$key] = 0; } $endTime = microtime(true); echo '插入 ', $size, ' 个恶意的元素须要 ', $endTime - $startTime, ' 秒', "\n"; $startTime = microtime(true); $array = array(); for ($key = 0, $maxKey = $size - 1; $key <= $maxKey; ++$key) { $array[$key] = 0; } $endTime = microtime(true); echo '插入 ', $size, ' 个普通元素须要 ', $endTime - $startTime, ' 秒', "\n";
输出结果
插入 65536 个恶意的元素须要 5.0739450454712 秒 插入 65536 个普通元素须要 0.0010519027709961 秒
max_input_vars
=> 1000