1、引用变量
写时复制机制
$a = range(0, 1000);
var_dump(memory_get_usage());
COW Copy On Write
$b = $a;
//$b = &$a;//此时就算后续$a $b改变,也不会重新拷贝
var_dump(memory_get_usage());
对a修改之后,将会复制
$a = range(0, 1000);
var_dump(memory_get_usage());
// zval变量容器
// refcount 引用计数
// is_ref 是否有引用
// unset 只会取消引用,不会销毁空间
// 对象本身就是引用传递
2、常量和数据类型
- 字符串定义方法:单引号 双引号 heredoc nowdoc(不转义任何字符)
三大数据类型 标量、复合、特殊
- 浮点(不能用于比较)
- 布尔 0, 0.0, '', '0', false, array(), NULL
- 数组
超全局数组 $GLOABAL $_SERVER (SERVER_ADDR 服务器IP REMOTE_ADDR 客户端IP )
- NULL NULL 未定义的变量 unset销毁的变量
- 常量 const语言结构 define函数(不能定义类常量)
预定义常量 _FILE_ _LINE_ _DIR_ _FUNCTION_ _CLASS_ _TRAIT_ _METHOD_ _NAMESPACE_
3、运算符考点
- foo() & @foo() @ 错误控制符,忽略该表达式任何错误
- 递增递减 > ! > 算数运算 > 大小比较 > (不)相等比较 > 引用 > 位运算符(^) > 位运算符(|) > 逻辑与 > 逻辑或 > 三目 > 赋值 > and > xor > or
- === VS == 类型比较
- 递增递减不影响布尔值
- null递减 -> null null递加 -> 1
- 逻辑运算符 注意短路作用
4、流程控制考察点
- while list each 不会reset数组指针
foreach会重置数组指针 - switch case 会生成跳转表,所以一般效率会高一些(判断条件复杂,且是整型、浮点、字符串则可以用于优化if else)
5、变量的作用域和静态变量
- global 声明变量则可以在函数内使用
global $outer;
,或者直接引用$GLOBALS['outer'];
- static 首次声明需要赋值;函数内声明,函数结束也不会释放
- 返回引用,则必须声明和指派返回值时都使用&
- 外部文件的导入 require / include
未找到文件时,include会报一个警告,而require会报一个错误
serialize() unserialize()
6、正则表达式
- 作用:分割、查找、匹配、替换
- 通用原子:\d 0-9;\w 数组字母下划线; \s 空白符 字母大写则反选
-
模式修正符:i 不区分大小写;m 按换行分割;e 匹配内容做处理(php7取消);
s 修正.的换行;U 取消贪婪模式;x忽略空白符;A必须以模式开头;D修正$对\n的忽略;u utf-8中文匹配时候用 - 后向引用和贪婪模式:
$str = '<b>abc<\/b>';
//后向引用
preg_replace('/<b>(.*)<\/b>/', '\\1', $str);
$str = '<b>abc</b><b>bcd</b>';
//贪婪模式
$pattern = '/<b>.*?<\/b>/';//?用于取消贪婪模式
$pattern = '/<b>.*<\/b>/U';// 或者U取消贪婪模式
preg_replace($pattern, '\\1', $str)'
-
常用函数:
preg_match
pre_match_all
preg_replace
preg_split
$result = preg_split('/[;\r\n]+/s', $value); // 返回数据保存在$result数组中
- 匹配中文:
$pattern = '/[\x{4e00}-\x{9fa5}]+/u';
7、文件目录处理
php遍历目录
function loopDir($dir){
$handle = opendir($dir);
while(false !== ($file = readdir($handle))){
if($file != '.' && $file != '..'){
echo $file . '\n';
if(filetype($dir . '/' . $file) == 'dir'){
loopDir($dir. '/' . $file);
}
}
}
}
8、会话控制技术
用户跟踪、用户状态保持
cookie
存储在客户端(浏览器)
- 优点:不占用服务器资源
- 缺点:不在服务器不安全,用户可以禁用
session
存储在服务器,基于cookie
操作
$_SESSION
session_destory()
配置
session.auto_start
session.cookie_domain
session.cookie_lifetime
session.cookie_path
session.name
session.save_path
session.use_cookies
session.use_trans_sid
//垃圾回收,每100次session_start,有1次机会清理1440秒之前的session
session.gc_probability = 1
session.gc_divisor = 100
session.gc_maxlifetime = 1440
- 优点:存在服务器,安全
- 缺点:占用服务器资源,分布式服务器也成问题(redis)
session传递
session_name(). '=' . session_id();
session存储
session_set_save_handler()
9、PHP类权限控制修饰符
权限控制修饰符
public 外部亦可
protected 类内部和子类
private 类内部
封装、继承、多态
- 封装 即隐藏对象的属性和实现细节,仅对外公开接口,控制在程序中属性的读和修改的访问级别
- 继承 php只能单一继承,同时只能继承一个类,必要时方法需要重写
parent::func() //调用父类方法 - 多态 abstract 抽象类,内部可以有非抽象方法;接口中只能是抽象方法
10、 魔术方法
1、__get() __set()
2、__call() __callStatic()别忘了staic声明
3、__toString() php对象当做字符串使用时候调用eg. echo $obj;
4、__invoke() php对象当做函数使用时候调用eg. echo $obj();
__construct() __destruct() __isset()
11、 设计模式
- 工厂模式: 工厂方法或者类生成对象,而不是在代码中new。容易修改类名之类的属性,不需要每一处new都修改
- 单例模式: 使某个类的对象仅允许创建一个。节约资源
- 注册树模式: 全局共享和交换对象。增加代码的复用性
- 适配器模式: 可以将不同的函数接口封装成统一的API
- 策略模式: 将一组特定的行为和算法封装成类,以适应某些上下文环境,这种模式就是策略模式。实现了从硬编码到解耦的一个过程。处理分支逻辑,依赖倒置、控制反转。
- 数据对象映射模式: 将对象和数据存储映射起来。遵循单一职责原则,将持久化数据存储层,驻于内存的数据表现层,以及数据映射本身三者相互独立、互不依赖
- 观察者模式: 当一个对象状态发生改变时,依赖的对象全部会收到通知并自动更新。实现了低耦合,非侵入式的通知与更新机制
- 原型模式: 与工厂模式类似,都是用来创建对象,但是不同的时,原型模式先创建好一个对象,通过clone来创建新的对象,免去初始化等操作。适用于大对象创建,防止new开销很大,只需内存拷贝即可。
- 装饰器模式: 可以动态的修改添加类的功能。需要添加功能时只需要添加一个装饰器对象即可,无需修改原有的类,更具有灵活性
- 迭代器模式: 在不需要了解内部实现的前提下,遍历一个聚合对象的内部元素。可以隐藏遍历元素所需的操作
- 代理模式: 客户端与实体之间建立一个代理对象,客户端的操作委派给代理对象,隐藏实体的具体实现细节,例如可以用代理模式读从库,写主库。与适配器模式保证统一的目的不同,代理模式为的是隐藏原类代码
- 门面模式: 提供一个统一的接口去访问多个子系统的多个不同的接口,它为子系统中的一组接口提供一个统一的高层接口。使用子系统更容易使用。让用户与子系统解耦,统一接口方便应用,用户不需要知道子系统的内部构造。但是没有面向抽象编程,而是提供中介类,转换服务提供方的服务接口。
12、面向对象编程的基本原则
1、单一职责。一个类只需要做好一件事情
2、开放封闭。一个类应该是可以扩展的而不可修改的
3、依赖倒置。一个类不应该强依赖另外一个类,每个类对另外的类都是可替换的。
4、配置化。尽可能使用配置而不是硬编码。
5、面向接口编程。只关心接口,而不需要关心实现。
13、php7 新特性
- 性能提升70%
- try catch
- 7.1 JIT,准确判断数据类型,生成准确机器指令,提升性能
- zval 使用栈内存。减少内存分配和内存管理
-
zend_string存储hash值,array查询不再需要重复计算hash
- hashtable arBuckets -> arData,arBuckets中存的是指向数据的指针,而arData内直接存数据,减少了内存申请次数,提升了cache命中率和内存访问速度
- zend_parse_parameters 改为宏实现,性能提升5%
- 新增4种OPCODE,call_user_function, is_int/string/array, strlen,defined 4种函数变为PHP OpCode指令,速度更快。
- 基础类型int、float、bool等改为直接进行值拷贝(引用计数改进,直接去除zval种的引用计数字段)
- 排序算法改进
- PCRE with JIT。正则表达式可以编译为机器码
- execute_data 和 opline 使用全局寄存器。Zend执行器在opcode的执行过程中,会频繁的用到execute_data和opline两个变量,execute_data为zend_execute_data结构,opline为当前执行的指令,使用全局寄存器保存这两个变量的地址,以实现更高效率的读取
-
使用gdb4.8的PGO功能
14、网络协议
HTTP1.1中常见状态码
1XX信息类,2XX成功类,3XX重定向,4XX客户端错误,5XX服务器错误
204 成功但没有返回数据
301 永久重定向,302临时重定向,304客户端带条件的GET,但文档内容未改变not modified
400 请求中有错误,401 需要认证
501服务器错误 ,503 服务器超负荷或停机维护中
OSI七层模型
第四层传输层 TCP/UDP
第七层应用层 HTTP/HTTPS/FTP
HTTP协议的工作特点和工作原理
工作特点:基于B/S模式;通信开销小;使用灵活,可以用超文本传输协议;节省传输时间;无状态
工作原理:客户端发送请求创建一个TCP连接,指定端口号,连接到服务器,服务器浏览器请求,收到请求,分析请求类型后,返回状态和数据
HTTP协议常见请求/响应头和请求方法
- Content-Type,Accept,Origin,Cookie,User-Agent,Referrer,Access-Control-Allow-Origin,Last-Modified
- GET POST(请求信息不保存在浏览器历史中,所以较安全) HEAD OPTIONS PUT DELETE TRACE
PUT 用于向指定的URI传送更新资源,是幂等的
OPTIONS 获得由Request-URI标识的资源在请求/响应的通信过程中可以使用的功能选项
TRACE 回显服务器收到的请求,主要用于测试或诊断。
HTTPS协议的工作原理
在HTTP基础上添加了SSL/TLS握手以及数据加密传输
常见网络协议含义及端口
FTP 21 文件传输
Telnet 23 远程连接
SMTP 25 简单邮件传输协议
POP3 110 接受邮件
HTTP 80 超文本传输协议
DNS 53 域名解析服务
15、开发环境及配置
版本控制软件
集中式:SVN
分布式:Git
PHP运行原理
nginx + php-fpm(fastcgi process manager)
可以参考此文章 https://www.jianshu.com/p/648abc5a883a
PHP配置项
register_globals 注册全局变量 建议关闭
allow_url_fopen 允许远程打开文件
allow_url_include 允许远程包含文件
date.timezone 设置时区
display_errors 是否展示errors
error_reporting 错误级别设置
safe_mode 是否开启安全模式
post_max_size 提交数据最大大小
16、js和jq知识点
js基本语法
变量 字母 $ _ 开头 var声明 默认undefined
var a=1;
var a; //a值不会丢失
变量均为对象
创建对象 new Object(); 对象构造器;json对象{}
函数外变量为全局,内为局部
js内置对象
Number、String、Boolean、Array、Date、Math、RegExp
window 对象 Window、Navigator、Screen、History、Location
js html dom对象
Document、Element、Attr、Event
jq基础知识
jq选择器
jq事件
jq效果 show hide
jq dom操作 属性、值、css、尺寸
AJAX
基于XMLHttpRequest对象
17、linux知识点
常用命令
sudo 使用管理员权限执行命令
su 切换用户
chmod 修改文件权限
man 显示命令介绍
w 显示哪些用户在使用
top 持续监视进程和Linux整体性能
ps 显示进程瞬间信息
kill 杀死进程
pkill 是ps命令和kill命令的结合,按照进程名来杀死指定进程
killall 杀死所有同名进程
网络应用 curl、mail
网络测试 ping、netstat、host
网络配置 hostname、ifconfig
常用工具 ssh、screen、clear、who、date
软件包管理 yum、rpm、apt-get
文件查找和比较 locate、find
文件内容查看 head、tail、less、more
文件处理 touch、unlink、rename、ln、cat
目录操作 cd、mv、rm、pwd、tree、cp、ls
压缩 zip、unzip、tar
系统定时任务
1、crontab -e
-
命令(分、时、日、月、周)
2、at 命令
-
vi/vim
shell 基础
开头: #!/bin/sh
18、MySQL知识点
MySQL 数据类型
- int:unsigned int(12) 这个12只是表示显示字符的个数,unsigned指非负
- 实数:FLOAT、DOUBLE、DECIMAL,decimal可存储比bigint还大的整数,可用于存储精确的小数
- 字符串:char(定长,空格填充,适合比较短,经常变更的列)、varchar(变长,额外字节记录长度,<255用1个字节,否则用两个字节)、BOB/TEXT(尽量避免,会产生临时表导致严重的性能开销)
- 枚举:实际存储为数字
- 时间:timestamp比date空间效率高
- 列属性:auto_increment、default、not null、zerofill
MySQL 存储引擎
- InnoDB
默认事务性引擎
支持行级锁
支持崩溃后安全恢复
支持真正的热备份
表存储在共享空间,也可以配置分开
主键查询性能高于其他引擎
很多内部优化,读数据时自动内存中构建hash索引,插入数据时自动构建插入缓存区 - MyISAM
拥有全文索引、压缩、空间函数
表级锁不支持崩溃后安全恢复
表存储在两个文件,MYD、MYI
设计简单,select * 性能很好
MySQL 锁机制
写锁、读锁
- 悲观锁
总是假设最坏的情况,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会阻塞直到它拿到锁(共享资源每次只给一个线程使用,其它线程阻塞,用完后再把资源转让给其它线程)。传统的关系型数据库里边就用到了很多这种锁机制,比如行锁,表锁等,读锁,写锁等,都是在做操作之前先上锁。- 乐观锁
总是假设最好的情况,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,可以使用版本号机制和CAS算法实现。乐观锁适用于多读的应用类型,这样可以提高吞吐量,像数据库提供的类似于write_condition机制,其实都是提供的乐观锁。
表锁、行锁
- 1,Record Lock:单个行记录上的锁。
- 2,Gap Lock:间隙锁,锁定一个范围,但不包括记录本身。GAP锁的目的,是为了防止同一事务的两次当前读,出现幻读的情况。
- 3,Next-Key Lock:1+2,锁定一个范围,并且锁定记录本身。对于行的查询,都是采用该方法,主要目的是解决幻读的问题。
MySQL 事务处理、存储过程、触发器
- 不支持事务的表执行事务不会报错
- 为了以后使用保存的一条或多条MySQL语句集合
- 触发器是保证数据完整性的一种方法,是一种特殊的存储过程
mysql索引的基础和类型
流程:
先找索引,根据索引找对应行
对性能影响:
- 大大减少需要扫描的数据量
- 帮助服务器避免排序和临时表
- 将随机IO变为顺序IO
- 大大提高查询速度,降低写的速度,占用磁盘空间
使用场景:
小表没必要建立索引,
中大型表,很有必要建立索引
特大型的表,建立使用索引代价也随之增长,可以使用分区分表的技术来解决
索引类型:
索引有很多种类型,都是实现在存储引擎层的
普通索引:没有任何约束限制
唯一索引:具有唯一性的约束
主键索引:特殊的唯一索引,不允许空值
组合索引:多个列组合在一起创建索引
外键索引:InnoDB才能用,保证数据的一致性、完整性和实现级联操作
全文索引:只能用于MyISAM,并且只能对英文进行全文检索
索引创建原则:
1、where和on后的列最适合做索引
2、索引列基数越大,索引效果越好
3、对字符串进行索引,应该制定一个前缀长度,可以节省大量的索引空间
4、看情况创建复合索引
5、避免创建过多的索引
6、主键尽可能选较短的数据类型,减少磁盘占用,提高查询效率
索引注意事项:
1、复合索引遵循前缀原则
2、like %不能在前,需要在前时可以去使用全文索引
3、clumn is null是可以使用索引的
4、如果mysql估计使用索引比全表扫描慢,会放弃使用索引
5、如果or前的条件中的列有索引,后面的列没有索引,则都不会用到
6、列类型是字符串,则查询时一定要加引号,否则会失效
mysql语句编写
UPDATE A,B set A.c1 = B.c1,A.c2=B.c2 where A.id=B.id and B.age > 50;
//OR
update A inner join B on A.id = B.id set A.c1=B.c1,A.c2=B.c2 where B.age>50;
- 交叉连接
select * from A,B
select * from A cross join B
笛卡尔积,结果集会很大没有意义
- 内连接
select * from A,B where A.id = B.id
select * from A (inner) join B on A.id = B.id
内连接分三类:等值连接,不等值连接和自连接
- 外连接(左连接、右连接)
先查询左(右)表,再按照关联条件匹配右(左)表,没有匹配到的用NULL填充 - 联合查询
多个结果集集中在一起,UNION前的结果为基准,两个结果集列数要想等,相同记录行会合并
如果使用UNION ALL 重复集不会合并 - 全连接
mysql不支持,但是可以通过左连接和右连接UNION得到 - 嵌套查询
用一条语句的结果作为另外一条语句的条件
//答案
select
t1.teamName,m.matchResult,t2.teamName,m.matchTime
from
match as m left join team as t1 on m.hostTeamID = t1.teamID,
left join team as t2 on m.guestTeamID = t2.teamID
where
m.matchTime between "2006-6-1" and "2006-7-1";
mysql查询优化
- 查找执行速度慢的原因
1、记录慢查询日志
pt-query-digest 工具进行分析
2、show profile
set profiling = 1;开启,执行语句都会检测消耗时间存到临时表中
用 show profiles、show profile for query 临时表ID 查看语句的执行时间
3、show status
会返回一些计数器,show global status查看服务器级别的所有计数
4、show processlist
观察是否有大量线程处于不正常的状态或者特征
5、explain
分析单条语句 - 优化mysql查询
1、优化查询过程中的数据访问
(1)确定程序是否在检索大量超过需要的数据,太多行或者列,比如select * 替换为制定列
(2)确认mysql是否在分析大量不必要的数据行,可以使用limit限制
(3)重复查询相同数据,可以建立缓存
(4)是否在扫描额外的记录,用explain分析,然后用索引覆盖扫描列
(5)调整表结构,添加冗余字段
(6)重写SQL语句,使命中索引
2、优化长难的查询语句
(1)切分查询
大查询分为多个小查询,如删除10000 变为100次删100条
(2)分解关联查询
将一条关联语句分解成多条SQL,让缓存的效率更高,执行单个查询可以减少锁的竞争,在应用层做关联可以更容易对数据库进行拆分
3、优化特定类型的查询语句
优化count()
(1)count() 而不要用count(cloumn)
(2)explain找近似时间的cloumn来替代count()
(3)增加汇总表
(4)使用缓存
优化关联查询
(1)确定on或using子句的列上有索引
(2)确保group by 和order by中只有一个表中的列,这样才能用上索引
优化子查询(嵌套查询)
(1)尽可能使用关联查询来替代
优化group by 和distinct
(1)使用索引优化
(2)使用标识列(主键)分组效率更高
(3)不需要使用order by时可以使用 order by null 这样mysql就不会进行文件排序了
(4)with rollup超级聚合,可以放到应用程序中处理
优化limit分页
(1)偏移量大时,查询效率低,可以记录上次查询的最大ID
优化union
(1)union all 效率高于 union,即不进行查重
mysql高可扩展和高可用
1、分区表原理
物理底层将分区表划分为多个物理子表
- 工作原理:创建表时候用partition by子句,查询时,优化器会根据分区定义过滤没有我们需要的数据的分区
- 主要目的:按一个较粗的粒度分在不同的表中,这样可以将相关的数据存放在一起,如果想一次性删除整个分区的数据也方便
- 适用场景:表很大,无法全部存在内存,或者只在表的最后有热点数据;数据更易维护,可以对独立的分区进行独立的操作;数据可以分布在不同的机器上,从而高效的使用资源;使用分区来避免某些特殊的瓶颈;可以备份和恢复独立的分区
- 限制:最多1024个分区;5.1之后分区表达式必须是整数,5.5版本后可以使用列分区;分区字段中有主键和唯一索引,那么它们都必须包含进来;分区表无法使用外键;对现有表结构做修改;所有分区必须相同存储引擎
2、分库分表原理 - 工作原理:通过算法或者工具将表垂直或者水平进行物理切分。
- 适用场景:单表记录条数达到百万到千万级别;解决表锁的问题
- 分表方式:水平分割。常用数据和不常用数据的切分;垂直分表。常用列和不常用列的切分。
- 分表缺点:分表往往基于应用层的逻辑算法,扩展性较差;对于应用层来说,增加开发成本。
3、mysql复制原理及负载均衡
(1)工作原理:
主库数据更改记录在二进制日志中,从库会由此日志执行相同操作进行复制
(2)解决的问题 - 数据分布:随意停止或开始复制,在不同地理位置分布数据备份
- 负载均衡:降低单个服务器的压力
- 高可用和故障切换:帮助应用程序避免单点失败
- 升级测试:高版本做从库,看是否有问题
mysql安全性
1、SQL查询安全方案
(1)预处理语句防止SQL注入(prepare语句)
(2)写入数据库的数据要进行特殊字符的转义
(3)查询错误信息不要返回给用户,将错误记录到日志
(4)尽量使用PDO对数据库进行相关操作,PDO拥有对预处理语句很好的支持的方法,MySQLi也有,但是可扩展性不如PDO。MySQL不支持预处理
2、mysql安全设置
(1)定期做数据备份
(2)不给查询用户root权限,合理分配权限
(3)关闭远程访问数据库权限
(4)修改root密码
(5)删除多余的用户
(6)改变root用户名称
(7)限制一般用户浏览其他库
(8)限制用户对数据文件的访问权限
框架基础知识
MVC框架工作原理
深入理解MVC
1、单一入口
(1)工作原理:用一个处理程序文件处理所有的HTTP请求,根据参数的不同区分不同的模块和操作的请求
(2)优势:
- 所有请求都通过index,可以进行统一的安全性检查
- 集中处理程序
(3)劣势: - url地址不美观(可以用URL重写美化)
- 处理效率会稍低
2、模板引擎
Smarty、Liquid
工作原理:模板引擎就是庞大的完善的正则表达式替换库
常见框架特性
1、Yaf
(1)特性:C语言编写PHP拓展形式的框架
(2)优点:执行效率高、轻量级框架、可扩展性强
(3)缺点:高版本兼容性差、底层代码可读性差、需要安装扩展、功能单一、开发需要编写大量的插件
2、Yii2
(1)特性:通用Web后端框架
(2)优点:结构简单优雅、实用功能丰富、扩展性强、性能高
(3)缺点:学习成本高,量级较重
高并发解决方案
基础概念
- QPS:每秒请求数
- PV:综合浏览量,一个访客24h内访问页面数量
- UV:独立访客量
- 吞吐量:单位时间处理请求数
- 响应时间:请求发出到收到响应花费的时间
- 带宽:日网站带宽 = PV / 统计时间(秒) * 平均页面大小(KB)* 8
- (总PV * 80%)/ (6小时秒数 * 20%) = 峰值每秒请求数
压力测试
测试能承受的最大并发,测试最大承受的QPS
性能测试工具:ab
- 使用:ab -c 100 -n 5000 待测试网站
- 注意事项:测试机器与被测试机器分开;
不要对线上服务做压力测试 - 观察测试工具ab所在的机器,以及被测试的前端机的CPU,内存,网络等都不超过最高限度的75%
优化策略
QPS=100
数据库缓存层、数据库的负载均衡
QPS=800
带宽吃紧,CDN加速,负载均衡
QPS=1000
静态HTML缓存
QPS=2000
业务分离,分布式存储
(1)流量优化
防盗链处理
(2)前端优化
减少HTTP请求、添加异步请求、启用浏览器缓存和文件压缩、CDN加速、建立独立图片服务器
(3)服务端优化
页面静态化、并发处理、队列处理
(4)数据库优化
数据库缓存、分库分表、分区操作、读写分离、负载均衡
(5)服务器优化
负载均衡(7层nginx,4层lvs)
防盗链处理
通过referer或者签名,网站可以检测目标网页访问的来源网页,一旦检测到来源不是本站即进行阻止或者返回指定的页面
nginx ngx_http_referer_module用于阻挡来源非法的域名请求
nginx指令 valid_referers,全局变量$invalid_referer
动态语言层的动态处理
进程、线程、协程
(1)进程:执行中的程序
三态模型:运行、就绪、阻塞
五态模型:新建态、终止态、活跃就绪、静止就绪、活跃阻塞、静止阻塞
(2)线程:进程中的实体
三种状态:运行、就绪、阻塞
(3)协程:用户态的轻量级线程
调度由用户控制,有自己的寄存器上下文和栈,切换时需要转移寄存器内容
多进程、多线程
同步阻塞模型
(1)多进程
最早的服务端程序都是多进程多线程来解决并发IO的,一个请求创建一个进程,然后子进程进入循环同步堵塞地与客户端连接进行交互,收发处理数据
(2)多线程
线程可以直接与客户端联系,阻塞等待客户端连接
(3)缺点
- 严重依赖进程的数量解决并发问题
- 启动大量进程会带来额外的进程调度消耗
异步非阻塞模型
很多高并发异步IO服务器程序都是基于epoll实现的
IO复用异步非阻塞程序使用经典的Reactor模型,本身不处理任何数据收发。只是可以监视一个socket句柄的事件变化
PHP并发编程实践
(1)Swoole扩展
(2)消息队列
- 应用场景:异步操作、应用解耦、流量削峰
(3)接口的并发请求
curl_multi_init
数据库缓存
什么是数据库缓存
解决数据库服务器的压力
提高应用数据的响应速度
常见形式:内存缓存、文件缓存
为什么要使用缓存
为了让客户端少访问甚至不访问数据库而进行数据查询,最大程度的降低对数据库服务器的访问压力
- 缓存方式:内存
- 缓存场景:读多写少
- 缓存数据实时性:不建议实时更新
- 缓存数据稳定性:主从、集群保证可用
使用MySQL查询缓存
- query_cache_type (0,1,2)
0 - 不使用缓存
1 - 永远使用缓存。select SQL_NO_CACHE * ... 可以关闭查询缓存
2 - 按需使用查询缓存。select SQL_CACHE * ... 开启查询缓存 - query_cache_size
默认为0,表示为查询缓存预留的内存为0
set global query_cache_size=111111;设置内存大小 - 缓存可以看做是SQL文本和结果的映射
- 表结构或数据改变时,缓存失效
- flush query cache;//清理查询缓存内存碎片
- reset query cache;//从查询缓存中移出所有查询
- flush table;//关闭所有打开的表,同时清空缓存
使用Memcache缓存
中间缓存层;分布式高速缓存系统
使用Redis缓存
redis和memcached的区别
1、Redis和Memcache都是将数据存放在内存中,都是内存数据库。不过memcache还可用于缓存其他东西,例如图片、视频等等;
2、Redis不仅仅支持简单的k/v类型的数据,同时还提供list,set,hash等数据结构的存储;
3、虚拟内存--Redis当物理内存用完时,可以将一些很久没用到的value 交换到磁盘;
4、过期策略--memcache在set时就指定,例如set key1 0 0 8,即永不过期。Redis可以通过例如expire 设定,例如expire name 10;
5、分布式--设定memcache集群,利用magent做一主多从;redis可以做一主多从。都可以一主一从;
6、存储数据安全--memcache挂掉后,数据没了;redis可以定期保存到磁盘(持久化);
7、灾难恢复--memcache挂掉后,数据不可恢复; redis数据丢失后可以通过aof恢复;
8、Redis支持数据的备份,即master-slave模式的数据备份;
9、应用场景不一样:Redis出来作为NoSQL数据库使用外,还能用做消息队列、数据堆栈和数据缓存等;Memcached适合于缓存SQL语句、数据集、用户临时性数据、延迟查询数据和session等。
Memcached和Redis作为两种Inmemory的key-value数据库,在设计和思想方面有着很多共通的地方,功能和应用方面在很多场合下(作为分布式缓存服务器使用等) 也很相似,在这里把两者放在一起做一下对比的介绍
数据库优化
(1)数据类型优化
decimal
char定长,varchar变长
enum,特定固定分类
IP存储,转化为整型存储
(2)索引优化
高区分度,低查询量
复合索引前缀原则
like查询 % 问题
全表扫描优化
or条件索引使用情况,前条件有索引,后条件没索引则用不上索引了
字符串类型索引失效问题
(3)语句优化
优化查询过程中的数据访问,使用limit限制,不用select *
优化长难句,变复杂为简单,切分查询,分解关联查询
优化特定类型语句,优化count(),优化关联查询,优化子查询,优化group by 和distinct ,优化limit 和 union
(4)引擎优化
优先InnoDB
(5)表结构设计优化
分区
分库分表
(6)服务器架构优化
主从复制
二进制文件实现主从复制
读写分离
双主热备
负载均衡
负载均衡
七层负载均衡
基于URL等应用层信息的负载均衡,nginx proxy
四层负载均衡
软件 LVS 和 硬件 F5
欢迎大家关注我的公众号