服务器配置优化php
系统参数调整前端
Linux 系统内核参数优化mysql
vim /etc/sysctl.conf nginx
net.ipv4.ip_local_port_range = 1024 65535 # 用户端口范围 web
net.ipv4.tcp_max_syn_backlog = 4096 redis
net.ipv4.tcp_fin_timeout = 30 算法
fs.file-max=65535 # 系统最大文件句柄,控制的是能打开文件最大数量sql
数据库参数优化数据库
实例总体编程
thread_concurrency #并发线程数量个数
sort_buffer_size #排序缓存
read_buffer_size #顺序读取缓存
read_rnd_buffer_size #随机读取缓存
key_buffer_size #索引缓存
thread_cache_size #线程缓存(1G—>8, 2G—>16, 3G—>32, >3G—>64)
链接层(基础优化)
设置合理的链接客户和链接方式
max_connections #最大链接数,看交易笔数设置
max_connect_errors #最大错误链接数,能大则大
connect_timeout #链接超时
max_user_connections #最大用户链接数
skip-name-resolve #跳过域名解析
wait_timeout #等待超时
back_log #能够在堆栈中的链接数量
SQL 层(基础优化)
query_cache_size:查询缓存
OLAP 类型数据库,须要重点加大此内存缓存.
可是通常不会超过 GB.
对于常常被修改的数据,缓存会立马失效。
咱们能够实用内存数据库(redis、memecache),替代他的功能。
存储引擎层
innodb 基础优化参数
default-storage-engine
innodb_buffer_pool_size # 没有固定大小,50%测试值,看看状况再微调。可是尽可能设置不要超过物理内存70% innodb_file_per_table=(1,0)
innodb_flush_log_at_trx_commit=(0,1,2) #1是最安全的,0是性能最高,2折中
binlog_sync
Innodb_flush_method=(O_DIRECT, fdatasync)
innodb_log_buffer_size #100M如下
innodb_log_file_size #100M 如下
innodb_log_files_in_group #5个成员如下,通常2-3个够用(iblogfile0-N)
innodb_max_dirty_pages_pct #达到百分之75的时候刷写 内存脏页到磁盘。log_bin
max_binlog_cache_size #能够不设置
max_binlog_size #能够不设置
innodb_additional_mem_pool_size #小于2G内存的机器,推荐值是20M。32G内存以上100M
大数据的一些操做
大数据的分页
直接用 limit start, count 分页语句
当起始页较小时,查询没有性能问题,随着起始记录的增长,时间也随着增大
发现
1)limit 语句的查询时间与起始记录的位置成正比
2)mysql 的 limit 语句是很方便,可是对记录不少的表并不适合直接使用
对 limit 分页问题的性能优化方法
利用表的覆盖索引来加速分页查询
咱们都知道,利用了索引查询的语句中若是只包含了那个索引列(覆盖索引),那么这种状况会查询很快。
由于利用索引查找有优化算法,且数据就在查询索引上面,不用再去找相关的数据地址了,这样节省了不少时间。另外 Mysql 中也有相关的索引缓存,在并发高的时候利用缓存就效果更好了。
id 字段是主键,天然就包含了默认的主键索引。
覆盖索引
若是一个索引包含 (或覆盖) 全部须要查询的字段的值,称为‘覆盖索引’。即只需扫描索引而无须回表。
覆盖索引优势
1.索引条目一般远小于数据行大小,只须要读取索引,则mysql会极大地减小数据访问量。
2.由于索引是按照列值顺序存储的,因此对于IO密集的范围查找会比随机从磁盘读取每一行数据的IO少不少。
3.一些存储引擎如myisam在内存中只缓存索引,数据则依赖于操做系统来缓存,所以要访问数据须要一次系统调用
4.innodb的聚簇索引,覆盖索引对innodb表特别有用。
覆盖索引必需要存储索引列的值,而哈希索引、空间索引和全文索引不存储索引列的值,因此 mysql 只能用 B-tree 索引作覆盖索引。
例子
select id from product limit 866613, 20
SELECT * FROM product WHERE ID > =(select id from product limit 866613, 1) limit 20
SELECT * FROM product a JOIN (select id from product limit 866613, 20) b ON a.ID = b.id
百万级的数据的导出
一。对于数据超过了 65535 行的问题,很天然的就会想到将整个数据分块,利用 excel 的多 sheet 页的功能,将超出 65535 行后的数据写入到下一个 sheet 页中,即经过多 sheet 页的方式,突破了最高 65535 行数据的限定,具体作法就是,单独作一个连接,使用 JSP 导出,在 JSP 上经过程序判断报表行数,超过 65535 行后分 SHEET 写入。这样这个问题就得以解决了
二。在这种大数据量的报表生成和导出中,要占用大量的内存,尤为是在使用 TOMCAT 的状况下,JVM 最高只能支持到 2G 内存,则会发生内存溢出的状况。此时的内存开销主要是两部分,一部分是该报表生成时的开销,另外一部分是该报表生成后写入一个 EXCEL 时的开销。因为 JVM 的 GC 机制是不能强制回收的,所以,对于此种情形,咱们要改变一种方式:
将该报表设置起始行和结束行参数,在 API 生成报表的过程当中,分步计算报表,好比一张 20 万行数据的报表,在生成过程当中,可经过起始行和结束行分 4-5 次进行。这样,就下降了报表生成时的内存占用,在后面报表生成的过程当中,若是发现内存不够,便可自动启动 JVM 的 GC 机制,回收前面报表的缓存
导出 EXCEL 的过程,放在每段生成报表以后当即进行,改多个 SHEET 页为多个 EXCEL,即在分步生成报表的同时分步生成 EXCEL,则经过 POI 包生成 EXCEL 的内存消耗也得以下降。经过
屡次生成,一样能够在后面 EXCEL 生成所须要的内存不足时,有效回收前面生成 EXCEL 时占用的内存
再使用文件操做,对每一个客户端的导出请求在服务器端根据 SESSIONID 和登录时间生成惟一的临时目录,用来放置所生成的多个 EXCEL,而后调用系统控制台,打包多个 EXCEL 为 RAR
或者 JAR 方式,最终反馈给用户一个 RAR 包或者 JAR 包,响应客户请求后,再次调用控制台删除该临时目录。
经过分段运算和生成,有效下降了报表从生成结果到生成 EXCEL 的内存开销。其次是经过使用压缩包,响应给用户的生成文件体积大大缩小,下降了多用户并
发访问时服务器下载文件的负担,有效减小多个用户导出下载时服务器端的流量,从而达到进一步减轻服务器负载的效果
php 相关
cgi ,fastcgi,php-fpm 区别
cgi
CGI 的英文是(COMMON GATEWAY INTERFACE)公共网关接口,它的做用就是帮助服务器与语言通讯,这里就是 nginx 和 php 进行通讯,由于 nginx 和 php 的语言不通,所以须要一个沟通转换的过程,而 CGI 就是这个沟通的协议。
nginx 服务器在接受到浏览器传递过来的数据后,若是请求的是静态的页面或者图片等无需动态处理的则会直接根据请求的 url 找到其位置而后返回给浏览器,这里无需 php 参与,可是若是是一个动态的页面请求,这个时候 nginx 就必须与 php 通讯,这个时候就会须要用到 cgi 协议,将请求数据转换成 php 能理解的信息,而后 php 根据这些信息返回的信息也要经过 cgi 协议转换成 nginx 能够理解的信息,最后 nginx 接到这些信息再返回给浏览器。
fast-cgi
传统的 cgi 协议在每次链接请求时,会开启一个进程进行处理,处理完毕会关闭该进程,所以下次链接,又要再次开启一个进程进行处理,所以有多少个链接就有多少个 cgi 进程,这也就是为何传统的 cgi 会显得缓慢的缘由,所以过多的进程会消耗资源和内存。
而 fast-cgi 每次处理完请求后,不会 kill 掉这个进程,而是保留这个进程,使这个进程能够一次处理多个请求。这样每次就不用从新 fork 一个进程了,大大提升效率。
php-cgi
php-cgi 是 php 提供给 web serve 也就是 http 前端服务器的 cgi 协议接口程序,当每次接到 http 前端服务器的请求都会开启一个 php-cgi 进程进行处理,并且开启的 php-cgi 的过程当中会先要重载配置,数据结构以及初始化运行环境,若是更新了 php 配置,那么就须要重启 php-cgi 才能生效,例如 phpstudy 就是这种状况。
php-fpm
php-fpm 是 php 提供给 web serve 也就是 http 前端服务器的 fastcgi 协议接口程序,它不会像 php-cgi 同样每次链接都会从新开启一个进程,处理完请求又关闭这个进程,而是容许一个进程对多个链接进行处理,而不会当即关闭这个进程,而是会接着处理下一个链接。它能够说是 php-cgi 的一个管理程序,是对 php-cgi 的改进。
php-fpm 会开启多个 php-cgi 程序,而且 php-fpm 常驻内存,每次 web serve 服务器发送链接过来的时候,php-fpm 将链接信息分配给下面其中的一个子程序 php-cgi 进行处理,处理完毕这个 php-cgi 并不会关闭,而是继续等待下一个链接,这也是 fast-cgi 加速的原理,可是因为 php-fpm 是多进程的,而一个 php-cgi 基本消耗 7-25M 内存,所以若是链接过多就会致使内存消耗过大,引起一些问题,例如 nginx 里的 502 错误。
同时 php-fpm 还附带一些其余的功能:
例如平滑过渡配置更改,普通的 php-cgi 在每次更改配置后,须要从新启动才能初始化新的配置,而 php-fpm 是不须要,php-fpm 分将新的链接发送给新的子程序 php-cgi,这个时候加载的是新的配置,而原先正在运行的 php-cgi 仍是使用的原先的配置,等到这个链接后下一次链接的时候会使用新的配置初始化,这就是平滑过渡。
参考连接:https://blog.csdn.net/belen_xue/article/de…
PHP5 跟 php7 的区别
PHP7.0 号称是性能提高上革命性的一个版本。面对 Facebook 家的 HHVM 引擎带来的压力,开发团队重写了底层的 Zend Engine,名为 Zend Engine 2。
底层内核解析
PHP7 中最重要的改变就是 zval 再也不单独从堆上分配内存而且不本身存储引用计数。须要使用 zval 指针的复杂类型(好比字符串、数组和对象)会本身存储引用计数。这样就能够有更少的内存分配操做、更少的间接指针使用以及更少的内存分配。在 PHP7 中的 zval, 已经变成了一个值指针,它要么保存着原始值,要么保存着指向一个保存原始值的指针。也就是说如今的 zval 至关于 PHP5 的时候的 zval . 只不过相比于 zval , 直接存储 zval, 咱们能够省掉一次指针解引用,从而提升缓存友好性.
参考连接:https://www.jb51.net/article/76732.htm
PHP7 为何比 PHP5 性能提高了
一、变量存储字节减少,减小内存占用,提高变量操做速度
二、改善数组结构,数组元素和 hash 映射表被分配在同一块内存里,下降了内存占用、提高了 cpu 缓存命中率
三、改进了函数的调用机制,经过优化参数传递的环节,减小了一些指令,提升执行效率
安全
函数修改
preg_replace () 再也不支持 /e 修饰符,,同时官方给了咱们一个新的函数 preg_replace_callback
create_function () 被废弃,实际上它是经过执行 eval 实现的。
mysql* 系列全员移除,若是你要在 PHP7 上面用老版本的 mysql* 系列函数须要你本身去额外装了,官方不在自带,如今官方推荐的是 mysqli 或者 pdo_mysql。
unserialize () 增长一个可选白名单参数,其实就是一个白名单,若是反序列数据里面的类名不在这个白名单内,就会报错。
assert () 默认不在能够执行代码
语法修改
foreach 再也不改变内部数组指针
8 进制字符容错率下降,在 php5 版本,若是一个八进制字符若是含有无效数字,该无效数字将被静默删节。在 php7 里面会触发一个解析错误。
十六进制字符串再也不被认为是数字
移除了 ASP 和 script PHP 标签
超大浮点数类型转换截断,将浮点数转换为整数的时候,若是浮点数值太大,致使没法以整数表达的状况下, 在 PHP5 的版本中,转换会直接将整数截断,并不会引起错误。在 PHP7 中,会报错。
整体
性能提高:PHP7 比 PHP5.0 性能提高了两倍。
全面一致的 64 位支持。
之前的许多致命错误,如今改为 [抛出异常]。
PHP 7.0 比 PHP5.0 移除了一些老的不在支持的 SAPI([服务器端] 应用编程端口)和扩展。
.PHP 7.0 比 PHP5.0 新增了空接合操做符。
PHP 7.0 比 PHP5.0 新增长告终合比较运算符。
PHP 7.0 比 PHP5.0 新增长了函数的返回类型声明。
PHP 7.0 比 PHP5.0 新增长了标量类型声明。
PHP 7.0 比 PHP5.0 新增长匿名类。
多进程同时读写一个文件
PHP 是支持进程的而不支持多线程(这个先搞清楚了),若是是对于文件操做,其实你只须要给文件加锁就能解决,不须要其它操做,PHP 的 flock 已经帮你搞定了。
用 flock 在写文件前先锁上,等写完后解锁,这样就实现了多线程同时读写一个文件避免冲突。
流程
flock 参数说明:file 必需,规定要锁定或释放的已打开的文件,lock 必需。规定要使用哪一种锁定类型。block 可选。若设置为 1 或 true,则当进行锁定时阻挡其余进程。
LOCK_SH 要取得共享锁定(读取的程序)
LOCK_EX 要取得独占锁定(写入的程序)
LOCK_UN 要释放锁定(不管共享或独占)
LOCK_NB 若是不但愿 flock () 在锁定时堵塞
在 PHP 中,flock 彷佛工做的不是那么好!在多并发状况下,彷佛是常常独占资源,不即时释放,或者是根本不释放,形成死锁,从而使服务器的 cpu 占用很高,甚至有时候会让服务器完全死掉。好因此使用 flock 以前,必定要慎重考虑。
解决方案
对文件进行加锁时,设置一个超时时间,超时设置为 1ms,若是这里时间内没有得到锁,就反复得到,直接得到到对文件操做权为止,固然。若是超时限制已到,就必需立刻退出,让出锁让其它进程来进行操做。
不使用 flock 函数,借用临时文件来解决读写冲突的问题
将须要更新的文件考虑一份到咱们的临时文件目录,将文件最后修改时间保存到一个变量,并为这个临时文件取一个随机的,不容易重复的文件名。
当对这个临时文件进行更新后,再检测原文件的最后更新时间和先前所保存的时间是否一致。
若是最后一次修改时间一致,就将所修改的临时文件重命名到原文件,为了确保文件状态同步更新,因此须要清除一下文件状态。
可是,若是最后一次修改时间和先前所保存的一致,这说明在这期间,原文件已经被修改过,这时,须要把临时文件删除,而后返回 false, 说明文件这时有其它进程在进行操做。
对操做的文件进行随机读写,以下降并发的可能性。
先前须要定义一个随机空间,空间越大,并发的的可能性就越小,这里假设随机读写空间为 [1-500], 那么咱们的日志文件的分布就为 log1~ 到 log500 不等。每一次用户访问,都将数据随机写到 log1~log500 之间的任一文件。在同一时刻,有 2 个进程进行记录日志,A 进程多是更新的 log32 文件,而 B 进程呢?则此时更新的可能就为 log399. 要知道,若是要让 B 进程也操做 log32, 几率基本上为 1/500, 差很少约等于零。在须要对访问日志进行分析时,这里咱们只须要先将这些日志合并,再进行分析便可。使用这种方案来记录日志的一个好处时,进程操做排队的可能性比较小,可使进程很迅速的完成每一次操做。
将全部要操做的进程放入一个队列中。
队列中的每个排除的进程至关于第一个具体的操做,因此第一次咱们的服务只须要从队列中取得至关于具体操做事项就能够了,若是这里还有大量的文件操做进程,不要紧,排到咱们的队列后面便可,只要愿意排,队列的多长都不要紧。