我们专注攀枝花网站设计 攀枝花网站制作 攀枝花网站建设
成都网站建设公司服务热线:400-028-6601

网站建设知识

十年网站开发经验 + 多家企业客户 + 靠谱的建站团队

量身定制 + 运营维护+专业推广+无忧售后,网站问题一站解决

php数据库集群管理 php apache mysql集成

PHP集群如何部署?当网站的访问,数据过多时.程序应该如何调整?

个人建议 至少4台服务器,并且最好是以局域网方式互通(服务器4可以完全独立)

上蔡网站建设公司创新互联,上蔡网站设计制作,有大型网站制作公司丰富经验。已为上蔡近1000家提供企业网站建设服务。企业网站搭建\成都外贸网站建设公司要多少钱,请找那个售后服务好的上蔡做网站的公司定做!

服务器1和服务器2都只放php代码程序,暴露在外网,分别当电信服务器和网通服务器

服务器3只放数据库,通过用户权限,仅允许被服务器1和2访问——不暴露在外网

服务器4只放附件,暴露在外网,所有的附件请求,都直接对这个服务器进行

需要指出的是,你如果作为网站管理者,每次管理数据库,都要用1或者2当跳板,才可以访问。

关于PHP-Apache-Mysql高并发集群(详细加双倍分)

这个这样说很难说详细,第一可以用阿里云的SLB,但是我没配置这个, 具体实施不清楚,而且要保证2台或者3台服务器的数据是一致的。理想情况下是可以用nginx做反向代理或者用lvs,不熟起来相对有些小小难度。建议不要用windows了。具体可以详聊。

如何实现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 MapString, 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 apache mysql集成
文章分享:http://shouzuofang.com/article/dosjigc.html

其他资讯