很多站长朋友们都不太清楚php代码高可用,今天小编就来给大家整理php代码高可用,希望对各位有所帮助,具体内容如下:
本文目录一览: 1、 PHP中高级面试题 – 第三天 2、 怎么提高php编程能力? 3、 php文件代码 4、 如何实现php+session+memcached高可用集群 5、 PHP的性能探讨和测试 6、 php有哪些优势和特点 PHP中高级面试题 – 第三天一、简述一下MongoDB的应用场景
mongodb 支持副本集、索引、自动分片,可以保证较高的性能和可用性。
更高的写入负载
默认情况下,MongoDB 更侧重高数据写入性能,而非事务安全,MongoDB 很适合业务系统中有大量 “低价值” 数据的场景。但是应当避免在高事务安全性的系统中使用 MongoDB,除非能从架构设计上保证事务安全。
高可用性
MongoDB 的复副集 (Master-Slave) 配置非常简洁方便,此外,MongoDB 可以快速响应的处理单节点故障,自动、安全地完成故障转移。这些特性使得 MongoDB 能在一个相对不稳定(如云主机)的环境中,保持高可用性。
数据量很大或者未来会变得很大
依赖数据库 (MySQL) 自身的特性,完成数据的扩展是较困难的事,在 MySQL 中,当一个单达表到 5-10GB 时会出现明显的性能降级,此时需要通过数据的水平和垂直拆分、库的拆分完成扩展,使用 MySQL 通常需要借助驱动层或代理层完成这类需求。而 MongoDB 内建了多种数据分片的特性,可以很好地适应大数据量的需求。
基于位置的数据查询
MongoDB 支持二维空间索引,因此可以快速及精确地从指定位置获取数据。
表结构不明确
在一些传统 RDBMS 中,增加一个字段会锁住整个数据库 / 表,或者在执行一个重负载的请求时会明显造成其它请求的性能降级。通常发生在数据表大于 1G 的时候(当大于 1TB 时更甚)。 因 MongoDB 是文档型数据库,为非结构货的文档增加一个新字段是很快速的操作,并且不会影响到已有数据。另外一个好处当业务数据发生变化时,是将不再需要由 DBA 修改表结构。
二、数据库设计经验,为什么进行分表?分库?一般多少数据量开始分表?分库?分库分表的目的?
1、为什么要分表
当一张表的数据达到几百万时,你查询一次所花的时间会变多,如果有联合查询的话,有可能会死在那儿了。分表的目的就在于此,减小数据库的负担,缩短查询时间。日常开发中我们经常会遇到大表的情况,所谓的大表是指存储了百万级乃至千万级条记录的表。这样的表过于庞大,导致数据库在查询和插入的时候耗时太长,性能低下,如果涉及联合查询的情况,性能会更加糟糕。
分表和表分区的目的就是减少数据库的负担,提高数据库的效率,通常点来讲就是提高表的增删改查效率。数据库中的数据量不一定是可控的,在未进行分库分表的情况下,随着时间和业务的发展,库中的表会越来越多,表中的数据量也会越来越大,相应地,数据操作,增删改查的开销也会越来越大;另外,由于无法进行分布式式部署,而一台服务器的资源(CPU、磁盘、内存、IO 等)是有限的,最终数据库所能承载的数据量、数据处理能力都将遭遇瓶颈。
2、分表的方案
做 mysql 集群,有人会问 mysql 集群,根分表有什么关系吗?虽然它不是实际意义上的分表,但是它启到了分表的作用,做集群的意义是什么呢?为一个数据库减轻负担,说白了就是减少 sql 排队队列中的 sql 的数量,举个例子:有 10 个 sql 请求,如果放在一个数据库服务器的排队队列中,他要等很长时间,如果把这 10 个 sql 请求,分配到 5 个数据库服务器的排队队列中,一个数据库服务器的队列中只有 2 个,这样等待时间是不是大大的缩短了呢?
linux mysql proxy 的安装,配置,以及读写分离
mysql replication 互为主从的安装及配置,以及数据同步
优点:扩展性好,没有多个分表后的复杂操作(php 代码)
缺点:单个表的数据量还是没有变,一次操作所花的时间还是那么多,硬件开销大。
三、简述一下数据库主从复制,读写分离
* 什么是主从复制
主从复制,是用来建立一个和主数据库完全一样的数据库环境,称为从数据库;
* 主从复制的原理:
1.数据库有个bin-log二进制文件,记录了所有的sql语句。
2.只需要把主数据库的bin-log文件中的sql语句复制。
3.让其从数据的relay-log重做日志文件中再执行一次这些sql语句即可。
* 主从复制的作用
1.做数据的热备份,作为后备数据库,主数据库服务器故障后,可切换到从数据库继续工作,避免数据丢失。
2.架构的扩展。业务量越来越大,I/O访问频率过高,单机无法满足,此时做多库的存储,降低磁盘I/O访问频率,提高单机的I/O性能
3.主从复制是读写分离的基础,使数据库能制成更大 的并发。例如子报表中,由于部署报表的sql语句十分慢,导致锁表,影响前台的服务。如果前台服务使用master,报表使用slave,那么报表sql将不会造成前台所,保证了前台的访问速度。
* 主从复制的几种方式:
1.同步复制:所谓的同步复制,意思是master的变化,必须等待slave-1,slave-2,…,slave-n完成后才能返回。
2.异步复制:如同AJAX请求一样。master只需要完成自己的数据库操作即可。至于slaves是否收到二进制日志,是否完成操作,不用关心。MYSQL的默认设置。
3.半同步复制:master只保证slaves中的一个操作成功,就返回,其他slave不管。
这个功能,是由google为MYSQL引入的。
* 关于读写分离
在完成主从复制时,由于slave是需要同步master的。所以对于insert/delete/update这些更新数据库的操作,应该在master中完成。而select的查询操作,则落下到slave中。
怎么提高php编程能力?要想提高你的PHP编程能力,你可以做两件事情:1)更扎实的掌握基本编程技能;2)更细微、更深入地了解PHP。
以下总结出的几条指南导航将有助于提高开发者的PHP编程能力:
一、提高PHP编码能力的10个细节
或许你并不能从这些细节中学到绝对新的东西(例如“如何对变量和函数做好的命名”,“对代码做好注释”,“频繁测试代码”),而它们可以让你巩固基础知识。以下几点解释了为什么最好的普通编程实践在PHP应用软件开发中尤为重要。
其中10点建议分别为:
1)如何开始良好的开发风格;
2)合适的变量及函数命名;
3)注释代码;
4)自己动手做大部分的工作;
5)多方涉猎;
6)了解开发语言的局限性;
7)接受结构上的意见反馈;
8)频繁的测试代码;
9)在自己的工程上内嵌程序;
10)不要把每一个文件都分一个文件夹
二、写出更优PHP代码的7条法则
以下7种方法列举出了PHP开发商极有可能面对的问题(例如不使用模板,不合适的封装,在增删修改时PHP和SQL的混淆使用等等),对于那些很有可能危害到PHP应用程序运行的各种复杂语句,该指南也提供了多种方法来清除(例如对大容量的网页减少数据库查询)。
以下是关键点:
1)在模板中使用可选择的PHP语法;
2)封装所有的东西;
3)使用一个数据库对象;
4)使用增删查改功能;
5)与调试为友;
6)重视命名;
7)减少数据库查询。
php文件代码123.php 是一个php文件。
要想执行这个文件。必须搭建支持解析php的web服务器。
在Windows下最常见的web服务软件组合为wamp。下载地址;nbsp;这个软件执行效率和稳定性较高。
安装后服务器目录结构如图所示。
www就是网站根目录
把123.php放在www这个目录下,启开web服务就可以使用访问了
127.0.0.1 是机器内置的自身循环地址。指向机器本身
标准访问是127.0.0.1:端口号。网页服务默认端口号是80
在没有修改端口的情况下可以直接使用127.0.0.1访问
服务则自动解析为127.0.0.1:80;
;nbsp;
和是等价的。
page是一个传递变量,传递的值为"php.php",这些值可以更具需要随意修改。
你可以在123.php中使用代码
<?php
print_r($_GET);//打印get方式提交的值
?>
如何实现php+session+memcached高可用集群在这个互联网高度发达的时代,许多应用的用户动辄成百上千万,甚至上亿。为了支持海量用户的访问,应用服务器集群这种水平扩展的方式是最常用的。这种情形下,就会涉及到许多单机环境下完全不需要考虑的问题,这其中session的创建、共享和存储是最常见之一。
在单机环境中,Session的创建和存储都是由同一个应用服务器实例来完成,而存储也仅是内存中,最多会在正常的停止服务器的时候,把当前活动的Session钝化到本地,再次启动时重新加载。
而多个实例之间,Session数据是完全隔离的。而为了实现Session的高可用,多实例间数据共享是必然的,下面我们以Redis 的SessionManager实现多Tomcat实例Session共享的配置为例,我们来梳理下一般session共享的流程:
添加具体要使用的manager的Jar文件及其依赖
redis session manager依赖jedis, commons-pool, commons-pool2
对应版本的redis session manager的jar文件
在TOMCAT_HOME/conf/context.xml中增加如下配置
<Valve className="com.radiadesign.catalina.session.RedisSessionHandlerValve" />
<Manager className="com.radiadesign.catalina.session.RedisSessionManager"
host="localhost"
port="6379" database="0"
maxInactiveInterval="30" />
其中host和port等替换为对应的配置信息
启动多个Tomcat实例,以自带的examples应用为例进行验证
访问examples应用的servlets/servlet/SessionExample,
在页面中添加数据到session中,并查看页面上对应的session信息
访问另一个实例上相同应用的页面,查看session信息,两者应该是一致的
使用redis-cli查看redis中存储的对应数据,相应的sessionId对应的数据已经保存了下来
以上是一个基本的配置过程,而在这些配置与验证的步骤中,第二步是核心逻辑实现。 前面的文章,曾介绍过Tomcat的Valve,在请求处理时,Pipeline中的各个Valve的invoke方法会依次执行。Tomcat的AccessLogValve介绍
此处的session处理,就是以一个自定义Valve的形式进行的。关于Session的文章,前面也写过几篇,会附在结尾处。
以下是RedisSessionhandlerValve的invoke方法,我们看,主要是在Valve执行后进行Session的存储或移除。
public void invoke(Request request, Response response) {
try {
getNext().invoke(request, response);
} finally {
final Session session = request.getSessionInternal(false);
storeOrRemoveSession(session);
manager.afterRequest();
}
}
而session的保存和移除又是通过manager执行的。 manager.save(session); manager.remove(session);
这里,manager就是前面定义的RedisSessionManager。默认单实例情况下,我们使用的都是StandardManager,对比一下两者,标准的Manager对于session的创建和删除,都会调到其父类ManagerBase中相应的方法,
public void add(Session session) {
sessions.put(session.getIdInternal(), session);
int size = getActiveSessions();
if( size > maxActive ) {
synchronized(maxActiveUpdateLock) {
if( size > maxActive ) {
maxActive = size;
}
}
}
}
public void remove(Session session, boolean update) {
if (session.getIdInternal() != null) {
sessions.remove(session.getIdInternal());
}
}
我们来看,由于其只保存在内存的Map中protected Map<String, Session> sessions = new
ConcurrentHashMap<>(),每个Tomcat实例都对于不同的map,多个实例间无法共享数据。
对应到RedisSessionManager对于session的处理,都是直接操作redis,基本代码是下面这个样:
public void save(Session session) throws IOException {
Jedis jedis = null;
Boolean error = true;
try {
RedisSession redisSession = (RedisSession) session;
Boolean sessionIsDirty = redisSession.isDirty();
redisSession.resetDirtyTracking();
byte[] binaryId = redisSession.getId().getBytes();
jedis = acquireConnection();
if (sessionIsDirty || currentSessionIsPersisted.get() != true) {
jedis.set(binaryId, serializer.serializeFrom(redisSession));
}
currentSessionIsPersisted.set(true);
jedis.expire(binaryId, getMaxInactiveInterval());
} }
移除时的操作是这样的
public void remove(Session session, boolean update) {
Jedis jedis = null;
Boolean error = true;
log.trace("Removing session ID : " + session.getId());
try {
jedis = acquireConnection();
jedis.del(session.getId());
error = false;
} finally {
if (jedis != null) {
returnConnection(jedis, error);
}
}
}
而此时,多个Tomcat实例都读取相同的Redis,session数据是共享的,其它实例的初始请求过来时,由于会执行findSession的操作,此时会从Redis中加载session,
public Session findSession(String id) throws IOException {
RedisSession session;
if (id == null) {
session = null;
currentSessionIsPersisted.set(false);
} else if (id.equals(currentSessionId.get())) {
session = currentSession.get();
} else {
session = loadSessionFromRedis(id); // 看这里,会从redis中load
if (session != null) {
currentSessionIsPersisted.set(true);
}
}
currentSession.set(session);
currentSessionId.set(id);
return session;
}
从而可以保证在一个实例被切换后,另外的实例可以继续响应同一个session的请求。
以上即为Redis实现session共享高可用的一些关键内容。有兴趣的朋友可以看下通过Memcached实现高可用,也是这个原理。顺着这个思路,如果你有将Session存储在其它地方的需求时,完全可以写一个出来,自己动手,丰衣足食。
总结一下,我们是通过自定义的Valve来实现请求后session的拦截,同时,使用自定义的SessionManager,来满足不同的session创建与存储的需求。而至于是存储在Redis/Memcached中,还是存储在DB中,只是位置的区别。原理,是一致的。
PHP的性能探讨和测试缘起
关于PHP 很多人的直观感觉是PHP是一种灵活的脚本语言 库类丰富 使用简单 安全 非常适合WEB开发 但性能低下 PHP的性能是否真 的就如同大家的感觉一样的差呢?本文就是围绕这么一个话题来进行探讨的 从源码 应用场景 基准性能 对比分析等几个方面深入分析PHP之性能问题 并通 过真实的数据来说话
从原理分析PHP性能
从原理分析PHP的性能 主要从以下几个方面 内存管理 变量 函数 运行机制来进行分析
内存管理
类似Nginx的内存管理方式 PHP在内部也是基于内存池 并且引入内存池的生命周期概念 在内存池方面 PHP对PHP脚本和扩展的所有内 存相关操作都进行了托管 对大内存和小内存的管理采用了不同的实现方式和优化 具体可以参考以下文档 在内存分配和回收的生命周期内 PHP采用一次初始化申请+动态扩容+内存标识回收机制 并且在每次请求结束后直 接对内存池进行重新mask
变量
总所周知 PHP是一种弱变量类型的语言 所以在PHP内部 所有的PHP变量都对应成一种类型Zval 其中具体定义如下
图一PHP变量
在变量方面 PHP做了大量的优化工作 比如说Reference counting和copy on writer机制 这样能够保证内存使用上的优化 并且减少内存拷贝次数(请参考) 在数组方面 PHP内部采用高效的hashtable来实现
函数
在PHP内部 所有的PHP函数都回转化成内部的一个函数指针 比如说扩展中函数
ZEND_FUNCTION ( my_function );//类似function my_function(){}
在内部展开后就会是一个函数
void zif_my_function ( INTERNAL_FUNCTION_PARAMETERS );
void zif_my_function(
int ht
zval * return_value
zval * this_ptr
int return_value_used
zend_executor_globals * executor_globals
);
从这个角度来看 PHP函数在内部也是对应一个函数指针
运行机制
在话说PHP性能的时候 很多人都会说“C/C++是编译型 JAVA是半编译型 PHP是解释型” 也就是说PHP是先动态解析再代码运行的 所以从这个角度来看 PHP性能必然很差
的确 从PHP脚本运行来输出 的确是一个动态解析再代码运行的过程 具体来说 PHP脚本的运行机制如下图所示
图二 PHP运行机制
PHP的运行阶段也分成三个阶段
Parse 语法分析阶段
Compile 编译产出opcode中间码
Execute 运行 动态运行进行输出
所以说 在PHP内部 本身也是存在编译的过程 并且据此产生了大量的opcode cache工具 比如说apc eacc xcache等等 这些opcode cache在生产环境基本上在标配 基于opcode cache 能到做到“PHP脚本编译一次 多次运行”的效果 从这点上 PHP就和JAVA的半编译机制非常类似
所以 从运行机制上来看 PHP的运行模式和JAVA是非常类似的 都是先产生中间码 然后运行在不同虚拟机上
动态运行
从上面的几个分析来看 PHP在内存管理 变量 函数 运行机制等几个方面都做了大量的工作 所以从原理来看 PHP 不应该存在性能问题 性能至少也应该和Java 比较接近
这个时候就不得不谈PHP动态语言的特性所带来的性能问题了 由于PHP是动态运行时 所以所有的变量 函数 对象调用 作用域实现等等都是在 执行阶段中才确定的 这个从根本上决定了PHP性能中很难改变的一些东西 在C/C++等能够在静态编译阶段确定的变量 函数 在PHP中需要在动态运行 中确定 也就决定了PHP中间码不能直接运行而需要运行在Zend Engine上
说到PHP变量的具体实现 又不得不说一个东西了 Hashtable Hashtable可以说在PHP灵魂之一 在PHP内部广泛用到 包含变量符号栈 函数符号栈等等都是基于hashtable的
以PHP变量为例来说明下PHP的动态运行特点 比如说代码
<?php
$var = “hello blog xiuwz ”;
?>
该代码的执行结果就是在变量符号栈(是一个hashtable)中新增一个项
当要使用到该变量时候 就去变量符合栈中去查找(也就是变量调用对出了一个hash查找的过程)
同样对于函数调用也基本上类似有一个函数符号栈(hashtable)
其实关于动态运行的变量查找特点 在PHP的运行机制中也能看出一些 PHP代码通过解释 编译后的流程下图
图 PHP运行实例
从上图可以看出 PHP代码在pile之后 产出的了类符号表 函数符号表 和OPCODE 在真正执行的时候 zend Engine会根据op code去对应的符号表中进行查找 处理
从某种程度上 在这种问题的上 很难找到解决方案 因为这是由于PHP语言的动态特性所决定的 但是在国内外也有不少的人在寻找解决方案 因为 通过这样 能够从根本上完全的优化PHP 典型的列子有facebook的hiphop
结论
从上面分析来看 在基础的内存管理 变量 函数 运行机制方面 PHP本身并不会存在明显的性能差异 但由于PHP的动态运行特性 决定了 PHP和其他的编译型语言相比 所有的变量查找 函数运行等等都会多一些hash查找的CPU开销和额外的内存开销 至于这种开销具体有多大 可以通过后 续的基准性能和对比分析得出
因此 也可以大体看出PHP不太适合的一些场景 大量计算性任务 大数据量的运算 内存要求很严格的应用场景 如果要实现这些功能 也建议通过扩展的方式实现 然后再提供钩子函数给PHP调用 这样可以减低内部计算的变量 函数等系列开销
基准性能
对于PHP基准性能 目前缺少标准的数据 大多数同学都存在感性的认识 有人认为 QPS就是PHP的极限了 此外 对于框架的性能和框架对性能的影响很没有响应的权威数字
本章节的目的是给出一个基准的参考性能指标 通过数据给大家一个直观的了解
具体的基准性能有以下几个方面
裸PHP性能 完成基本的功能
裸框架的性能 只做最简单的路由分发 只走通核心功能
标准模块的基准性能 所谓标准模块的基准性能 是指一个具有完整服务模块功能的基准性能
环境说明
测试环境
Uname aPnux db forum test db baidu _ # SMP Wed Aug : : CST x _ x _ x _ GNU/Pnux
Red Hat Enterprise Pnux AS release (Nahant Update )
Intel(R) Xeon(R) CPU E @ GHz
软件相关
Nginx nginx version: nginx/ built by gcc (Red Hat )
Php (采用php fpm)
PHP (cP) (built: Mar : : )
Copyright (c) The PHP Group
Zend Engine v Copyright (c) Zend Technologies
with eAccelerator v Copyright (c) eAccelerator by eAccelerator
bingo
PHP框架
其他说明
目标机器的部署方式 nginx >php fpm >php脚本
测试压力机器和目标机器独立部署
裸PHP性能
最简单的PHP脚本
<?php
require_once ‘ /actions/indexAction php’;
$objAction = new indexAction();
$objAction >init();
$objAction >execute();
?>
Acitons/indexAction php里面的代码如下
<?php
class indexAction
{
pubPc function execute()
{
echo ‘hello world!’;
}
}
?>
通过压力工具测试结果如下
裸PHP框架性能
为了和 的对比 基于bingo 框架实现了类似的功能 代码如下
<?php
require_once ‘Bingo/Controller/Front php’;
$objFrontController = Bingo_Controller_Front::getInstance(array(
‘actionDir’ => ‘ /actions’
));
$objFrontController >dispatch();
压力测试结果如下
从该测试结果可以看出 框架虽然有一定的消耗 但对整体的性能来说影响是非常小的
标准PHP模块的基准性能
所谓标准PHP模块 是指一个PHP模块所必须要具体的基本功能
路由分发
自动加载
LOG初始化Notice日志打印 所以的UI请求都一条标准的日志
错误处理
时间校正
自动计算每个阶段耗时开销
编码识别编码转化
标准配置文件的解析和调用
采用bingo 的代码自动生成工具产生标准的测试PHP模块 test
测试结果如下
结论
从测试数据的结论来看 PHP本身的性能还是可以的 基准性能完全能够达到几千甚至上W的QPS 至于为什么在大多数的PHP模块中表现不佳 其实这个时候更应该去找出系统的瓶颈点 而是简单的说OK PHP不行 那我们换C来搞吧 (下一个章节 会通过一些例子来对比 采用C来处理不见得有特 别的优势)
通过基准数据 可以得出以下几个具体的结论
PHP本身性能也很不错 简单功能下能够达到 QPS 极限也能过W
PHP框架本身对性能影响非常有限 尤其是在有一定业务逻辑和数据交互的情况下 几乎可以忽略
一个标准的PHP模块 基准性能能够达到 QPS( cpu idle)
对比分析
lishixinzhi/Article/program/PHP/201311/21287
php有哪些优势和特点PHP的优势包括:
PHP开放的源代码
所有的PHP源代码事实上都可以得到。
PHP是免费的
和其它技术相比,PHP本身免费且是开源代码。
快捷性
程序开发快,运行快,技术本身学习快。嵌入于HTML:因为PHP可以被嵌入于HTML语言,它相对于其他语言。编辑简单,实用性强,更适合初学者。
跨平台性强
由于PHP是运行在服务器端的脚本,可以运行在UNIX、LINUX、WINDOWS、Mac OS下。
效率高
PHP消耗相当少的系统资源。
图像处理
用PHP动态创建图像,PHP图像处理默认使用GD2。且也可以配置为使用image magick进行图像处理。
面向对象
在php4,php5 中,面向对象方面都有了很大的改进,php完全可以用来开发大型商业程序。
专业专注
PHP支持脚本语言为主,同为类C语言,容易入门。
关于php代码高可用的介绍到此就结束了,不知道本篇文章是否对您有帮助呢?如果你还想了解更多此类信息,记得收藏关注本站,我们会不定期更新哦。
查看更多关于php代码高可用 php支持高并发吗的详细内容...