zoukankan      html  css  js  c++  java
  • 某公司后端开发工程师面试题学习

    最近看到的某公司后端开发工程师面试题,拿来研究学习一下,感觉提高技术,看面试题也是一个挺好的方法:(

     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 中储存的数字值增一。

            如果 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。其他进程也无法执行该操作了。

          2)可以用redis缓存实现锁。前面答案已经描述。这个适用于随机响应的情况,如果需要响应每一个请求,且按请求的先后顺序进行依次处理。则不太适合,应当构建队列。

          3)使用队列来响应并发请求(队列依然依赖redis的list数据结构实现)。来一个排队一个,依次处理。处理程序可以用php写一个守护程序。按顺序去redis里的list去取请求处理,如果list为空,则等待1秒再去取。(大概逻辑是这样)。

      4.这个网上答案很多。

          区别:1)myisam的text支持索引,innodb不支持;

                     2)innodb支持事务,myisam不支持,对于InnoDB每一条SQL语言都默认封装成事务,自动提交,这样会影响速度,所以最好把多条SQL语言放在begin和commit之间,组成一个事务;

                    3)innodb有行锁,myisam只是表锁;

                    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线程会把相关的“事件”执行到自己的数据库中,以此实现从数据库和主数据库的一致性,也就实现了主从复制。

    具体参考:https://www.cnblogs.com/gl-developer/p/6170423.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

    作者:Leven
    本博客主要记录个人工作和学习中的一些总结,经验和感悟。欢迎转载和评论,转载请给出原文链接。
    您也可以通过邮箱联系我:leven_developer#outlook.com
    如果文章对您有所帮助,您可以给我一点打赏,会让我更有动力做所从事的事情,非常感谢。
  • 相关阅读:
    高并发编程之基础概念
    使用JAXB实现Bean与Xml相互转换
    python语法(五)—函数
    2018年终总结
    python语法(四)— 文件操作
    excel开发
    spring 常用注解,@primary注解
    spring中InitializingBean和@Bean的初始化,bean初始化
    @PostConstruct 注解
    LocalDateTime java8
  • 原文地址:https://www.cnblogs.com/Andres/p/8830962.html
Copyright © 2011-2022 走看看