# 1、缓存 #
## 1.1缓存三大要素 ##
1.1.1 命中率
命中率指请求缓存次数和缓存返回正确结果次数的比例。比例越高,证明缓存的使用率越高。
以Query Cache为例。
MySQL的Query Cache用来缓存和Query相关的数据。具体来说,Query Cache缓存客户端
提交给MySQL的SELECT语句以及该语句的结果集。就是将SELECT语句和语句的结果做Hash
映射关系后保存在一定的内存区域中。
1.1.2 缓存更新策略
1.1.3 缓存最大数据量
文件缓存幵源产品Secache
##1.2 obcode##
一个PHP程序在运行完后,内存马上释放,基本上所有数据都在此时销毁(仅有极少数据
会缓存),也就是说此时计算机内存中基本上不存在这个PHP代码中的数据,这和常驻内存的
Java等语言有显著区别。这种缓存机制具有如下的优缺点:
优点:有效避免内存泄露,内存回收机制更简单,避免因为一个程序的问题而连累整个服
务器。
缺点:无法复用已有数据,每个PHP请求都得重复执求-翻洋-执行的过程,重复过多。
Opcode (Operation Code,操作码)缓存就是虚拟机把PHP代码编译成一种中间码的结果缓
存起来(可以缓存到硬盘或内存)。下一次PHP运行此页面时,只要直接解释这些代码就行了。
这样省去了 Flex语法器进行语法编译和大部分语法检查(这个语法检査在多个阶段均存在)的
过程,一定程度上提高了 PHP运行速度,减轻了服务器负荷。
##1.2.1 eAccelerator使用##
在服务器第一次请求PHP文件时,会对PHP文件的Opcode进行缓存;再次请求时,直接
取出缓存的Opcode,由Zend虚拟机直接执行,从而节省了语法解析的消耗
##1.2.2 如何査看Opcode##
首先安装VLD扩展(Vulcan Logic Disassembler), 用来检测PHP脚本的执行情
,Opcode就是PHP “汇编代码‛。
eAccelerator缓存Opcode,同时提供一组API用来操作缓存数据。变相实现了类似Java中的
“共享变量” 功能。我们知道,PHP本身无法实现共享变量,变最在请求完成后就被销毁,无
法在另一个进程中得到其数据。借助eAccelerator就能实现类似功能。
无论eAccelerator还是APC, Opcode缓存软件实现的都只是简单的“共享变量‛,不能和具
有完整GC功能的Java或.NET中的内存变量相提并论,但是这确实提高了 PHP的执行效率,
使其接近编译型语言的速度。
##1.3 mamcache ##
### 1.3.1 Memcached如何支持高并发 ###
Memcached使用多路复用I /O 模型(如epoll、select等)。传统阻塞I /O 中,系统可能会因
为某个用户连接还没做好i / o 准备而一直等待,直到这个连接做好I /O 准备。如果这时有其他
用户连接到服务器,很可能会因为系统阻塞而得不到响应。
而多路复用I /O 是一种消息通知模式,用户连接做好I /O 准备后,系统会通知我们这个连
接可以进行I /O 操作,这样就不会阻塞在某个用户连接。因此,Memcached才能支持高并发。
此外,Memcached使用了多线程模式。在开启Memcached服务器时通过使用“-t‛参数指
定要开启的线程数。但并不是线程数越多越好,一般设置为CPU核数,这样效率最高。因为线
程数越多,系统需要的线程调度时间就越多。而把线程数设置成CPU核数,系统需要的线程调
度时间域少。
###1.3.2 使用Slab分配算法保存数据 ###
Memcached默认只能存储不大于1 MB的数据(修改Memcached源码可以打破这个限制,只
需把POWER_BLOCK宏设置为更大的数)。为什么Memcached会有这个限制呢?因为Memcached
在存储数据时使用Slab内存分配算法。使用这种算法可以减少生成内存碎片,提高内存
使用效率等。但使用这种算法也导致Memcached只能使用不大于1 MB的内存。
###1.3.3 Memcached多线程模型 ###
Memcached是一个多线程的缓存服务器程序。在Memcached内部,线程分为:
主线程(main thread):接收客户端连接,并把连接分配给工作线程处理。
工作线程(worker thread): 处理客户端连接的请
###1.4 PHP opcode原理 ###
php代码执行流程
PHP执行代码会经过如下4个步骤(确切的来说,应该是PHP的语言引擎Zend)
1.Scanning(Lexing[Lex就是一个词法分析的依据表]) ,将PHP代码转换为语言片段(Tokens)
2.Parsing, 将Tokens转换成简单而有意义的表达式
3.Compilation, 将表达式编译成Opocdes
4.Execution, 顺次执行Opcodes,每次一条,从而实现PHP脚本的功能。
现在有的Cache比如APC,可以使得PHP缓存住Opcodes,这样,每次有请求来临的时候,就不需要重复执行前面3步,从而能大幅的提高PHP的执行速度
#2、redis#
##2.1 key相关命令##
Redis本质上是Key-Value数据库,所以先了解key的相关操作。在Redis中,key使用字符
串存储,但是key中不能出现空格或者换行符“
” ,原因是空格和换行符都是Redis的特殊字
符,但只限于key, value可以使用任何字符。
注意Redis以“
” 作为命令结束符,所以在key中不能存在“
” ,否则就会出错。此外,
Redis以空格作为命令和参數的分隔符,所以在key中也不能存在空格。
应该尽量使用较短的k e y ,因为较短的key可以节省内存和带宽。
##2.2 Redis支持的数据类型##
Redis支持多种数据类型,如String、List、Set、Sorted Set、Hash等
# 3、网站优化#
## 3.1 优化网站响应时间 ##
###3.1.1 减少HTTP清求###
下载一个CSS文件或者图片需要一个独立的HTTP请求,而解析HTTP协议的过程需要时
间。处于相对顶层的HTTP协议占用更多传输量,所以减少HTTP请求可以降低网站的响应时
间和减少传输的数据。要减少HTTP请求,主要的方法有:
□ 将多个图片合并成为一个文件,利用CSS背景图片的偏移技术呈现在网页中,从而减少
图片下载的清求。
□ 合并JavaScript脚本和CSS样式文件。
□ 利用浏览器的Cache功能,避免重复下载相同文件。
###3.1.2 动态内容静态化###
如果应用中一些内容不经常改动,动态内容静态化是非常有效的加速方法。例如在新闻发
布系统中,把发布的新闻生成静态HTML文件,减少服务器脚本的计算时间,从而降低服务器
的响应时间。不过这种方法不能用于内容经常变化的应用,如SNS (社交网络)。
###3.1.3 优化数据库###
对于使用数据库的Web站点来说,数据库性能关系整个Web应用的性能,如果数据库性
能不佳,其他的优化工作也是徒劳无功。所以优化数据库性能,对提高整个Web应用的效率有
着举足轻重的作用。
第1 1章高性能网站架构方案♦ > 423
###3.1.4 使用负载均衡###
单台Web服务器处理能力有限,单台服务器承受的压力达到极限时,需要有更多的服务器
分担工作,我们需要想办法将流量合理分配到更多的服务器上。
实现负载均衡有多种方法,如HTTP重定向、基于DNS的轮询解析、反向代理服务器。无
论哪种方法,最终目的都是把流量分配到更多服务器上,从而降低单台服务器的压力。
###3.1.5 使用缓存###
缓存把需要花费昂贵开销的计算结果保存起来,在以后需要时直接取出,从而避免重复计
算。而在Web应用中,数据库的访问耗时相对较多,所以减少数据库的访问次数可以有效提高
应用性能。
缓存的方法有很多,可以把查询数据库的结果存储为一个PHP文件,需要时直接include
到程序中即可。也可以把查询结果存储在Memcached,需要时直接从Memcached中读取。
## 3.2吞吐率 ##
吞吐率指单位时间内服务器处理的请求数,通常使用“reqs/s‛(服务器每秒处理请求的数
量)表示。在一些常见Web服务器软件中,通常提供当前服务器运行状态以及吞吐率的査看
方法 .
吞吐率只描述服务器在实际运行期间单位时间内处理的请求数, 而我们更加关心服务器
并发处理能力的上限,即单位时间内服务器能够处理的最大请求数(即最大吞吐率)。但是
在测试时,很难调动足够的人测试服务器的最大吞吐率。所以,需要使用某些方法模拟足够数
目的并发用户数,这种方法称为“压力测试‛。
## 3.3 压力测试 ##
压力测试工具很多,如LoadRunner、JMeter和ab等。由于LoadRunner和JMeter使用过于复
杂,本书中大部分使用ab。
ab的参数比较多,常用的只有以下几个:
在测试会话中执行的请求个数,默认执行一个请求u
要创建的并发用户数,默认创建一个用户数。
等待Web服务器响应的敁大时间(单位:秒),默认没有时间限制。
使用Keep-Alive特性。
对请求附加一个Cookie,形式为name = value。
测试结果中关注以下内容:
□ Server Software:被测试Web服务器的软件名称。
□ Server Hostname :请求URL中的主机名称。
□ Server Port:被测试Web服务器的侦听端口。
□ Document Path:请求的_______URL的绝对路径。
□ Document Length: HTTP响应数据的正文长度。
□ Concurrency Level:并发用户数,设置的“ -C” 参数。
□ Time taken for tests:所有请求处理完成所花费的总时间。
□ Complete requests:总请求数,设置的“-n” 参数。
□ Failed requests :失败的请求数。
□ Total transferred:所有请求的响应数据长度总和。
□ HTML transferred:所有请求的响应数据中正文数据的总和。也就是减去Total transferred
中HTTP响应数据中头信息的长度。
□ Requests per second : Web 服务器的吞吐率,等于 Complete requests/Time taken for tests。
□ Time per request:用户平均请求等待时间,等于 Time taken for tests/( Complete requests/
Concurrency Level) 0
□ Transfer rate:这些请求在单位时间内从服务器取得的数据长度,等于Total transferred/
## 3.4 持久链接##
持久连接(Keep-Alive)又称长连接,指TCP连接中持续发送多份数据而不断开的连接,
与之对应的称为短连接,就是连接后发送一次数据便断开的连接。TCP三次捤手需要交换三个分组的数据,
而交换数据需要耗费一定时间。在允许的情况下,连接次数越少,越有利于性能的提升。
HTTP长连接的实施需要浏览器和Web服务器共同协助完成。一方面,浏览器需要保持一
个TCP连接不能释放,并且不断地发生多个请求。另一方面,服务器不能过早地主动关闭连
接。目前的浏览器普遍支持长连接,只需要在发出的HTTP请求数据头中包含相关长连接声明
即可如下所示:
Connection:Keep-Alive
这个声明告诉服务器:如果可以,请让我重用这个连接。告诉服务器不要在处理完当前请
求后马上关闭连接,同时,Web服务器必须打开长连接的支持。目前所有主流Web服务器软件都支持长连接。
注意TCP连接是双向的,任何一方都可以主动关闭连接。所以,当浏览器与Web服务器设置
的超时时间不一致时,将以最短的超时时间为准。在请求大量小文件时,长连接能够有效地减少重新建立连接的开销。
在启动ab时加上“-k”参数可以使用Keep-Alive模式进行测试。
注意长连接不一定都是正效应,也可能影响服务器的并发性能。
##3.5 MySQL响应速度提高方案: HandlerSocket##
日本DeNA公司架构师Yoshinori开发的HandlerSocket,以MySQL Plugin的形式运行,在
MySQL体系架构中绕开SQL解析这层,使得应用程序直接和InnoDB存储引擎交互,通过合并
写人、简单协议等手段提高数据访问的性能,在CPU密集型应用中优势尤其明显。
HandlerSocket解决了缓存问题,InnoDB有成熟的解决方案,通过参数配置用于缓存数据的
内存大小。只要参数分配合理,应用程序就能在无须干涉的情况下实现热点数据的缓存,降低
缓存维护成本。
## 3.6 Web应用加速方案: Varnish##
在没有任何优化的情况下,每一个HTTP请求,Web服务器都必须从服务器磁盘中读取请
求页面的数据,然后发送给客户端。相对内存访问速度来说,磁盘访问的速度极其缓慢(内存
访问速度是磁盘访问速度的105 ~106倍)。把访问过的页面缓存到内存中,下次访问直接从内
存中读取,能有效加快Web应用的访问速度。
###3.6.1 传统代理与反向代理###
一般情况下,使用浏览器直接连接其他Internet站点取得网络信息,直接联系到目的站点
服务器,目的站点服务器把信息传送回来。介于客户端和Web服务器之间的另一台服务器称为代理服务器,
浏览器不直接到Web服务器取回网页,而向代理服务器发出请求,信号先送到代理服务器,
由代理服务器取回浏览器所需要信息并传送给浏览器。
文件査看工具 WinCacheGrind
用WinCacheGrind打开这些文件,能看到每个文件中每个函数的运行消耗
#4 yii2设计模式#
依赖注入(Denpdency Injection, DI)和服务定位器(Service Locator)两种模式
详情参考:http://www.digpage.com/di.html
依赖注入(Dependence Injection, DI)
DI是IoC的一种设计模式,是一种套路,按照DI的套路,就可以实现IoC,就能符合DIP原则。 DI的核心是把类所依赖的单元的实例化过程,放到类的外面去实现。