PHP之面试题总结
总结一些面试题,有备无患,走起...
1.熟悉的 nosql 和 sql 有什么区别(优势,劣势)
Memcache,Redis 都是内存数据库 redis是一个开源的支持多种数据类型的key=>value的存储数据库。支持字符串、列表、集合、有序集合、哈希五种类型 memcache 只支持简单的key/value数据结构,不像Redis可以支持丰富的数据类型。 无法进行持久化,数据不能备份,只能用于缓存使用,且重启后数据全部丢失
2.实现PHP5中的 var_dump 函数
<?php function mydump() { $args = func_num_args(); for($i = 0;$i < $args; $i ++) { $param = func_get_arg($i); switch(gettype($param)) { case 'NULL' : echo 'NULL'; break; case 'boolean' : echo ($param ? 'bool(true)' : 'bool(false)'); break; case 'integer' : echo "int($param)"; break; case 'double' : echo "float($param)"; break; case 'string' : dumpString($param); break; case 'array' : dumpArr($param); break; case 'object' : dumpObj($param); break; case 'resource' : echo 'resource'; break; default : echo 'UNKNOWN TYPE'; break; } } } function dumpString($param) { $str = sprintf("string(%d) %s",strlen($param),$param); echo $str; } function dumpArr($param) { $len = count($param); echo "array($len) {\r\n"; foreach($param as $key=>$val) { if(is_array($val)) { dumpArr($val); } else { echo sprintf('["%s"] => %s(%s)',$key,gettype($val),$val); } } echo "}\r\n"; } function dumpObj($param) { $className = get_class($param); $reflect = new ReflectionClass($param); $prop = $reflect->getDefaultProperties(); echo sprintf("Object %s #1(%d) {\r\n",$className,count($prop)); foreach($prop as $key=>$val) { echo "[\"$key\"] => "; mydump($val); } echo "}"; } class MyClass { protected $_name; function test() { echo "hello"; } } $str = "test"; mydump(new MyClass(),$str); echo "\r\n"; $arr2 = array( "1" => "Ddaddad", "one" => array("two" => "Dddd" ), "three" => 1 ); mydump($arr2); mydump(1,true,null);
3. 获取上周一和周日的日期
echo date('Y-m-d',strtotime('monday last week')); //上周一
echo date('Y-m-d', strtotime('-' . (6+date('w')) . ' days')); echo date('Y-m-d',strtotime('sunday last week')); //上周日
4. 对数组实现去除空元素 排重 按值从大到小排序 重新建立数字索引
$data = array_unique( array_filter($data) ) ;
rsort($data);
array_values($data);
5. 写一个shell命令 实现找出所有包含 spread的进程,杀死这些进程并记录日志,日志包含杀死进程名称和杀死进程的时间
ps -ef |grep spread |grep -v grep |awk '{print $2}'|xargs kill -9 kill -9 $(ps -ef | grep spread| grep -v grep | awk '{print $2}')
6. 写出你知道的http头部属性 注意大小写 并说明用途
Accept 指定客户端能够接收的内容类型 Accept: text/plain, text/html
Accept-Charset 浏览器可以接受的字符编码集。 Accept-Charset: iso-8859-5
Accept-Encoding 指定浏览器可以支持的web服务器返回内容压缩编码类型。 Accept-Encoding: compress, gzip
Accept-Language 浏览器可接受的语言 Accept-Language: en,zh
Accept-Ranges 可以请求网页实体的一个或者多个子范围字段 Accept-Ranges: bytes
Authorization HTTP授权的授权证书 Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
Cache-Control 指定请求和响应遵循的缓存机制 Cache-Control: no-cache
Connection 表示是否需要持久连接。(HTTP 1.1默认进行持久连接) Connection: close
Cookie HTTP请求发送时,会把保存在该请求域名下的所有cookie值一起发送给web服务器。 Cookie: $Version=1; Skin=new;
Content-Length 请求的内容长度 Content-Length: 348
Content-Type 请求的与实体对应的MIME信息 Content-Type: application/x-www-form-urlencoded
Date 请求发送的日期和时间 Date: Tue, 15 Nov 2010 08:12:31 GMT
Expect 请求的特定的服务器行为 Expect: 100-continue
From 发出请求的用户的Email From: user@email.com
Host 指定请求的服务器的域名和端口号 Host: www.zcmhi.com
If-Match 只有请求内容与实体相匹配才有效 If-Match: “737060cd8c284d8af7ad3082f209582d”
If-Modified-Since 如果请求的部分在指定时间之后被修改则请求成功,未被修改则返回304代码 If-Modified-Since: Sat, 29 Oct 2010 19:43:31 GMT
If-None-Match 如果内容未改变返回304代码,参数为服务器先前发送的Etag,与服务器回应的Etag比较判断是否改变 If-None-Match: “737060cd8c284d8af7ad3082f209582d”
If-Range 如果实体未改变,服务器发送客户端丢失的部分,否则发送整个实体。参数也为Etag If-Range: “737060cd8c284d8af7ad3082f209582d”
If-Unmodified-Since 只在实体在指定时间之后未被修改才请求成功 If-Unmodified-Since: Sat, 29 Oct 2010 19:43:31 GMT
Max-Forwards 限制信息通过代理和网关传送的时间 Max-Forwards: 10
Pragma 用来包含实现特定的指令 Pragma: no-cache
Proxy-Authorization 连接到代理的授权证书 Proxy-Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
Range 只请求实体的一部分,指定范围 Range: bytes=500-999
Referer 先前网页的地址,当前请求网页紧随其后,即来路 Referer: http://www.zcmhi.com/archives...
TE 客户端愿意接受的传输编码,并通知服务器接受接受尾加头信息 TE: trailers,deflate;q=0.5
Upgrade 向服务器指定某种传输协议以便服务器进行转换(如果支持) Upgrade: HTTP/2.0, SHTTP/1.3, IRC/6.9, RTA/x11
User-Agent User-Agent的内容包含发出请求的用户信息 User-Agent: Mozilla/5.0 (Linux; X11)
Via 通知中间网关或代理服务器地址,通信协议 Via: 1.0 fred, 1.1 nowhere.com (Apache/1.1)
Warning 关于消息实体的警告信息 Warn: 199 Miscellaneous warning
7. 写出 shell命令 统计 ip出现的次数 结果类似
awk '{arr[$1]++;}END{for(i in arr){print i , arr[i] }}' test.txt
8. 如何实现一个数组[1,2,3]连续复制3次变为[1,2,3,1,2,3,1,2,3]
$arr=[1,2,3]; 1) print_r(f($arr,3)); function f($arr,$num){ return array_filter(explode(',',str_repeat(implode(',',$arr).',',$num))); } 2) print_r( array_merge($arr,$arr,$arr) );
效率对比:
$arr1 = [111,222,333]; $t1 =microtime(true); array_merge($arr1,$arr1,$arr1); //索引数组不会合并,而是追加到后面 $t2 = microtime(true); array_filter(explode(',',str_repeat(implode(',',$arr1).',',3) ) ); $t3 = microtime(true); echo '第一种方式耗时:'.number_format($t2-$t1,10).PHP_EOL; echo '第一种方式耗时:'.number_format($t3-$t2,10).PHP_EOL; 第一种方式耗时:0.0000860691 第一种方式耗时:0.0001721382
9. 请简述一下数据库的优化?
1.从结构层: web服务器采用负载均衡服务器,mysql服务器采用主从复制,读写分离 2.从储存层: 采用合适的存储引擎,采用三范式 3.从设计层: 采用分区分表,索引,表的字段采用合适的字段属性,适当的采用逆范式,开启mysql缓存 4.sql语句层:结果一样的情况下,采用效率高,速度快节省资源的sql语句执行
10. 如何解决异常处理?
抛出异常:使用try…catch,异常的代码放在try代码块内,如果没有触发异常,则代码继续执行,如果异常被触发,就会 抛出一个异常。Catch代码块捕获异常,并创建一个包含异常信息的对象。$e->getMessage(),输出异常的错误信息。 解决异常:使用set_error_handler函数获取异常(也可以使用try()和catch()函数),然后使用set_exception_handler()函数设置默认的异常处理程序,register_shutdown_function()函数来执行,执行机制是,php要把调入的函数调入到内存,当页面所有的php语句都执行完成时,再调用此函数
11. 怎么保证促销商品不会超卖?
这个问题是我们当时开发时遇到的一个难点,超卖的原因主要是下的订单的数目和我们要促销的商品的数目不一致导致的,每次总是订单的数比我们的促销商品的数目要多,当时我们的小组讨论了好久,给出了好几个方案来实现: 第一种方案:在每次下订单前我们判断促销商品的数量够不够,不够不允许下订单,更改库存量时加上一个条件,只更改商品库存大于0的商品的库存,当时我们使用ab进行压力测试,当并发超过500,访问量超过2000时,还是会出现超卖现象。所以被我们否定了。 第二种方案:使用mysql的事务加排他锁来解决,首先我们选择数据库的存储引擎为innoDB,使用的是排他锁实现的,刚开始的时候我们测试了下共享锁,发现还是会出现超卖的现象。有个问题是,当我们进行高并发测试时,对数据库的性能影响很大,导致数据库的压力很大,最终也被我们否定了。 第三种方案:使用文件锁实现。当用户抢到一件促销商品后先触发文件锁,防止其他用户进入,该用户抢到促销品后再解开文件锁,放其他用户进行操作。这样可以解决超卖的问题,但是会导致文件得I/O开销很大。 最后我们使用了redis的队列来实现。将要促销的商品数量以队列的方式存入redis中,每当用户抢到一件促销商品则从队列中删除一个数据,确保商品不会超卖。这个操作起来很方便,而且效率极高,最终我们采取这种方式来实现
12. redis消息队列先进先出需要注意什么?
通常使用一个list来实现队列操作,这样有一个小限制,所以的任务统一都是先进先出,如果想优先处理某个任务就不太好处理了,这就需要让队列有优先级的概念,我们就可以优先处理高级别的任务,实现方式有以下几种方式: 1)单一列表实现:队列正常的操作是 左进右出(lpush,rpop)为了先处理高优先级任务,在遇到高级别任务时,可以直接插队,直接放入队列头部(rpush),这样,从队列头部(右侧)获取任务时,取到的就是高优先级的任务(rpop) 2)使用两个队列,一个普通队列,一个高级队列,针对任务的级别放入不同的队列,获取任务时也很简单,redis的BRPOP命令可以按顺序从多个队列中取值,BRPOP会按照给出的 key 顺序查看,并在找到的第一个非空 list 的尾部弹出一个元素,redis> BRPOP list1 list2 0 list1 做为高优先级任务队列 list2 做为普通任务队列 这样就实现了先处理高优先级任务,当没有高优先级任务时,就去获取普通任务 方式1最简单,但实际应用比较局限 方式2是推荐用法,实际应用最为合适
13. 接口安全方面是怎么处理的?
我们当时是这么做的,使用HTTP的POST方式,对固定参数+附加参数进行数字签名,使用的是md5加密,比如:我想通过标题获取一个信息,在客户端使用 信息标题+日期+双方约定好的一个key通过md5加密生成一个签名(sign),然后作为参数传递到服务器端,服务器端使用同样的方法进行校验,如何接受过来的sign和我们通过算法算的值相同,证明是一个正常的接口请求,我们才会返回相应的接口数据。 也可以使用RSA加密
14.写过接口吗,怎么定义接口的?
写过。接口分为两种:一种是数据型接口,一种是应用型接口。 数据型接口:是比抽象类更抽象的某种“结构”——它其实不是类,但是跟类一样的某种语法结构,是一种结构规范,规范我们类要以什么格式进行定义,一般用于团队比较大,分支比较多的情况下使用。 应用型接口: API(application interface) 数据对外访问的一个入口 我主要是参与的APP开发中接口的编写,客户端需要什么样的数据,我们就给他们提供相应的数据,数据以json/xml的格式返回,并且配以相应的接口文档。
15. sku减库存?
SKU = Stock Keeping Unit (库存量单位) 即库存进出计量的单位,可以是以件,盒,托盘等为单位。SKU是库存量单位,区分单品。 在服装、鞋类商品中使用最多最普遍。 例如纺织品中一个SKU通常表示:规格、颜色、款式。 在设计表时,不仅仅只有商品表,商品表中有个总库存,我们还需要涉及一张SKU表,里面有SKU库存和单价字段,用户每购买一件商品,实际上购买的都是SKU商品,这样在下订单成功后,应该根据所购买的商品的唯一的SKU号来进行相应的SKU库存的减少,当然商品的总库存保存在商品主表中,也需要减少总库存中的库存量。
16. 库存设置?
库存分为商品总库存和SKU库存,往往商品总库存的为SKU库存的总和。一般在商城的后台对货品设置最高库存及最低库存后,当前库存数量与最高、最低两者比较,超出库存或者低于库存的,则被统计成报表形式反映,便于用户掌握货品库存超、短缺状态及数量。
17. Redis如何防止高并发
其实redis是不会存在并发问题的,因为他是单进程的,再多的命令都是一个接一个地执行的。我们使用的时候,可能会出现并发问题,比如获得和设定这一对。Redis的为什么 有高并发问题?Redis的的出身决定 Redis是一种单线程机制的nosql数据库,基于key-value,数据可持久化落盘。由于单线程所以redis本身并没有锁的概念,多个客户端连接并不存在竞争关系,但是利用jedis等客户端对redis进行并发访问时会出现问题。发生连接超时、数据转换错误、阻塞、客户端关闭连接等问题,这些问题均是由于客户端连接混乱造成。 同时,单线程的天性决定,高并发对同一个键的操作会排队处理,如果并发量很大,可能造成后来的请求超时。 在远程访问redis的时候,因为网络等原因造成高并发访问延迟返回的问题。 解决办法 在客户端将连接进行池化,同时对客户端读写Redis操作采用内部锁synchronized。 服务器角度,利用setnx变向实现锁机制。
18. 支付宝流程怎么实现的?
首先要有一个支付宝账号,接下来向支付宝申请在线支付业务,签署协议。协议生效后有支付宝一方会给网站方一个合作伙伴ID,和安全校验码,有了这两样东西就可以按照支付宝接口文档开发支付宝接口了,中间主要涉及到一个安全问题。整个流程是这样的:我们的网站通过post传递相应的参数(如订单总金额,订单号)到支付页面,支付页面把一系列的参数经过处理,以post的方式提交给支付宝服务器,支付宝服务器进行验证,并对接收的数据进行处理,把处理后的结果返回给我们网站设置的异步和同步回调地址,通过相应的返回参数,来处理相应的业务逻辑,比如返回的参数代表支付成功,更改订单状态。
19. 怎么实现第三方登录?
第三方登陆主要是基于author协议来实现,下面简单说下实现流程: 1、首先我们需要以开发者的身份向第三方登陆平台申请接入应用,申请成功后,我们会获得一个appID和一个secrectID. 2、当我们的网站需接入第三方登陆时,会引导用户跳转到第三方的登陆授权页面,此时把之前申请的appID和secrectID带给登陆授权页面。 3、用户登陆成功后即得到授权,第三方会返回一个临时的code给我们的网站。 4、我们的网站接受到code后,再次向我们的第三方发起请求,并携带接收的code,从第三方获取access_token. 5、第三方处理请求后,会返回一个access_token给我们的网站,我们的网站获取到access_token后就可以调用第三方提供的接口了,比如获取用户信息等。最后把该用户信息存入到我们站点的数据库,并把信息保存到session中,实现用户的第三方登陆
20. 如何处理负载、高并发?
从低成本、高性能和高扩张性的角度来说有如下处理方案: 1、HTML静态化 其实大家都知道,效率最高、消耗最小的就是纯静态化的html页面,所以我们尽可能使我们的 网站上的页面采用静态页面来实现,这个最简单的方法其实也是最有效的方法。 2、图片服务器分离 把图片单独存储,尽量减少图片等大流量的开销,可以放在一些相关的平台上,如骑牛等 3、数据库集群和库表散列及缓存 数据库的并发连接为100,一台数据库远远不够,可以从读写分离、主从复制,数据库集群方面来着手。另外尽量减少数据库的访问,可以使用缓存数据库如memcache、redis。 4、镜像: 尽量减少下载,可以把不同的请求分发到多个镜像端。 5、负载均衡: Apache的最大并发连接为1500,只能增加服务器,可以从硬件上着手,如F5服务器。当然硬件的成本比较高,我们往往从软件方面着手。 负载均衡 (Load Balancing) 建立在现有网络结构之上,它提供了一种廉价有效透明的方法扩展网络设备和服务器的带宽、增加吞吐量、加强网络数据处理能力,同时能够提高网络的灵活性和可用性。目前使用最为广泛的负载均衡软件是Nginx、LVS、HAProxy。我分别来说下三种的优缺点: Nginx的优点是: 工作在网络的7层之上,可以针对http应用做一些分流的策略,比如针对域名、目录结构,它的正则规则比HAProxy更为强大和灵活,这也是它目前广泛流行的主要原因之一,Nginx单凭这点可利用的场合就远多于LVS了。 Nginx对网络稳定性的依赖非常小,理论上能ping通就就能进行负载功能,这个也是它的优势之一;相反LVS对网络稳定性依赖比较大,这点本人深有体会; Nginx安装和配置比较简单,测试起来比较方便,它基本能把错误用日志打印出来。LVS的配置、测试就要花比较长的时间了,LVS对网络依赖比较大。 可以承担高负载压力且稳定,在硬件不差的情况下一般能支撑几万次的并发量,负载度比LVS相对小些。 Nginx可以通过端口检测到服务器内部的故障,比如根据服务器处理网页返回的状态码、超时等等,并且会把返回错误的请求重新提交到另一个节点,不过其中缺点就是不支持url来检测。比如用户正在上传一个文件,而处理该上传的节点刚好在上传过程中出现故障,Nginx会把上传切到另一台服务器重新处理,而LVS就直接断掉了,如果是上传一个很大的文件或者很重要的文件的话,用户可能会因此而不满。 Nginx不仅仅是一款优秀的负载均衡器/反向代理软件,它同时也是功能强大的Web应用服务器。LNMP也是近几年非常流行的web架构,在高流量的环境中稳定性也很好。 Nginx现在作为Web反向加速缓存越来越成熟了,速度比传统的Squid服务器更快,可以考虑用其作为反向代理加速器。 Nginx可作为中层反向代理使用,这一层面Nginx基本上无对手,唯一可以对比Nginx的就只有 lighttpd了,不过 lighttpd目前还没有做到Nginx完全的功能,配置也不那么清晰易读,社区资料也远远没Nginx活跃。 Nginx也可作为静态网页和图片服务器,这方面的性能也无对手。还有Nginx社区非常活跃,第三方模块也很多。 Nginx的缺点是: Nginx仅能支持http、https和Email协议,这样就在适用范围上面小些,这个是它的缺点。 对后端服务器的健康检查,只支持通过端口来检测,不支持通过url来检测。不支持Session的直接保持,但能通过ip_hash来解决。 LVS:使用Linux内核集群实现一个高性能、高可用的负载均衡服务器,它具有很好的可伸缩性(Scalability)、可靠性(Reliability)和可管理性(Manageability)。 LVS的优点是: 抗负载能力强、是工作在网络4层之上仅作分发之用,没有流量的产生,这个特点也决定了它在负载均衡软件里的性能最强的,对内存和cpu资源消耗比较低。 配置性比较低,这是一个缺点也是一个优点,因为没有可太多配置的东西,所以并不需要太多接触,大大减少了人为出错的几率。 工作稳定,因为其本身抗负载能力很强,自身有完整的双机热备方案,如LVS+Keepalived,不过我们在项目实施中用得最多的还是LVS/DR+Keepalived。 无流量,LVS只分发请求,而流量并不从它本身出去,这点保证了均衡器IO的性能不会受到大流量的影响。 应用范围比较广,因为LVS工作在4层,所以它几乎可以对所有应用做负载均衡,包括http、数据库、在线聊天室等等。 LVS的缺点是: 软件本身不支持正则表达式处理,不能做动静分离;而现在许多网站在这方面都有较强的需求,这个是Nginx/HAProxy+Keepalived的优势所在。 如果是网站应用比较庞大的话,LVS/DR+Keepalived实施起来就比较复杂了,特别后面有 Windows Server的机器的话,如果实施及配置还有维护过程就比较复杂了,相对而言,Nginx/HAProxy+Keepalived就简单多了。 HAProxy的特点是: HAProxy也是支持虚拟主机的。 HAProxy的优点能够补充Nginx的一些缺点,比如支持Session的保持,Cookie的引导;同时支持通过获取指定的url来检测后端服务器的状态。 HAProxy跟LVS类似,本身就只是一款负载均衡软件;单纯从效率上来讲HAProxy会比Nginx有更出色的负载均衡速度,在并发处理上也是优于Nginx的。 HAProxy支持TCP协议的负载均衡转发,可以对MySQL读进行负载均衡,对后端的MySQL节点进行检测和负载均衡,大家可以用LVS+Keepalived对MySQL主从做负载均衡。 HAProxy负载均衡策略非常多,HAProxy的负载均衡算法现在具体有如下8种: ① roundrobin,表示简单的轮询,这个不多说,这个是负载均衡基本都具备的; ② static-rr,表示根据权重,建议关注; ③ leastconn,表示最少连接者先处理,建议关注; ④ source,表示根据请求源IP,这个跟Nginx的IP_hash机制类似,我们用其作为解决session问题的一种方法,建议关注; ⑤ ri,表示根据请求的URI; ⑥ rl_param,表示根据请求的URl参数’balance url_param’ requires an URL parameter name; ⑦ hdr(name),表示根据HTTP请求头来锁定每一次HTTP请求; ⑧ rdp-cookie(name),表示根据据cookie(name)来锁定并哈希每一次TCP请求。 Nginx和LVS对比的总结: Nginx工作在网络的7层,所以它可以针对http应用本身来做分流策略,比如针对域名、目录结构等,相比之下LVS并不具备这样的功能,所以Nginx单凭这点可利用的场合就远多于LVS了;但Nginx有用的这些功能使其可调整度要高于LVS,所以经常要去触碰触碰,触碰多了,人为出问题的几率也就会大。 Nginx对网络稳定性的依赖较小,理论上只要ping得通,网页访问正常,Nginx就能连得通,这是Nginx的一大优势!Nginx同时还能区分内外网,如果是同时拥有内外网的节点,就相当于单机拥有了备份线路;LVS就比较依赖于网络环境,目前来看服务器在同一网段内并且LVS使用direct方式分流,效果较能得到保证。另外注意,LVS需要向托管商至少申请多一个ip来做Visual IP,貌似是不能用本身的IP来做VIP的。要做好LVS管理员,确实得跟进学习很多有关网络通信方面的知识,就不再是一个HTTP那么简单了。 Nginx安装和配置比较简单,测试起来也很方便,因为它基本能把错误用日志打印出来。LVS的安装和配置、测试就要花比较长的时间了;LVS对网络依赖比较大,很多时候不能配置成功都是因为网络问题而不是配置问题,出了问题要解决也相应的会麻烦得多。 Nginx也同样能承受很高负载且稳定,但负载度和稳定度差LVS还有几个等级:Nginx处理所有流量所以受限于机器IO和配置;本身的bug也还是难以避免的。 Nginx可以检测到服务器内部的故障,比如根据服务器处理网页返回的状态码、超时等等,并且会把返回错误的请求重新提交到另一个节点。目前LVS中 ldirectd也能支持针对服务器内部的情况来监控,但LVS的原理使其不能重发请求。比如用户正在上传一个文件,而处理该上传的节点刚好在上传过程中出现故障,Nginx会把上传切到另一台服务器重新处理,而LVS就直接断掉了,如果是上传一个很大的文件或者很重要的文件的话,用户可能会因此而恼火。 Nginx对请求的异步处理可以帮助节点服务器减轻负载,假如使用 apache直接对外服务,那么出现很多的窄带链接时apache服务器将会占用大 量内存而不能释放,使用多一个Nginx做apache代理的话,这些窄带链接会被Nginx挡住,apache上就不会堆积过多的请求,这样就减少了相当多的资源占用。这点使用squid也有相同的作用,即使squid本身配置为不缓存,对apache还是有很大帮助的。 Nginx能支持http、https和email(email的功能比较少用),LVS所支持的应用在这点上会比Nginx更多。在使用上,一般最前端所采取的策略应是LVS,也就是DNS的指向应为LVS均衡器,LVS的优点令它非常适合做这个任务。重要的ip地址,最好交由LVS托管,比如数据库的 ip、webservice服务器的ip等等,这些ip地址随着时间推移,使用面会越来越大,如果更换ip则故障会接踵而至。所以将这些重要ip交给 LVS托管是最为稳妥的,这样做的唯一缺点是需要的VIP数量会比较多。Nginx可作为LVS节点机器使用,一是可以利用Nginx的功能,二是可以利用Nginx的性能。当然这一层面也可以直接使用squid,squid的功能方面就比Nginx弱不少了,性能上也有所逊色于Nginx。Nginx也可作为中层代理使用,这一层面Nginx基本上无对手,唯一可以撼动Nginx的就只有lighttpd了,不过lighttpd目前还没有能做到 Nginx完全的功能,配置也不那么清晰易读。另外,中层代理的IP也是重要的,所以中层代理也拥有一个VIP和LVS是最完美的方案了。具体的应用还得具体分析,如果是比较小的网站(日PV小于1000万),用Nginx就完全可以了,如果机器也不少,可以用DNS轮询,LVS所耗费的机器还是比较多的;大型网站或者重要的服务,机器不发愁的时候,要多多考虑利用LVS。
21. 封装过一个简单的框架?
封装过一个简单的MVC框架,主要分为3层,控制器层和模型层视图层,以及路由的分配和入口文件,模板引擎,单例模式、工厂模式,第三方类库的引入等。
22. 索引的优缺点?
优点: a)可以保证数据库表中每一行的数据的唯一性 b)可以大大加快数据的索引速度 c)加速表与表之间的连接,物别是在实现数据的参考完事性方面特别有意义 d)在使用分组和排序子句进行数据检索时,同样可以显著减少查询中分组和排序的时间 f)通过使用索引,可以在时间查询的过程中,使用优化隐藏器,提高系统的性能 缺点: a) 创建索引和维护索引要耗费时间,这种时间随着数据量的增加而增加 b) 索引需要占物理空间,除了数据表占用数据空间之外,每一个索引还要占用一定的物理空间,如果需要建立聚簇索引,那么需要占用的空间会更大 c) 以表中的数据进行增、删、改的时候,索引也要动态的维护,这就降低了整数的维护速度 d) 建立索引的原则 e) 在经常需要搜索的列上,可以加快搜索的速度 f) 在作为主键的列上,强制该列的唯一性和组织表中数据的排列结构 g) 在经常用在连接的列上,这些列主要是一外键,可以加快连接的速度 h) 在经经常需要根据范围进行搜索的列上创建索引,国为索引已经排序,其指定的范围是连续的 i) 在经常需要排序的列上,国为索引已经排序,这样井底可以利用索引的排序,加快排序井底时间 j) 在经常使用在where子句中的列上,加快条件的判断速度