手机之家新系统介绍及架构分享

36
手手手手手手 手手手手手手手 IMOBILE TEAM 2009.03.29

description

手机之家 (Imobile.com.cn) 在 Beta 技术沙龙上的分享 PPT

Transcript of 手机之家新系统介绍及架构分享

Page 1: 手机之家新系统介绍及架构分享

手机之家新系统介绍及架构分享IMOBILE TEAM2009.03.29

Page 2: 手机之家新系统介绍及架构分享

手机之家首页

Page 3: 手机之家新系统介绍及架构分享

一)手机之家新系统介绍1) 关于手机之家2) 新系统概览

二)软件架构分享1)架构演变与发展2) DAL设计概览3)持续改进

三) Q & A

目录

Page 4: 手机之家新系统介绍及架构分享

手机之家新系统介绍

Page 5: 手机之家新系统介绍及架构分享

关于手机之家

手机之家是一个旨在提供全方位的手机相关服务的资讯类网站。在 7年的时间里,手机之家从无到有,已经发展成为极具人气、最受关注的手机产品资讯网站。

目前已有的一些统计数据:a. 1000w+用户b. 3000w+帖子c. 1.1TB+附件d. 780w+ Page View/每天e. 5~10w在线用户 /15分钟

Page 6: 手机之家新系统介绍及架构分享

新系统概览 (1)

a. 从头设计、全部重写

b. 100%采用开源软件

c.自行开发:Web层:MVC框架 , 模板引擎 , JS框架 ...基础组件:简单的 glue, Monkey(Java NIO框架 ), JMCL ...中间件: DAL(Data Access Layer), JMCD, Session, Tools,

小文件存储系统 , 基于 Lucene的搜索系统 ...

d.混合编程: PHP+JAVA

e.操作系统: centos5; 数据库:MySQL5; Web Server: Nginx

Page 7: 手机之家新系统介绍及架构分享

新系统概览 (3)

Logic

MySQL

Model MySQL

MySQL

DAL

中间件Ctrl

View

Web

Page 8: 手机之家新系统介绍及架构分享

软件架构分享

Page 9: 手机之家新系统介绍及架构分享

架构演变与发展 - 老系统的问题

a)由于系统分层比较模糊,导致问题极难排查,到底是哪个层面出现了错误 ?是页面相关的地方、访问数据的地方,还是处理逻辑的地方?

b)由于 web server可以直接访问 db server,在高峰阶段,并发量比较 大,导致 db server经常 down掉。

c)数据表结构设计不当,导致无法很简单地 (甚至不可能 )进行竖直和水平 方向的伸缩。

没有设计!

Page 10: 手机之家新系统介绍及架构分享

HTTP MySQL

MC

数据访问层表现层 逻辑层FastCGI MySQL

架构演变与发展 - 纯 PHP分层方案 (1)

R W

Page 11: 手机之家新系统介绍及架构分享

架构演变与发展 - 纯 PHP分层方案 (2)

方案 (1)解决了之前所说的问题。但是:

a)开发一个功能,要写很多代码,而且有大部份代码是相当乏味的,重复性 极高,千篇一律,特别是数据访问层代码。

b)程序员自己控制缓存。这使得: <1>缓存代码渗透到业务逻辑的每一个角落,造成代码维护成本上升。 <2>程序员根据自己的喜好来控制缓存的 KEY和 VALUE,造成缓存混乱。

<3>程序员既要负责业务逻辑的编写,还要负责缓存管理,造成编程复 杂度提高、开发效率低下。

这些问题,迫使我们寻找其它的解决方案。。。

Page 12: 手机之家新系统介绍及架构分享

架构演变与发展 - 改进缓存 (1)

我们对数据库记录的缓存的访问做了一定的抽象处理,开发出了 cache处理器。

所有的数据访问都经过 cache处理器。这样,系统代替程序员接管了缓存的存取访问。缓存的 KEY和 VALUE由系统处理,从而避免了冲突和混乱。

cache处理器的引入减少了 40%的数据访问层代码!

最重要的是,我们采用了 Namespace的方法使得缓存能自动清除了。

Page 13: 手机之家新系统介绍及架构分享

HTTP MySQL

MC

表现层 逻辑层FastCGI

架构演变与发展 - 改进缓存 (2)

R W

cache处理器

数据访问层cache处理器

NS处理器

php fcgi+

SQLite实现

Page 14: 手机之家新系统介绍及架构分享

架构演变与发展 - 改进缓存 (3)

但是问题又来了,此时,系统响应速度变得很慢。原因在于,我们Namespace是借助 PHP fcgi进程 +SQLite来实现的。

这促使我们对采用纯 PHP方案的可行性产生了质疑。。。

Page 15: 手机之家新系统介绍及架构分享

架构演变与发展 - PHP+JAVA,提升性能 (1)

memcached不支持 namespace,也不支持遍历。

所以,我们基于之前开发的monkey(java nio框架 )实现了一个支持 namespace – 遍历功能的内存缓存程序 jmcd。我们采用了简单高效的 STP协议。

Page 16: 手机之家新系统介绍及架构分享

架构演变与发展 - PHP+JAVA,提升性能 (2)

HTTP MySQL

MC

表现层 逻辑层FastCGI

R W

cache处理器

数据访问层cache处理器

NS处理器

基于 JMCL实现

Page 17: 手机之家新系统介绍及架构分享

架构演变与发展 - PHP+JAVA,提升性能 (3)

我们改进了 Session的实现方式:在monkey和 jmcl的基础上开发出session server。

这次响应时间提升了 80毫秒以上!这基本上达到了性能预期:平均每个页面响应时间低于 20毫秒。

Page 18: 手机之家新系统介绍及架构分享

架构演变与发展 - DA引入 , DAL产生 (1)

cache 处理器在缓存的存取方面有了很大的进步,但是由于接口众多,使用起来不太方面。而且还是要编写大量的重复代码。

为此,我们重构了这部份代码,吸收了其它框架的优点,开发出了 Data Accessor(简称 DA)。

Page 19: 手机之家新系统介绍及架构分享

架构演变与发展 - DA引入 , DAL产生 (2)

HTTPMySQL

MC

表现层 逻辑层

R/W

DA

JMCD

存储 NS、Id List、聚合运算结果

Page 20: 手机之家新系统介绍及架构分享

架构演变与发展 - DA引入 , DAL产生 (3)

DA标准化了调用接口,简化了编程,使程序员在业务逻辑层面不再关心缓存与切库分表,极大地提高了生产力 (代码量继续减少,易用性提高 )。

但是它仍然有很多不足。 DA直接和数据库打交道,在这一点上,可以说是又回到了起点。

不过,从逻辑上来说, DA已经是之后构想的 Data Access Layer的雏形,经过 4个月的运行测试,现在,我们把[原 DA]称为 DAL1.0,而把[原 DA]中包含的客户端程序仍然称为 DA。

Page 21: 手机之家新系统介绍及架构分享

架构演变与发展 - DAL2.0(1)

DAL1.0有很多不足,要弥补这些不足,必须从根本上进行重新设计。如果说 DAL1.0是为易用性而设计,那么 DAL2.0就是为性能、可用性等等而设计。。。

Page 22: 手机之家新系统介绍及架构分享

架构演变与发展 - DAL2.0(2)

HTTP MySQLDAL Server表现层 逻辑层SCGIDA

CACHE

JDBC

Oracle

???

JDBC

JDBC

Page 23: 手机之家新系统介绍及架构分享

DAL 设计概览 - 关于分库切表

1)垂直切分:按功能分。分到不同的数据库或服务器。

2)水平切分:对数据进行水平分割。a.最好分到同一个数据库。b.一种已经证明是切实可行的方案:主表+辅表。c.有 3种类型:主表不打散、主表打散无辅表、主表打散有辅表。d.但对程序员来说, TA看到的只是一张表,不妨称之为虚表 (逻辑表 ) ,这张虚表实际上可能是由 N张实表 (物理表 )组成的。

Page 24: 手机之家新系统介绍及架构分享

DAL 设计概览 - 关于缓存

1)缓存很重要。

2)但不应该紧耦合于业务逻辑。

3)慎用 XC/APC缓存,一般情况下,mc/jmc这种远程缓存已经够用了。

4)缓存的最佳实践:缓存单个条目,根据 id list(unique key list)找列表。

5)缓存能自动清理就自动清理,不能自动清理的想办法自动清理。

Page 25: 手机之家新系统介绍及架构分享

DAL 设计概览 - 目标

1)程序员不再关心 (尽量少关心 )分库切表问题,经 DBA配置,由 DAL 处理。

2)程序员不再关心缓存的存取与清理问题,由 DAL处理。

Page 26: 手机之家新系统介绍及架构分享

DAL 设计概览 - DA用法示例 (1)

1)增: DataAccessor::insert()->table('imobile.post.db_post')->data(array('post_id'=>1, ...))->dup()->execute();

2)删: DataAccessor::delete()->table('imobile.post.db_post')->where('post_id', 'IN', array(1, 2, 3))->limit(2)->execute();

Page 27: 手机之家新系统介绍及架构分享

DAL 设计概览 - DA用法示例 (2)

3)改: DataAccessor::update()->table('imobile.post.db_post')->data(array('level'=>0))->where('user_id', '<', 1000)->limit(100)->execute();

4)查: DataAccessor::select()->table('imobile.post.db_post')->columns('post_id')->where(array('thread_id'=>1, 'forum_id'=>2))->getPage();

Page 28: 手机之家新系统介绍及架构分享

DAL 设计概览 - DAL Server2.0设计目标

1)提升性能 :a.连接池b.并行查询、合并结果c.更好的缓存处理 (过期策略可配置、缓存提供者可配置等等 )

2)提高可用性 :a.多个 DAL实例 (1 available + n candidates)b.引入单数据库事务

3)其它:更智能的 where分析,表的状态监控, DAL更具可扩展性。。。

Page 29: 手机之家新系统介绍及架构分享

DAL 设计概览 - DAL Server2.0的可扩展设计

DAL Server2.0总体上设计成 (core + plugins)的形式。

core负责一些不可插件化 (或难以插件化 )的组件, plugins则是那些可插化的组件。

如配置处理、查询分析,选路策略,数据处理等等就是属于 core的内容。而 CacheProvider, ConnectionProvider...就是一些可插件化的例子。

Page 30: 手机之家新系统介绍及架构分享

DAL 设计概览 - DAL Server2.0示意图

Monkey

query executor

routing strategy

query parser cache provider

result merger

cache

MySQLconn provider

DAL Server2.0

config manager

result encoder

dal handler

Page 31: 手机之家新系统介绍及架构分享

DAL 设计概览 - 扩展 DAL概念 (1)

访问数据,可以是访问数据库中的数据,也可以是MC/JMCD当中的数据,那为什么不可以是 lucene索引中的数据?

Page 32: 手机之家新系统介绍及架构分享

DAL 设计概览 - 扩展 DAL概念 (2)

5)搜: DataAccessor::search()->index('imobile.thread.db_thread')->fields('title')->key('三星 ')->where(array('forum_id'=>2))->andWhere('date', 'BETWEEN', array(20090305, 20090310))->getPage();

Page 33: 手机之家新系统介绍及架构分享

DAL 设计概览 - 扩展 DAL概念 (3)

HTTP表现层 逻辑层

SCGI

DA

Search Server

SCGI

原 DAL Server

Data Access Layer

MySQL

Lucene索引

Page 34: 手机之家新系统介绍及架构分享

持续改进

1)很多轮子已成通用轮子。

2)不断完善已有轮子。

3)还会有新轮子出现:如,在表现层引入Widget,更好的存储系统 ...

Page 35: 手机之家新系统介绍及架构分享

Q&A

Page 36: 手机之家新系统介绍及架构分享

The End

Thanks:)