某公司后端开发工程师面试题学习

最近看到的某公司后端开发工程师面试题,拿来研究学习一下,感受提升技术,看面试题也是一个挺好的方法:(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

相关文章
相关标签/搜索