这是一本反面教材,希望也能引起部分程序员的警惕。这半个月,经过几次面试,我差不多已经确立了自己的定位——离腾讯T3的定位还有一点距离。因为在小公司呆惯了(6年),公司里没有人在技术水平上超过我。作为技术核心,我觉得自己很优秀。生活在一个小圈子里,很难主动去了解新技术。php和js本身都算不上精通。所以当事故发生的时候,我才意识到自己的技术是多么的脱节。之前的面试虽然没有特别准备,但是和6年前找工作的时候相比,差距还是很大的。以下是我遇到的部分面试题。我尝试使用我所知道的知识来发表声明。肯定会有很多误解和疏漏。希望大家指正。公司1:1,mysql_real_escape_string和mysql_escape_string有什么本质区别,有什么用,为什么不推荐使用?答:mysql_real_escape_string需要提前连接好数据库,数据库连接可以作为第二个参数传入(不填则使用之前的连接)。两者都是对插入数据库的数据进行转义,但是mysql_real_escape_string进行转义时,数据库连接会被认为是字符集。它们用于让数据正常插入数据库,防止sql注入,但不能100%防止sql注入。再问:为什么不能100%预防?答:由于客户端编码和服务端编码不同,可能会出现注入问题,但这种情况其实很少见。继续回答:被弃用的原因是官方不再推荐使用mysql_xx数据库操作方式。推荐使用pdo和mysqli,因为mysqli在性能和安全性上都优于mysql。衍生出的问题是mysqli的连接复用(持久化)问题,我没有很好的回答。2、什么是内存泄漏,js内存泄漏是怎么发生的?答:内存泄漏是因为一块分配的内存在浏览器进程结束之前既不能使用也不能回收。泄漏的原因是闭包在函数中维护了局部变量,无法释放,尤其是在使用闭包且有外部引用和setInterval时危害很大。备注:我觉得这个回答不好,因为肯定不是关闭的原因。查了资料,从一个比较浅的位置回答了这个问题:泄露的原因有几种:(1)页面元素被删除了,但是元素绑定的事件没有被删除;(2))闭包在函数中维护局部变量(外部不可控),使其无法被释放;(3)意外的全局变量;(4)引用被删除,但是引用里面的引用在内存中还存在。从以上原因来看,内存泄漏的根本原因是引用不能正确回收,值类型不能导致内存泄漏。对于每个引用,它都有自己的引用计数。当引用计数归零或者被标记清零时,js垃圾回收器会认为引用被回收了。3、什么是闭包,它与原型链、作用域链的关系是什么?答:闭包是指存在于作用域链分支的函数域中的函数。直到你找到它。当闭包有外部引用时,js会维护闭包本身和函数作用域链的内存状态。注意:这是我自己的废话。继续回答:与原型链无关。函数的原型(prototype)主要用来实现继承。原型链可以用来追溯继承关系。类似于作用域链,它会逐步访问属性,直到找到为止。原型链的最顶层是null,可以理解为所有对象都继承自null,所以null的类型是object。继续回答:作用域链可以看成一个树形结构,从根节点窗口向下展开。下层节点可以访问上层节点,上层节点不能访问下层节点。生成闭包的函数作用域属于其中一个节点,向下扩散后,闭包函数生成叶子节点,叶子节点可以互相访问。当访问的变量在叶节点中找不到时,会向上层节点查找,直到找到为止。这个概念有点类似于原型链上的概念。属性查找。4、一台电脑的配置无限好,可以同时打开多少个网页答:65535-1000=64535(端口数)5、ip地址可以伪造吗?答:http头是可以被篡改的,但是只能修改X_FORWARDED_FOR。真实ip地址(REMOTE_ADDR)很难修改(除非被路由器修改),因为真实ip是底层sessionip地址,并且因为TCP3次握手的存在,无法建立连接,伪造意义不大。至于UDP,一般用于内网通信。6、一百万个奖品,每人可中3个奖品,先到先得,如何控制并发,不能被超发,保证完整的先到先得模式答:百万奖品预先插入到数据库经过洗牌后,所有获胜的操作只能更新,不能插入。进入抽奖的用户使用memcahe原子锁实现抽奖次数的自增。当开奖次数达到3次时,返回未中奖。再问:预插需要大量资源,如果奖品数量达到1亿怎么办?答:使用redis队列存储请求,异步运行守护进程分发奖品。问题是用户无法实时看到中奖状态。再问:这肯定不行。复答:使用全局内存锁保证开奖进程在单进程运行,但是会面临大并发阻塞的问题。再问一下:内存比较珍贵,不需要锁内存怎么办,如果有一个亿的奖池,预插入数据库肯定不好,怎么办?答:设置中奖概率,分三张表,全部使用innodb引擎,一张保存中奖记录(预先插入一行),一张保存中奖分布概况,一张保存用户开奖情况(uinuniqueindex),在大并发的情况下,使用mysql的独占锁进行并发控制。流程如下:开始查询用户开奖次数,加排他锁更新用户开奖次数/插入锁行查询分配状态,获取开奖结果(有些奖品发放后,概率会动态变化)更新分布表,插入中奖记录commit然后问:遇到脏读怎么办?答:我对这方面了解不多。那么请问:innodb的master线程在什么情况下会fork其他子线程呢?答:不知道7.数据链路层的数据是如何校验的,有哪些校验方式?答:crc32,其他校验可能是奇偶校验的模校验。备注:crc校验即可。8、b+树的查询时间复杂度是多少,哈希表是什么?为什么数据库索引存储在b+树而不是哈希表中?数据库索引存储还有其他数据结构吗?答案:O(log(n)),O(1)因为哈希表是哈希的,遇到key>'12'的搜索条件时不起作用,空间复杂度高。备注:b+数根据层数决定时间复杂度。在数据量大的情况下,一般有4-5层,然后用二分法在页面中查找数据。时间复杂度远小于log(n)。9、apache如何与php通信,什么是sapi?答:使用sapi进行通信,sapi是php封装的对外数据传输接口,通常有四种运行模式:cgi/fastcgi/cli/apache2handler。10.PHP的垃圾回收机制?答:垃圾回收是指当php的运行状态结束时,比如exit/die/fatalerror/script运行结束,php需要回收运行过程中创建的变量和资源的内存。ZEND引擎维护了一个栈zval,每一个创建的变量和资源都会被压入这个栈中,每次压入的数组结构类似:[refcount=>int,is_ref=>0|1,value=>union,type=>string],当变量未设置时,如果ref_count变为0,就会被回收。当遇到变量循环引用自身时,使用同步回收算法进行回收。注:PHP7对zal的结构进行了改写。11.jquery的sizzleengine的工作原理答:除了是一个DOM元素搜索引擎,我什么都不知道。12、seajs的工作原理,如何解决库重复加载的问题,如何同步加载资源答:建立映射关系,缓存;资源不能同步加载,只能返回回调。13、memcache和redis的区别答:可存储的数据结构不同;redis支持持久化存储。14、md5的逆向原理答:先用字典查,再尝试暴力破解。再问:没有更好的办法吗?答:不再是了。备注:嗯,其实真的没有什么特别好的办法。我们只能用TB级别的海量特征库存入数据库,然后分片搜索。15、父类方法protected,子类重构为private。会发生什么?答:会出现致命错误,因为继承的方法或属性只能保持或放大权限,不能降低。例如,将protected重载为public是可行的。16、工作越细越好。答:0,浏览器本地缓存匹配;1、本地hosts映射比较;2、本地dns缓存分析;3、远程dns解析获取服务器ip地址;4、浏览器发送tcp连接请求包(syn);5、请求报文在传输层、网络层、数据链路层进行封装,通过网卡到达路由器;6、路由器将数据包转发给运营商的服务器;7、运营商的服务器通过中继节点通过最短寻址路径到达指定的ip地址;8.、服务器端可能有反向代理或者负载均衡,直接将请求转发给上游服务器。当然也可以制定安全防御规则,直接丢弃请求包;9、上游服务器收到连接请求,如果可用则返回。(同步+确认);10、浏览器检查ack并再次发送(syn+ack);11、服务端检查ack将连接状态切换为已建立,然后根据请求发送数据包;12.当transform-encoding为chunked时,浏览器开始渲染页面;13.挥手四次,关闭连接;14.渲染数据完成。备注:还有很多不懂的地方,有些东西自己完全看不懂。由于时间关系,后面有时间再详细画。17、keep-alive的概念Answer:长连接机制是指在keep-alive-timeout时间内,如果连接没有关闭,不再需要三次握手再次传输数据。备注:这里也有很多疑问,需要认真梳理。18、linux文件压缩操作命令、shell脚本等备注:因为平时开发都是在windows环境下,对linux缺乏了解,所以这部分几乎是0分。公司2:这是最被鄙视的公司。首先会有笔试,比较简单,但是也有一些坑,很多都忘记了。印象最深的是,我说我熟悉常见的设计模式,然后让我画UML类图,我一头雾水,所以写简历的时候最好写你很熟悉的东西,如果你只是略知一二,没必要放在简历里。公司3:这里只是问了几个问题:1、设计一个中继服务器,转发客户A->客户B的请求;2、myisam和innodb有什么区别;3、php进程死锁的原因是什么?如何自动检查自动恢复?4.有classA{publicfunctionb($a,$b,$c){}};如何使用['b'=>2,'a'=>1,'c'=>3]顺利执行A::b的调用赋值?5、php5.2->php7.1各版本的演变历史,新特性等?6.画个tcp三向握手图,还在找工作。在我看来,一个8年的程序员不应该是这样的。温水煮青蛙的教训是非常惨痛的。幸运的是,现在意识到问题还为时不晚,等到35岁,可能真的晚了。注:本文为八年phper高级工程师面试之路转载
