phper必知必会(二)
1.说说你对进程,线程以及协程的理解
进程:是系统进行资源分配和调度的基本单位,是基本操作系统结构的基础。进程是程序基本执行的实体。进程与进程之间是独立的,拥有完全独立的地址空间,进程的切换只发生在内核态,由操作系统调度。
线程:线程是操作系统进行运算调度的最小单位。它被包含在进程之中,是进程中实际运作的运行单位。一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。
协程:是一种用户态的轻量级线程,协程的调度完全由用户控制。携程拥有自己的寄存器上下文和栈。协程调度切换时,将寄存器上下文和栈保存在其它地方,在切回来的时候,恢复之前保存的寄存器上下文和栈,直接操作栈则基本没有内核切换的开销,可以不加锁的访问全局变量,所以上下文切换的非常快,执行协程只需要极少的栈内存。
2.请比较下memcached,redis,并说明下redis的常见应用场景
1.redis支持的数据类型比较多不仅支持常见k/v类型还支持list,set,hash等类型,它比memcached更像数据库
2.memcached只是简单的key/value的缓存,被用来做常规的缓存处理
3.memcached不支持持久化存储,它把全部数据存储在内存中,断电或重启时数据会掉
4.redis支持数据持久化,所以断电或者重启后之前落地的数据还可以找到
5.redis支持数据的备份,即master-slave模式的数据备份,memcached可以使用一致性hash做分布式
6.redis使用的是单线程模型,保证了数据按顺序提交,memcached使用的是cas保证数据一致性。cas(check and set)是一个确保并发一致性的机制,属于“乐观锁”范畴;原理就是拿版本号,操作对比版本号,如果一致就操作不一致就放弃。
redis常见应用场景:
排行榜:如果使用传统的关系型数据库来做这个事儿,还是有点麻烦的,如果使用redis的sortSet数据结构能够非常方便搞定。
计数器/限速器:redis中原子性的强悍的自增操作,可以用来统计点赞数,文章的阅读数,以及电商活动中的秒杀抢购中房子用户疯狂点击所带来的不必要的压力
好友关系:使用集合的求交集,并集,差集可以方便处理共同好友,相同爱好等一些功能
简单的消息队列:如果使用mysql来做无疑会对db产生一些压力,如果针对不是特别大队列任务处理的话,可以使用redis的消息队列功能,将一些需求和任务写到redis队列,异步处理
session共享:这个其实是针对分布式部署来说的,session一般是保存在服务器中的,如果流量请求分摊到多台服务器后,这样用户的会话就会产生问题,这个时候可以通过php的配置来将session统一存储在redis中来报错session的统一性。
3.mysql中的myisam和innodb数据库存储引擎的区别
1、存储结构
myisam:存储数据落在三个文件。.FRM文件存储表定义,.MYD数据文件,.MYI索引文件。
innodb:存储在两个文件,.frm存储表定义,.ibd其它数据
2、存储空间
myisam:可被压缩,存储空间较小
innod:需要更多的内存和存储空间
3、可移植性、备份及恢复
myisam:数据是以文件形式存储,可移植性强,直接拷贝文件即可。
innodb:使用binlog,mysqldump备份,数据过大就比较费时比较痛苦
4、事务支持
myisam:强调性能查询速度快,不支持事务
innodb:支持事务,外键等功能
5、AUTO_INCRMENT
myisam:可以和其它字段建立联合索引
innodb:具有自动增长的字段索引必须是独立的,如果和其它字段组合必须排在第一列
6、锁
myisam:只支持表级锁
innodb:支持事务和行级锁。但是innodb的行锁,只是在where的主键是有效的,非主键where会锁全表
7、全文索引
myisam:支持FULLTEXT类型的全文索引
innodb:不支持FULLTEXT全文索引,不过可以使用其它第三方的引擎支持比如sphinx
8、表主键
myisam:允许没有任何索引和主键的存在,索引都是保持行的地址
innod:如果没有设置主键,会自动创建一个用户不可见6直接的主键,数据是主索引的一部分,附加索引保存的是主索引的值
9、表的具体行数
myisam:保存有表的总行数,如果select count,会直接取出快速
innodb:没有直接保持总行数,查询所有需要遍历整个表,若增加where条件后跟myisam处理方式一样
10、CURD操作
myisam:大量查询适合使用该引擎
innod:大量的insert,update适合使用该引擎。
11、外键
myisam:不支持外键
innodb:支持外键功能
4.阐释数据库事务的ACID的四个特性
原子性(Atomicity):一个事务必须被视为一个不可分割的最小工作单元,整个事务中的所有操作要么全部提交完成,要么全部失败回滚,对于一个事务来说,不可能只执行其中的一部分操作。
一致性(Consistency):数据库总是从一个一致性的状态转换到另一个一致性的状态。
隔离性(Isolation):一个事务所做的修改在最终提交之前,对其它事务是不可见的。
持久性(Durability):一旦事务提交,则其修改会永远的保存在数据库中。
5.阐述mysql的4种隔离级别
读未提交(read-uncommitted):事务可以读取未提交的数据,这也被称为脏读。
读提交(read-committed):一个事务从开始直到事务提交之前,所做的任何修改对其他事务都是不可见的。
可重读(repeatable-read)mysql默认事务级别:当某个事务在读取某个范围内的记录时,另外一个事务又在该范围内插入了新的记录,当之前的事务再次读取该范围的记录时,会产生幻读。
可串行化(serializable)最高事务级别:避免了前面说的幻读,即在读取没一行数据上都加锁,所以可能导致大量的超时和锁争用的问题。
6.select count(*),select count(1),select(column)的区别
1.一般情况下select count(*)与select count(1)结果和速度是一样的,即查询所有
2.count(column)对特定的值具有行数进行计算,不包含空值,所以结果可能会有些不一样(可能会比count(*)统计的要少)
3.count(*)对行的数目进行计算,包括null
4.如果没有主键,那么count(1)要比count(*)快
5.如果表中只有一个字段,count(*)最快
6.一般来说大多情况下count(*)是最优的选择
7.如果理解oop?
oop即面向对象编程,在面向对象编程中最重要的两个概念就是类和对象。
时间万物都有其属性和特点或者说特性,我们将这些属性特性进行整合起来形成一个类,比如具有猫科类的特点和属性的我们称为猫科类。这个时候猫科类只是具有这类的属性的抽象模型,如果要具体要是那种猫或者说需要得到一个具体的实体这个时候就需要对类进行实例化,类在实例化后就是对象了,此时的猫就是一个更加具体存在的对象。
在编程世界里,就是通过这种思想将具有相同的属性的和特性进行就行管理,组合生一个类,类中有对应的属性和实现的方法,通过一些初始化和实例化,或者调用一些方法来达到我们需要的功能。
面向对象中有三大特点:
1.封装性
也成为隐藏性,就是将使用和具体实现分开,只对外开放部分接口和方法与外部联系,或者说只公开一部分供开发人员使用的方法和参数。
2.继承性
子类自动继承父类的属性和方法,并可以通过添加新的属性和方法来对部分属性和方法进行重写,这样增加了代码的重用性。
3.多态性
虽然说父类只有一个,但是可以有多个子类,这些子类中虽然调用的相同的属性或者方法,但是由于继承性这个的存在和重写,实例化后这些子类却可以或者完全不同的结果,得到不同形态的东西,这种技术就是多态性。
8.请阐述http与https的区别
1.https协议需要到ca申请证书,一般免费证书较少,因而需要一定费用
2.http是超文本传输协议,信息是明文传递,https则是更具有安全性的ssl加密传输协议
3.http和https使用的是完全不同的连接方式,用的端口也不一样,前者是80后者是443
4.http的连接很简单,是无状态的,https协议是由http+ssl协议构建的可进行加密传输,身份认证的网络协议,比http协议安全
9.使用php的三种方式获指定取路径下的文件夹和文件
方法一:通过opendir获取资源句柄,再使用readdir函数并遍历获取
$dir = "/data/wwwroot/test";
function oneReadDirs($dir){
$handle = opendir($dir);
$outStr = '';
while(($item = readdir($handle))!==false){
if($item!='.' && $item!='..' ){
$path = $dir.'/'.$item;
if(is_file($path)){
$outStr .= '[文件] '.$item.PHP_EOL;
}elseif(is_dir($path)){
$outStr .= '[目录] '.$item.PHP_EOL;
}
}
}
return $outStr;
}
$dirs = oneReadDirs($dir);
echo $dirs;
方法二:使用scandir一次性获取路径下的所有文件夹和文件再进行处理
function twoReadDirs($dir){
$dirs = scandir($dir);
$outStr = '';
foreach($dirs as $k=>$v){
$path = $dir.'/'.$v;
if($v!=='.' && $v!=='..' ){
if(is_file($path)){
$outStr .= '[文件] '.$v.PHP_EOL;
}elseif(is_dir($path)){
$outStr .= '[目录] '.$v.PHP_EOL;
}
}
}
return $outStr;
}
$dirs2 = twoReadDirs($dir);
echo $dirs2;
方法三:使用面向对象的dir处理方式获取
function threeReadDirs($dir){
$d = dir($dir);
$outStr = '';
while(($item = $d->read())!==false){
if($item!='.' && $item!='..' ){
$path = $dir.'/'.$item;
if(is_file($path)){
$outStr .= '[文件] '.$item.PHP_EOL;
}elseif(is_dir($path)){
$outStr .= '[目录] '.$item.PHP_EOL;
}
}
}
$d->close();
return $outStr;
}
$dirs3 = threeReadDirs($dir);
echo ($dirs3);
输出结果为:
[目录] app
[文件] index.html
[目录] cache
[文件] .htaccess
[目录] .phalcon
[目录] public
10.写一个函数算出两个文件的相对路径
$path1 = '/a/b/c/d/e/f/g/h/e.php';
$path2 = '/a/b/1/2/c.php';
function getRelativePath($path1, $path2){
$arr1=explode('/',dirname($path1));
$arr2=explode('/',dirname($path2));
for($i=0, $len=count($arr2); $i<$len; $i++ ){
if($arr1[$i]!=$arr2[$i]){
break ;
}
}
if($i<$len){
$return_path=array_fill(0,$len-$i,'..');
}
//$path1相对于$path2
$return_path=array_merge($return_path,array_slice($arr1,$i));
return implode('/',$return_path);
}
echo getRelativePath($path1,$path2);
//../../c/d/e/f/g/h