SlideShare a Scribd company logo
1 of 55
手机之家的数据访问层实践 许超前 @ 手机之家 2009 年 10 月 24 日
一、关于 DAL 二、 DAL1.0 的产生 三、走近 DAL2 四、 DAL 带来了什么 五、未来计划 六、 Q&A 目 录
1) 数据访问层 引用维基百科 : A Data Access Layer (DAL) is a layer of a computer program which provides  simplified access to data stored in persistent storage of some kind, such as an  entity-relational database. This data access layer is used in turn by other program modules to access and  manipulate the data within the data store without having to deal with the complexities inherent in this access.
1) 数据访问层 ( 续 ) 应用程序 Data Access Layer DB API 文件 DAL 在系统中的位置
2) 手机之家数据访问层 DAL1.0 和 DAL2.x 是手机之家开发的数据访问层的产品名的代号。下文如无特殊说明 DAL 代表此产品的通称。 DAL 是手机之家研发团队近几年在开发和运营上的经验的总结以及智慧的结晶。 开发 DAL 的目的是为了解决在构建大中型网站时遇到的和数据访问有关的诸多问题,如怎样使得分表透明化,怎样使得缓存存取清除自动化,怎样才能更好地防止服务单点故障等等。 DAL1.0 是一个具有里程碑意义的版本,但在很多方面仍然欠考虑。 DAL2.x 是一个经过精心设计、认真编写,具有较高可用性的分布式数据访问层,是一个吸收了 MySQL Proxy 、 Memcached 、集群等等思想而构建的软件系统。
一、关于 DAL 二、 DAL1.0 的产生 三、走近 DAL2 四、 DAL 带来了什么 五、未来计划 六、 Q&A 目 录
1) 老系统的问题 手机之家( www.imobile.com.cn )是一个有接近八年历史的网站,我们从 2008 年初开始重新设计和开发整个网站,我们在最初总结了一些之前遇到的经验和教训,其中包括: a) 由于 web server 可以直接访问 db server ,在高峰阶段,并发量比较大,导致 db server 经常 down 掉。 b) 添加缓存代码以降低数据库访问压力。但缓存访问逻辑却混杂在系统的各 个角落,造成代码维护成本上升。 c) 数据表结构设计不当,导致无法很简单地 ( 甚至不可能 ) 进行竖直和水平 方向的伸缩。
2) 纯 PHP 分层方案 1 HTTP MySQL Memcached 数据访问层 表现层 逻辑层 FastCGI MySQL Read Write
3) 方案 1 问题 方案 1 解决了之前所说的部分问题。但是: a) 开发一个功能,要写很多代码,而且有大部份代码是相当乏味的,重复性 极高,千篇一律,特别是数据访问层代码。 b) 程序员自己控制缓存。这使得: <1> 程序员根据自己的喜好来控制缓存的 KEY 和 VALUE ,造成缓存混乱。 <2> 程序员既要负责业务逻辑的编写,还要负责缓存管理,造成编程复 杂度提高、开发效率低下。 c) 在分表的情况下,程序员需要考虑和编写大量繁杂的和分表有关的代码。 这些问题,迫使我们寻找其它的解决方案。。。
4) 改进缓存 我们对数据库记录的缓存的访问做了一定的抽象处理,开发出了 Cache 处 理器。 所有的数据访问都经过 Cache 处理器。这样,系统代替程序员接管了缓存 的存取访问。缓存的 KEY 和 VALUE 由系统处理,从而避免了冲突和混乱。 Cache 处理器的引入减少了 40% 的数据访问层代码! 另外,为了让缓存能自动清理,我们采用了 Namespace 的思想。
5) 纯 PHP 分层方案 2 HTTP MySQL Memcached 表现层 逻辑层 FastCGI Read Write cache 处理器 数据访问层 cache 处理器 Namespace 处理器 PHP FastCGI + SQLite 实现
6) 方案 2 问题 但是问题又来了,此时,系统响应速度变得很慢。原因在于,我们 Namespace 是借助 PHP FastCGI 进程 +SQLite 来实现的。 这促使我们对采用纯 PHP 方案的可行性产生了质疑。。。
7)PHP+Java, 提升性能 Memcached 不支持 Namespace ,也不支持遍历。 所以,我们基于之前开发的 Monkey(Java NIO Framework) 实现了一个支 持 Namespace 和遍历功能的内存缓存程序。我们采用了简单高效的文本行 协议。
7)PHP+Java, 提升性能 ( 续 ) HTTP MySQL Memcached 表现层 逻辑层 FastCGI Read Write cache 处理器 数据访问层 cache 处理器 Java 内存 缓存服务 支持 Namespace 和遍历功能, 存储 Namespace
7)PHP+Java, 提升性能 ( 续 ) 改完后,系统的性能有了明显的提升。从原来的每个请求几十毫秒,降到 1.5 毫秒,甚至更少。
8)DA 引入, DAL1.0 产生 Cache 处理器在缓存的存取方面有了很大的进步,但是由于接口众多,使 用起来不太方便。特别是,对于分表,程序员仍然要花大量的精力去关心: a. 需要根据规则计算出数据的存取目标是在哪个分表当中。 b. 如果取回的数据分布在不同的分表中,需要合并结果。 c. 由于大表切分后变成了多个小的分表,对于有排序要求的查找,需要通过 建立并查找索引 ( 辅表 ) 来解决。 d. 如果一套分表有多个索引,需要寻找最优索引。 为此,我们重构了这部分代码,吸收了其它框架的优点,开发出了 Data Accessor( 简称 DA) 。
8)DA 引入, DAL1.0 产生 ( 续 ) HTTP MySQL Memcached 表现层 逻辑层 Read/Write DA Java 内存 缓存服务 存储 Namespace 、 Id List 、 聚合运算结果 存储单条记录
8)DA 引入, DAL1.0 产生 ( 续 ) 事实上, DA 和 Java 内存缓存服务 ( 指其中部分操作数据的逻辑 ) 就是后来 构想的 Data Access Layer 的雏形。 为此,我们把这些程序称为 DAL1.0 ,以此,作为我们数据访问层实践的里程 碑。
9)DAL1.0 问题 DA 标准化了调用接口,使程序员在业务逻辑层面尽量不再关心缓存与分表问 题,简化了编程,极大地提高了生产力 ( 代码量继续减少,易用性提高 ) 。 但是它仍然有很多不足: a.  表打散情况下,打散字段必须位于第一个查询条件中。 b.  另外, DA 直接和数据库打交道,在这一点上,可以说是又回到了起点。 c.  而且, DAL1.0 的 Java 内存缓存服务和 Memcached 在不同的进程,很多 情况下需要两次请求,才能组合出最终的数据。如果这两个在一个进程中, 显然能减少一次请求。
9)DAL1.0 问题 ( 续 ) d.  如果操作的数据分布在不同的分表中,为了提高性能,需要并行处理。但 是 PHP 不好做到。 e.  为了保证索引和分表数据的一致性,需要引入事务。但是 DAL1.0 没有。 f. DAL1.0 直接针对 MySQL 编码,万一手机之家将来需要采用其它的数据 库,怎么办? g.  在应用层对特殊字符进行转义以防止 SQL 注入,这为什么不在 DAL 里 面做呢? 以上种种问题,让我们有了开发 DAL2.x 的想法。
一、关于 DAL 二、 DAL1.0 的产生 三、走近 DAL2 四、 DAL 带来了什么 五、未来计划 六、 Q&A 目 录
1) 想象中的 DAL2.x MySQL DAL Server 其它 缓存服务 JDBC Oracle ??? JDBC JDBC Java DAL Client Memcached PHP DAL Client Python DAL Client ? DAL Client DALP DALP DALP DALP
2) 思考和总结  -  序 在开发 DAL1.0 的时候,我们对数据访问层做些什么且应该怎么做,已经有了一定认识,但还缺乏实际数据的验证。 在 DAL1.0 经过四个月的生产环境下的运行之后,很多东西渐渐变得明朗起来。 DAL1.0 表现良好,数据库的 QPS 从几千降到几百,缓存命中率一般在 70%~80% 之间。 这些迹象表明,这条路是走得通的。 现在需要的是要站得更高、看得更远、做得更好。所以,必须对之前的经验和教训做一个思考和总结,以此,作为 DAL2.x 设计和开发的出发点。
2) 思考和总结  -  关于水平切分 a. 最好分到同一个数据库。 b. 一种已经证明是切实可行的方案:主表+辅表。 c. 有 3 种类型:主表不打散、主表打散无辅表、主表打散有辅表。 d. 不管怎么打散,程序员看到的只是一张表,不妨称之为虚表 ( 逻辑表 )‏ ,这张虚表实际上可能是由 N 张实表 ( 物理表 ) 组成的。
2) 思考和总结  -  关于缓存 a. 慎用本地缓存。 一般情况下,像 Memcached 这种远程缓存已经够用了。 b. 选择或开发可根据字节数配置容量的缓存。 默认的缓存空间。 指定的缓存空间。 c.  缓存行记录。 缓存 Id List( 由 Id List 找行记录缓存 ) 和其它结果集。 两种缓存放在不同的缓存空间,便于自动清除。
2) 思考和总结  -  关于 JOIN 要慎用 JOIN 。避免 JOIN 的解决方案: a.  在应用层拼装成最终结果。 b.  采用汇总表。汇总表里放所有需要联合的数据表的所有数据。可以用最新表和历史表降低压力。 c.  采用 Lucene 。预先建立索引,然后在索引上进行检索。效率也还不错。
2) 思考和总结  -  关于 ORM a.  放弃主流 Java ORM 框架采用的 Java 实体类+ XML 配置的方式。 b.  采用直接面向数据库的开发方式。 DAL 自动从数据库获得需要的 信息。 XML 配置的只是分表的规则、连接池的使用、缓存的使用等。 只在应用层需要和数据库不一样的信息时 ( 如字段名 ) ,才在配置文 件里显式写出。 c.  接口采用 API Invocation+Call Chain 的方式,所有的方法名取自 SQL 关键字,方便记忆。 d.  客户端把返回的结构化数据转换成符合自己语言特点的的表达方式, 方便使用。
2) 思考和总结  -  指导方针 DAL2.x 总体上设计成 (Core + Plugins) 的形式。 Core 负责一些不可插件化 ( 或难以插件化 ) 的组件, Plugins 则是那些 可插化的组件。 我们定的是机制,提供的是策略;机制是软件目标和宗旨的体现,一般是不能轻易改变的,而策略则应当是能比较简单地进行切换的。 那么, Core 即机制, Plugins 即策略。
Oracle MySQL MySQL 分库 分库 索 引 库 MySQL DAL Server DAL Server DAL Server Cluster1  MySQL 分库 分库 DAL Client App Service Pool Data Access Layer DAL Server DAL Server DAL Server Cluster0 3)Big Picture - DAL2.x JDBC DALP JDBC JDBC JDBC DALP JDBC JDBC
3)Big Picture - DAL2.x Server Monkey NIO Framework query executor routing strategy query parser cache provider result merger cache MySQL conn provider config manager event listener dal handler Oracle client
3)Big Picture - DAL2.x Client Command Factory Insert Delete Update Select ... Command Sender
4)DAL2.x 用法示例  - PHP 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(3)‏ ->execute();
4)DAL2.x 用法示例  - PHP( 续 ) 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))‏ ->getAll();
5)DAL2.x 用法示例  - Java 1) 增 DalClient dalClient = new DalClient(&quot;127.0.0.1&quot;, 1965); Command cmd = Commands.insert() .table(&quot;imobile.soft.head_pic&quot;) .data({a:1, b:2}) .data({a:2, b:3}); ArrayNode an = dalClient.request(cmd); an.get(&quot;affectedRows&quot;);
5)DAL2.x 用法示例  - Java( 续 ) 2) 删 DalClient dalClient = new DalClient(&quot;127.0.0.1&quot;, 1965); Command cmd = Commands.delete() .table(&quot;imobile.soft.head_pic&quot;) .where(&quot;head_pic_id&quot;, &quot;<=&quot;, 4098210) .limit(4); dalClient.request(cmd).get(&quot;affectedRows&quot;);
5)DAL2.x 用法示例  - Java( 续 ) 3) 改 DalClient dalClient = new DalClient(&quot;127.0.0.1&quot;, 1965); Command cmd = Commands.update() .table(&quot;imobile.soft.head_pic&quot;) .data(“a=b+?”, 1) .where(&quot;head_pic_id&quot;, 4098210) .limit(1);  dalClient.request(cmd).get(&quot;affectedRows&quot;);
5)DAL2.x 用法示例  - Java( 续 ) 4) 查 DalClient dalClient = new DalClient(&quot;127.0.0.1&quot;, 1965); Command cmd = Commands.selectAll() .table(&quot;imobile.soft.head_pic&quot;) .columns(&quot;count(*)&quot;) .where(&quot;head_pic_id&quot;, &quot;<&quot;,4098210) .groupBy(&quot;site_id&quot;) .orderBy(&quot;soft_id&quot;) .limit(10);  dalClient.request(cmd).get(&quot;all&quot;);
6) 简单性能测试 : DAL2.x vs. DAL1.0 测试方法:每次涉及 1 个记录,循环 10000 次,每次涉及的记录都不相同。 DAL2.1.1 insert: 8.2153069972992s, 8.2881560325623s, 8.2909779548645s delete: 8.928288936615s, 8.4321990013123s, 8.039489030838s  update: 8.9594140052795s, 7.6687839031219s, 7.580326795578s select: 7.9645628929138s, 3.0665209293365s, 3.0304710865021s DAL1.0 insert: 42.473783969879s, 43.072340011597s, 42.900885105133s delete: 25.484493017197s, 25.382812976837s, 25.41899895668s update: 74.74593091011s, 74.557103872299s, 74.246424913406s select: 14.060505151749s, 9.7374119758606s, 6.5931770801544s
6) 简单性能测试 : DAL2.x vs. Memcached a.  测试方法:每次获取 1 个,循环 10000 次,每次获取的记录都不相同。 DAL2.1.1: 10.839928150177s( 全部不命中的情况 ) 3.0760769844055s 3.1021270751953s 3.0667681694031s Memcached1.4.2: 1.9119760990143s 1.8506801128387s 1.8564429283142s 1.8201019763947s
6) 简单性能测试 : DAL2.x vs. Memcached( 续 ) b.  测试方法:每次获取 1000 个,执行 1 次,所有的记录都不相同。 DAL2.1.1: 0.038145065307617s 0.039067983627319s 0.041125059127808s Memcached1.4.2: 0.026659965515137s 0.026319026947021s 0.02648401260376s
6) 简单性能测试 : DAL2.x vs. Memcached( 续 ) c.  测试方法:每次获取 10000 个,执行 1 次,所有的记录都不相同。 DAL2.1.1: 0.64966702461243s 0.55020594596863s 0.52798008918762s 0.57868385314941s Memcached1.4.2: 0.28920984268188s 0.28875994682312s 0.28748893737793s 0.27671718597412s
7) 简单性能测试结果及分析 a. DAL2.x vs. DAL1.0 结果及分析: 在增、删、改、查四类查询当中, DAL2.x 都比 DAL1.0 有了很大的提升。原因在于:减少了一次 socket 请求、采用了异步消息处理机制、引入连接池及优化了算法等等。 b. DAL2.x vs. Memcached1.4.2 结果及分析: 从时间消耗的数量级来看, DAL2.1.1 和 Memcached1.4.2 属于同一个级别; 从时间消耗的绝对值来看, DAL2.1.1 还是有一定的差距。 那么这 1/3~1/2 的时间消耗都花在哪了?主要是在协议解析及查询分析上。
8) 案例:手机之家部署和使用 DAL 情况 应用 消息 队列 服务 M3 搜索 索引服务 搜索 更新 客户端 MySQL 计划任务 消息 队列 事件 监听器 DAL2.x 调度器 回调应用程序 读取消息 推送消息 发送更新任务 读写数据 写消息 读写数据 每分钟调一次
8) 案例:手机之家部署和使用 DAL 情况 ( 续 ) MySQL0 MySQL1 MySQL2 MySQL3 Cluster0 Cluster1 Cluster2 Cluster3 DAL Client App Service Pool
8) 案例:手机之家部署和使用 DAL 情况 ( 续 ) 以下是自近期升级或 reload( 重载配置和元数据 ) 以来四组 DAL 缓存服务的命中率统计: a) [rowCacheHits] => 1999443615(96.53%) [rowCacheMisses] => 71820652(3.47%) b) [rowCacheHits] => 728834651(82.44%) [rowCacheMisses] => 155230407(17.56%) c) [rowCacheHits] => 717269426(93.35%) [rowCacheMisses] => 51101159(6.65%) d) [rowCacheHits] => 217927450(74.06%) [rowCacheMisses] => 76326220(25.94%) 其中, b 组服务命中率低的原因是:上面跑的是论坛,全动态的,更新频繁; d 组服务命中率低的原因是:应用层又做了缓存了,到 DAL 的冷请求变多了。
8) 案例:手机之家部署和使用 DAL 情况 ( 续 ) 四组 DAL 缓存服务的垃圾回收情况: a) 5.2G 430610.121: [GC 430610.121: [ParNew: 970596K->44174K(990336K), 0.0256880 secs] 4481307K->3554885K(5184640K), 0.0258610 secs] [Times: user=0.19 sys=0.00, real=0.03 secs] 430620.486: [GC 430620.487: [ParNew: 976270K->48820K(990336K), 0.0262000 secs] 4486981K->3559531K(5184640K), 0.0263790 secs] [Times: user=0.19 sys=0.00, real=0.03 secs] 430634.904: [GC 430634.904: [ParNew: 980916K->50728K(990336K), 0.0299380 secs] 4491627K->3562274K(5184640K), 0.0301230 secs] [Times: user=0.21 sys=0.00, real=0.03 secs] a 组 GC 时间一般在 0.03s 左右。远远小于 0.2s ,符合预期。 b) 12G 416275.295: [GC 416275.295: [ParNew: 990336K->48297K(990336K), 0.0973960 secs] 10629874K->9712340K(12524672K), 0.0974940 secs] [Times: user=0.54 sys=0.02, real=0.09 secs] 416300.211: [GC 416300.211: [ParNew: 980393K->58240K(990336K), 0.1081660 secs] 10644436K->9750993K(12524672K), 0.1082560 secs] [Times: user=0.57 sys=0.02, real=0.11 secs] 416323.653: [GC 416323.653: [ParNew: 990336K->58240K(990336K), 0.1131280 secs] 10683089K->9781286K(12524672K), 0.1132320 secs] [Times: user=0.63 sys=0.02, real=0.11 secs] b 组 GC 时间一般在 0.1s 左右。小于 0.2s ,符合预期。
8) 案例:手机之家部署和使用 DAL 情况 ( 续 ) c) 3.7G 430107.117: [GC 430107.117: [ParNew: 488106K->27846K(495168K), 0.0482880 secs] 3289951K->2832064K(3640896K), 0.0485100 secs] [Times: user=0.15 sys=0.00, real=0.05 secs] 430124.541: [GC 430124.541: [ParNew: 493894K->19566K(495168K), 0.0484850 secs] 3298112K->2827443K(3640896K), 0.0487180 secs] [Times: user=0.15 sys=0.00, real=0.05 secs] 430140.861: [GC 430140.862: [ParNew: 485614K->22204K(495168K), 0.0491390 secs] 3293491K->2832961K(3640896K), 0.0493860 secs] [Times: user=0.16 sys=0.00, real=0.05 secs] c 组 GC 时间一般在 0.04s 左右。远小于 0.2s ,符合预期。 d) 6.2G 346635.015: [GC 346635.015: [ParNew: 985396K->51289K(990336K), 0.0575730 secs] 5606751K->4682230K(6377232K), 0.0577020 secs] [Times: user=0.32 sys=0.01, real=0.06 secs] 346684.600: [GC 346684.600: [ParNew: 983385K->58240K(990336K), 0.0652490 secs] 5614326K->4701406K(6377232K), 0.0653740 secs] [Times: user=0.35 sys=0.02, real=0.06 secs] 346737.473: [GC 346737.473: [ParNew: 990336K->42276K(990336K), 0.0550940 secs] 5633502K->4694264K(6377232K), 0.0552260 secs] [Times: user=0.31 sys=0.01, real=0.05 secs] d 组 GC 时间一般在 0.06s 左右。远小于 0.2s ,符合预期。
9) 案例分析 a.  DAL2.x 的缓存命中率相比 DAL1.0 有了很大的提高。原因在于 DAL2.x 在并发处理方面略胜一筹。 b. JVM 的 GC 问题,往往为人所诟病。但从我们在生产环境下的实际运行结果来看, GC 对 DAL 来说并不是问题。我们有理由相信, JDK7 发布后, GC 对应用程序的影响将会变得更小。
一、关于 DAL 二、 DAL1.0 的产生 三、走近 DAL2 四、 DAL 带来了什么 五、未来计划 六、 Q&A 目 录
DAL 带来了什么 a. DAL 极大地提高了开发效率。 b. DAL 极大地提高了程序的可维护性。 c. DAL 极大地提高了系统的响应速度。 d. DAL 极大地提高了系统的承载能力。 e. DAL 极大地提高了架构的应变能力。
一、关于 DAL 二、 DAL1.0 的产生 三、走近 DAL2 四、 DAL 带来了什么 五、未来计划 六、 Q&A 目 录
DAL2.x 未来计划 a.  继续完善功能、提升性能 ; b.  支持更多的数据库,如 PostgreSQL, DB2 等 ; c.  提供更多的客户端,如 Python, Ruby 等 ; d.  和 Spring 、 Guice 集成 ; e. 数据库厂商中立的数据复制 ; f.  更多的协议开发,这样才能作为透明代理使用 ; g.  嵌入式 API; ...
一、关于 DAL 二、 DAL1.0 的产生 三、走近 DAL2 四、 DAL 带来了什么 五、未来计划 六、 Q&A 目 录
手机之家 :  http://www.imobile.com.cn/ DAL TEAM:  高春辉 , 刘增禄 , 张庆城 , 何顺 , 许超前 , ___( 此位置空缺中 , 谁来填补 ?!) 我的博客 :  http://www.longker.org/ 我的 Gtalk :  [email_address] 我的 MSN : chaoranxu@hotmail.com
The End Thanks

More Related Content

What's hot

数据库性能诊断的七种武器
数据库性能诊断的七种武器数据库性能诊断的七种武器
数据库性能诊断的七种武器Leyi (Kamus) Zhang
 
20130626联动优势数据访问层DAL架构和实践5(刘胜)数据分片和分页
20130626联动优势数据访问层DAL架构和实践5(刘胜)数据分片和分页20130626联动优势数据访问层DAL架构和实践5(刘胜)数据分片和分页
20130626联动优势数据访问层DAL架构和实践5(刘胜)数据分片和分页liu sheng
 
Csdn Emag(Oracle)第二期
Csdn Emag(Oracle)第二期Csdn Emag(Oracle)第二期
Csdn Emag(Oracle)第二期yiditushe
 
HDFS與MapReduce架構研討
HDFS與MapReduce架構研討HDFS與MapReduce架構研討
HDFS與MapReduce架構研討Billy Yang
 
我对后端优化的一点想法
我对后端优化的一点想法我对后端优化的一点想法
我对后端优化的一点想法mysqlops
 
【Maclean liu技术分享】深入理解oracle中mutex的内部原理
【Maclean liu技术分享】深入理解oracle中mutex的内部原理【Maclean liu技术分享】深入理解oracle中mutex的内部原理
【Maclean liu技术分享】深入理解oracle中mutex的内部原理maclean liu
 
A.oracle 查询结果的缓存问题
A.oracle 查询结果的缓存问题A.oracle 查询结果的缓存问题
A.oracle 查询结果的缓存问题WASecurity
 
Mahout資料分析基礎入門
Mahout資料分析基礎入門Mahout資料分析基礎入門
Mahout資料分析基礎入門Jhang Raymond
 
百度分布式数据实践与进展
百度分布式数据实践与进展百度分布式数据实践与进展
百度分布式数据实践与进展yp_fangdong
 
浅谈 My sql 性能调优
浅谈 My sql 性能调优浅谈 My sql 性能调优
浅谈 My sql 性能调优thinkinlamp
 
Jdbc4 0 规范技术预研
Jdbc4 0 规范技术预研Jdbc4 0 规范技术预研
Jdbc4 0 规范技术预研lorisjand
 
低功耗服务器定制与绿色计算
低功耗服务器定制与绿色计算低功耗服务器定制与绿色计算
低功耗服务器定制与绿色计算Wensong Zhang
 
Times Ten Training
Times Ten TrainingTimes Ten Training
Times Ten TrainingLi Chen
 
【Ask maclean技术分享】oracle dba技能列表 z
【Ask maclean技术分享】oracle dba技能列表 z【Ask maclean技术分享】oracle dba技能列表 z
【Ask maclean技术分享】oracle dba技能列表 zmaclean liu
 
Apache Zookeeper 分布式服务框架
Apache Zookeeper 分布式服务框架Apache Zookeeper 分布式服务框架
Apache Zookeeper 分布式服务框架Cabin WJ
 
Practical Data Analysis in R
Practical Data Analysis in RPractical Data Analysis in R
Practical Data Analysis in RChun-Ming Chang
 
Voldemort Intro Tangfl
Voldemort Intro TangflVoldemort Intro Tangfl
Voldemort Intro Tangflfulin tang
 

What's hot (19)

数据库性能诊断的七种武器
数据库性能诊断的七种武器数据库性能诊断的七种武器
数据库性能诊断的七种武器
 
20130626联动优势数据访问层DAL架构和实践5(刘胜)数据分片和分页
20130626联动优势数据访问层DAL架构和实践5(刘胜)数据分片和分页20130626联动优势数据访问层DAL架构和实践5(刘胜)数据分片和分页
20130626联动优势数据访问层DAL架构和实践5(刘胜)数据分片和分页
 
Csdn Emag(Oracle)第二期
Csdn Emag(Oracle)第二期Csdn Emag(Oracle)第二期
Csdn Emag(Oracle)第二期
 
HDFS與MapReduce架構研討
HDFS與MapReduce架構研討HDFS與MapReduce架構研討
HDFS與MapReduce架構研討
 
我对后端优化的一点想法
我对后端优化的一点想法我对后端优化的一点想法
我对后端优化的一点想法
 
【Maclean liu技术分享】深入理解oracle中mutex的内部原理
【Maclean liu技术分享】深入理解oracle中mutex的内部原理【Maclean liu技术分享】深入理解oracle中mutex的内部原理
【Maclean liu技术分享】深入理解oracle中mutex的内部原理
 
A.oracle 查询结果的缓存问题
A.oracle 查询结果的缓存问题A.oracle 查询结果的缓存问题
A.oracle 查询结果的缓存问题
 
Mahout資料分析基礎入門
Mahout資料分析基礎入門Mahout資料分析基礎入門
Mahout資料分析基礎入門
 
百度分布式数据实践与进展
百度分布式数据实践与进展百度分布式数据实践与进展
百度分布式数据实践与进展
 
Oracle 索引介紹
Oracle 索引介紹Oracle 索引介紹
Oracle 索引介紹
 
Oracle 資料庫建立
Oracle 資料庫建立Oracle 資料庫建立
Oracle 資料庫建立
 
浅谈 My sql 性能调优
浅谈 My sql 性能调优浅谈 My sql 性能调优
浅谈 My sql 性能调优
 
Jdbc4 0 规范技术预研
Jdbc4 0 规范技术预研Jdbc4 0 规范技术预研
Jdbc4 0 规范技术预研
 
低功耗服务器定制与绿色计算
低功耗服务器定制与绿色计算低功耗服务器定制与绿色计算
低功耗服务器定制与绿色计算
 
Times Ten Training
Times Ten TrainingTimes Ten Training
Times Ten Training
 
【Ask maclean技术分享】oracle dba技能列表 z
【Ask maclean技术分享】oracle dba技能列表 z【Ask maclean技术分享】oracle dba技能列表 z
【Ask maclean技术分享】oracle dba技能列表 z
 
Apache Zookeeper 分布式服务框架
Apache Zookeeper 分布式服务框架Apache Zookeeper 分布式服务框架
Apache Zookeeper 分布式服务框架
 
Practical Data Analysis in R
Practical Data Analysis in RPractical Data Analysis in R
Practical Data Analysis in R
 
Voldemort Intro Tangfl
Voldemort Intro TangflVoldemort Intro Tangfl
Voldemort Intro Tangfl
 

Similar to 手机之家的数据访问层实践

手机之家新系统介绍及架构分享
手机之家新系统介绍及架构分享手机之家新系统介绍及架构分享
手机之家新系统介绍及架构分享Dahui Feng
 
imobile-beta技术沙龙
imobile-beta技术沙龙imobile-beta技术沙龙
imobile-beta技术沙龙posestudio
 
Hadoop Map Reduce 程式設計
Hadoop Map Reduce 程式設計Hadoop Map Reduce 程式設計
Hadoop Map Reduce 程式設計Wei-Yu Chen
 
Ria的强力后盾:rest+海量存储
Ria的强力后盾:rest+海量存储 Ria的强力后盾:rest+海量存储
Ria的强力后盾:rest+海量存储 zhen chen
 
deep inside Sina App Engine cloud service
deep inside Sina App Engine cloud servicedeep inside Sina App Engine cloud service
deep inside Sina App Engine cloud servicecong lei
 
Taobao数据库这5年
Taobao数据库这5年Taobao数据库这5年
Taobao数据库这5年yp_fangdong
 
Mysql handlersocket
Mysql handlersocketMysql handlersocket
Mysql handlersocketpwesh
 
20120613联动优势数据访问层DAL架构和实践4(刘胜)最新特性
20120613联动优势数据访问层DAL架构和实践4(刘胜)最新特性20120613联动优势数据访问层DAL架构和实践4(刘胜)最新特性
20120613联动优势数据访问层DAL架构和实践4(刘胜)最新特性liu sheng
 
丁原:海量数据迁移方案
丁原:海量数据迁移方案丁原:海量数据迁移方案
丁原:海量数据迁移方案YANGL *
 
构建基于Lamp的网站架构
构建基于Lamp的网站架构构建基于Lamp的网站架构
构建基于Lamp的网站架构Cosey Lee
 
Terracotta And Continuent Based Clustering Architecture
Terracotta And Continuent Based Clustering ArchitectureTerracotta And Continuent Based Clustering Architecture
Terracotta And Continuent Based Clustering ArchitectureTarget Source
 
Beyond rails server
Beyond rails serverBeyond rails server
Beyond rails serverMichael Chen
 
20141128(刘胜)UTC2014分布式和云服务的思考与实践——支付清算行业分布式架构的探索
20141128(刘胜)UTC2014分布式和云服务的思考与实践——支付清算行业分布式架构的探索20141128(刘胜)UTC2014分布式和云服务的思考与实践——支付清算行业分布式架构的探索
20141128(刘胜)UTC2014分布式和云服务的思考与实践——支付清算行业分布式架构的探索liu sheng
 
Web Caching Architecture and Design
Web Caching Architecture and DesignWeb Caching Architecture and Design
Web Caching Architecture and DesignHo Kim
 
王龙:百度数据库架构演变与设计
王龙:百度数据库架构演变与设计王龙:百度数据库架构演变与设计
王龙:百度数据库架构演变与设计YANGL *
 

Similar to 手机之家的数据访问层实践 (20)

手机之家新系统介绍及架构分享
手机之家新系统介绍及架构分享手机之家新系统介绍及架构分享
手机之家新系统介绍及架构分享
 
imobile-beta技术沙龙
imobile-beta技术沙龙imobile-beta技术沙龙
imobile-beta技术沙龙
 
Hadoop Map Reduce 程式設計
Hadoop Map Reduce 程式設計Hadoop Map Reduce 程式設計
Hadoop Map Reduce 程式設計
 
Ria的强力后盾:rest+海量存储
Ria的强力后盾:rest+海量存储 Ria的强力后盾:rest+海量存储
Ria的强力后盾:rest+海量存储
 
Hic2011
Hic2011Hic2011
Hic2011
 
deep inside Sina App Engine cloud service
deep inside Sina App Engine cloud servicedeep inside Sina App Engine cloud service
deep inside Sina App Engine cloud service
 
Sae
SaeSae
Sae
 
Taobao数据库这5年
Taobao数据库这5年Taobao数据库这5年
Taobao数据库这5年
 
Mysql handlersocket
Mysql handlersocketMysql handlersocket
Mysql handlersocket
 
20120613联动优势数据访问层DAL架构和实践4(刘胜)最新特性
20120613联动优势数据访问层DAL架构和实践4(刘胜)最新特性20120613联动优势数据访问层DAL架构和实践4(刘胜)最新特性
20120613联动优势数据访问层DAL架构和实践4(刘胜)最新特性
 
丁原:海量数据迁移方案
丁原:海量数据迁移方案丁原:海量数据迁移方案
丁原:海量数据迁移方案
 
Hadoop 介紹 20141024
Hadoop 介紹 20141024Hadoop 介紹 20141024
Hadoop 介紹 20141024
 
构建基于Lamp的网站架构
构建基于Lamp的网站架构构建基于Lamp的网站架构
构建基于Lamp的网站架构
 
Terracotta And Continuent Based Clustering Architecture
Terracotta And Continuent Based Clustering ArchitectureTerracotta And Continuent Based Clustering Architecture
Terracotta And Continuent Based Clustering Architecture
 
Beyond rails server
Beyond rails serverBeyond rails server
Beyond rails server
 
20141128(刘胜)UTC2014分布式和云服务的思考与实践——支付清算行业分布式架构的探索
20141128(刘胜)UTC2014分布式和云服务的思考与实践——支付清算行业分布式架构的探索20141128(刘胜)UTC2014分布式和云服务的思考与实践——支付清算行业分布式架构的探索
20141128(刘胜)UTC2014分布式和云服务的思考与实践——支付清算行业分布式架构的探索
 
Cdc@ganji.com
Cdc@ganji.comCdc@ganji.com
Cdc@ganji.com
 
老舊web上雲端
老舊web上雲端老舊web上雲端
老舊web上雲端
 
Web Caching Architecture and Design
Web Caching Architecture and DesignWeb Caching Architecture and Design
Web Caching Architecture and Design
 
王龙:百度数据库架构演变与设计
王龙:百度数据库架构演变与设计王龙:百度数据库架构演变与设计
王龙:百度数据库架构演变与设计
 

手机之家的数据访问层实践

  • 1. 手机之家的数据访问层实践 许超前 @ 手机之家 2009 年 10 月 24 日
  • 2. 一、关于 DAL 二、 DAL1.0 的产生 三、走近 DAL2 四、 DAL 带来了什么 五、未来计划 六、 Q&A 目 录
  • 3. 1) 数据访问层 引用维基百科 : A Data Access Layer (DAL) is a layer of a computer program which provides simplified access to data stored in persistent storage of some kind, such as an entity-relational database. This data access layer is used in turn by other program modules to access and manipulate the data within the data store without having to deal with the complexities inherent in this access.
  • 4. 1) 数据访问层 ( 续 ) 应用程序 Data Access Layer DB API 文件 DAL 在系统中的位置
  • 5. 2) 手机之家数据访问层 DAL1.0 和 DAL2.x 是手机之家开发的数据访问层的产品名的代号。下文如无特殊说明 DAL 代表此产品的通称。 DAL 是手机之家研发团队近几年在开发和运营上的经验的总结以及智慧的结晶。 开发 DAL 的目的是为了解决在构建大中型网站时遇到的和数据访问有关的诸多问题,如怎样使得分表透明化,怎样使得缓存存取清除自动化,怎样才能更好地防止服务单点故障等等。 DAL1.0 是一个具有里程碑意义的版本,但在很多方面仍然欠考虑。 DAL2.x 是一个经过精心设计、认真编写,具有较高可用性的分布式数据访问层,是一个吸收了 MySQL Proxy 、 Memcached 、集群等等思想而构建的软件系统。
  • 6. 一、关于 DAL 二、 DAL1.0 的产生 三、走近 DAL2 四、 DAL 带来了什么 五、未来计划 六、 Q&A 目 录
  • 7. 1) 老系统的问题 手机之家( www.imobile.com.cn )是一个有接近八年历史的网站,我们从 2008 年初开始重新设计和开发整个网站,我们在最初总结了一些之前遇到的经验和教训,其中包括: a) 由于 web server 可以直接访问 db server ,在高峰阶段,并发量比较大,导致 db server 经常 down 掉。 b) 添加缓存代码以降低数据库访问压力。但缓存访问逻辑却混杂在系统的各 个角落,造成代码维护成本上升。 c) 数据表结构设计不当,导致无法很简单地 ( 甚至不可能 ) 进行竖直和水平 方向的伸缩。
  • 8. 2) 纯 PHP 分层方案 1 HTTP MySQL Memcached 数据访问层 表现层 逻辑层 FastCGI MySQL Read Write
  • 9. 3) 方案 1 问题 方案 1 解决了之前所说的部分问题。但是: a) 开发一个功能,要写很多代码,而且有大部份代码是相当乏味的,重复性 极高,千篇一律,特别是数据访问层代码。 b) 程序员自己控制缓存。这使得: <1> 程序员根据自己的喜好来控制缓存的 KEY 和 VALUE ,造成缓存混乱。 <2> 程序员既要负责业务逻辑的编写,还要负责缓存管理,造成编程复 杂度提高、开发效率低下。 c) 在分表的情况下,程序员需要考虑和编写大量繁杂的和分表有关的代码。 这些问题,迫使我们寻找其它的解决方案。。。
  • 10. 4) 改进缓存 我们对数据库记录的缓存的访问做了一定的抽象处理,开发出了 Cache 处 理器。 所有的数据访问都经过 Cache 处理器。这样,系统代替程序员接管了缓存 的存取访问。缓存的 KEY 和 VALUE 由系统处理,从而避免了冲突和混乱。 Cache 处理器的引入减少了 40% 的数据访问层代码! 另外,为了让缓存能自动清理,我们采用了 Namespace 的思想。
  • 11. 5) 纯 PHP 分层方案 2 HTTP MySQL Memcached 表现层 逻辑层 FastCGI Read Write cache 处理器 数据访问层 cache 处理器 Namespace 处理器 PHP FastCGI + SQLite 实现
  • 12. 6) 方案 2 问题 但是问题又来了,此时,系统响应速度变得很慢。原因在于,我们 Namespace 是借助 PHP FastCGI 进程 +SQLite 来实现的。 这促使我们对采用纯 PHP 方案的可行性产生了质疑。。。
  • 13. 7)PHP+Java, 提升性能 Memcached 不支持 Namespace ,也不支持遍历。 所以,我们基于之前开发的 Monkey(Java NIO Framework) 实现了一个支 持 Namespace 和遍历功能的内存缓存程序。我们采用了简单高效的文本行 协议。
  • 14. 7)PHP+Java, 提升性能 ( 续 ) HTTP MySQL Memcached 表现层 逻辑层 FastCGI Read Write cache 处理器 数据访问层 cache 处理器 Java 内存 缓存服务 支持 Namespace 和遍历功能, 存储 Namespace
  • 15. 7)PHP+Java, 提升性能 ( 续 ) 改完后,系统的性能有了明显的提升。从原来的每个请求几十毫秒,降到 1.5 毫秒,甚至更少。
  • 16. 8)DA 引入, DAL1.0 产生 Cache 处理器在缓存的存取方面有了很大的进步,但是由于接口众多,使 用起来不太方便。特别是,对于分表,程序员仍然要花大量的精力去关心: a. 需要根据规则计算出数据的存取目标是在哪个分表当中。 b. 如果取回的数据分布在不同的分表中,需要合并结果。 c. 由于大表切分后变成了多个小的分表,对于有排序要求的查找,需要通过 建立并查找索引 ( 辅表 ) 来解决。 d. 如果一套分表有多个索引,需要寻找最优索引。 为此,我们重构了这部分代码,吸收了其它框架的优点,开发出了 Data Accessor( 简称 DA) 。
  • 17. 8)DA 引入, DAL1.0 产生 ( 续 ) HTTP MySQL Memcached 表现层 逻辑层 Read/Write DA Java 内存 缓存服务 存储 Namespace 、 Id List 、 聚合运算结果 存储单条记录
  • 18. 8)DA 引入, DAL1.0 产生 ( 续 ) 事实上, DA 和 Java 内存缓存服务 ( 指其中部分操作数据的逻辑 ) 就是后来 构想的 Data Access Layer 的雏形。 为此,我们把这些程序称为 DAL1.0 ,以此,作为我们数据访问层实践的里程 碑。
  • 19. 9)DAL1.0 问题 DA 标准化了调用接口,使程序员在业务逻辑层面尽量不再关心缓存与分表问 题,简化了编程,极大地提高了生产力 ( 代码量继续减少,易用性提高 ) 。 但是它仍然有很多不足: a. 表打散情况下,打散字段必须位于第一个查询条件中。 b. 另外, DA 直接和数据库打交道,在这一点上,可以说是又回到了起点。 c. 而且, DAL1.0 的 Java 内存缓存服务和 Memcached 在不同的进程,很多 情况下需要两次请求,才能组合出最终的数据。如果这两个在一个进程中, 显然能减少一次请求。
  • 20. 9)DAL1.0 问题 ( 续 ) d. 如果操作的数据分布在不同的分表中,为了提高性能,需要并行处理。但 是 PHP 不好做到。 e. 为了保证索引和分表数据的一致性,需要引入事务。但是 DAL1.0 没有。 f. DAL1.0 直接针对 MySQL 编码,万一手机之家将来需要采用其它的数据 库,怎么办? g. 在应用层对特殊字符进行转义以防止 SQL 注入,这为什么不在 DAL 里 面做呢? 以上种种问题,让我们有了开发 DAL2.x 的想法。
  • 21. 一、关于 DAL 二、 DAL1.0 的产生 三、走近 DAL2 四、 DAL 带来了什么 五、未来计划 六、 Q&A 目 录
  • 22. 1) 想象中的 DAL2.x MySQL DAL Server 其它 缓存服务 JDBC Oracle ??? JDBC JDBC Java DAL Client Memcached PHP DAL Client Python DAL Client ? DAL Client DALP DALP DALP DALP
  • 23. 2) 思考和总结 - 序 在开发 DAL1.0 的时候,我们对数据访问层做些什么且应该怎么做,已经有了一定认识,但还缺乏实际数据的验证。 在 DAL1.0 经过四个月的生产环境下的运行之后,很多东西渐渐变得明朗起来。 DAL1.0 表现良好,数据库的 QPS 从几千降到几百,缓存命中率一般在 70%~80% 之间。 这些迹象表明,这条路是走得通的。 现在需要的是要站得更高、看得更远、做得更好。所以,必须对之前的经验和教训做一个思考和总结,以此,作为 DAL2.x 设计和开发的出发点。
  • 24. 2) 思考和总结 - 关于水平切分 a. 最好分到同一个数据库。 b. 一种已经证明是切实可行的方案:主表+辅表。 c. 有 3 种类型:主表不打散、主表打散无辅表、主表打散有辅表。 d. 不管怎么打散,程序员看到的只是一张表,不妨称之为虚表 ( 逻辑表 )‏ ,这张虚表实际上可能是由 N 张实表 ( 物理表 ) 组成的。
  • 25. 2) 思考和总结 - 关于缓存 a. 慎用本地缓存。 一般情况下,像 Memcached 这种远程缓存已经够用了。 b. 选择或开发可根据字节数配置容量的缓存。 默认的缓存空间。 指定的缓存空间。 c. 缓存行记录。 缓存 Id List( 由 Id List 找行记录缓存 ) 和其它结果集。 两种缓存放在不同的缓存空间,便于自动清除。
  • 26. 2) 思考和总结 - 关于 JOIN 要慎用 JOIN 。避免 JOIN 的解决方案: a. 在应用层拼装成最终结果。 b. 采用汇总表。汇总表里放所有需要联合的数据表的所有数据。可以用最新表和历史表降低压力。 c. 采用 Lucene 。预先建立索引,然后在索引上进行检索。效率也还不错。
  • 27. 2) 思考和总结 - 关于 ORM a. 放弃主流 Java ORM 框架采用的 Java 实体类+ XML 配置的方式。 b. 采用直接面向数据库的开发方式。 DAL 自动从数据库获得需要的 信息。 XML 配置的只是分表的规则、连接池的使用、缓存的使用等。 只在应用层需要和数据库不一样的信息时 ( 如字段名 ) ,才在配置文 件里显式写出。 c. 接口采用 API Invocation+Call Chain 的方式,所有的方法名取自 SQL 关键字,方便记忆。 d. 客户端把返回的结构化数据转换成符合自己语言特点的的表达方式, 方便使用。
  • 28. 2) 思考和总结 - 指导方针 DAL2.x 总体上设计成 (Core + Plugins) 的形式。 Core 负责一些不可插件化 ( 或难以插件化 ) 的组件, Plugins 则是那些 可插化的组件。 我们定的是机制,提供的是策略;机制是软件目标和宗旨的体现,一般是不能轻易改变的,而策略则应当是能比较简单地进行切换的。 那么, Core 即机制, Plugins 即策略。
  • 29. Oracle MySQL MySQL 分库 分库 索 引 库 MySQL DAL Server DAL Server DAL Server Cluster1 MySQL 分库 分库 DAL Client App Service Pool Data Access Layer DAL Server DAL Server DAL Server Cluster0 3)Big Picture - DAL2.x JDBC DALP JDBC JDBC JDBC DALP JDBC JDBC
  • 30. 3)Big Picture - DAL2.x Server Monkey NIO Framework query executor routing strategy query parser cache provider result merger cache MySQL conn provider config manager event listener dal handler Oracle client
  • 31. 3)Big Picture - DAL2.x Client Command Factory Insert Delete Update Select ... Command Sender
  • 32. 4)DAL2.x 用法示例 - PHP 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(3)‏ ->execute();
  • 33. 4)DAL2.x 用法示例 - PHP( 续 ) 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))‏ ->getAll();
  • 34. 5)DAL2.x 用法示例 - Java 1) 增 DalClient dalClient = new DalClient(&quot;127.0.0.1&quot;, 1965); Command cmd = Commands.insert() .table(&quot;imobile.soft.head_pic&quot;) .data({a:1, b:2}) .data({a:2, b:3}); ArrayNode an = dalClient.request(cmd); an.get(&quot;affectedRows&quot;);
  • 35. 5)DAL2.x 用法示例 - Java( 续 ) 2) 删 DalClient dalClient = new DalClient(&quot;127.0.0.1&quot;, 1965); Command cmd = Commands.delete() .table(&quot;imobile.soft.head_pic&quot;) .where(&quot;head_pic_id&quot;, &quot;<=&quot;, 4098210) .limit(4); dalClient.request(cmd).get(&quot;affectedRows&quot;);
  • 36. 5)DAL2.x 用法示例 - Java( 续 ) 3) 改 DalClient dalClient = new DalClient(&quot;127.0.0.1&quot;, 1965); Command cmd = Commands.update() .table(&quot;imobile.soft.head_pic&quot;) .data(“a=b+?”, 1) .where(&quot;head_pic_id&quot;, 4098210) .limit(1); dalClient.request(cmd).get(&quot;affectedRows&quot;);
  • 37. 5)DAL2.x 用法示例 - Java( 续 ) 4) 查 DalClient dalClient = new DalClient(&quot;127.0.0.1&quot;, 1965); Command cmd = Commands.selectAll() .table(&quot;imobile.soft.head_pic&quot;) .columns(&quot;count(*)&quot;) .where(&quot;head_pic_id&quot;, &quot;<&quot;,4098210) .groupBy(&quot;site_id&quot;) .orderBy(&quot;soft_id&quot;) .limit(10); dalClient.request(cmd).get(&quot;all&quot;);
  • 38. 6) 简单性能测试 : DAL2.x vs. DAL1.0 测试方法:每次涉及 1 个记录,循环 10000 次,每次涉及的记录都不相同。 DAL2.1.1 insert: 8.2153069972992s, 8.2881560325623s, 8.2909779548645s delete: 8.928288936615s, 8.4321990013123s, 8.039489030838s update: 8.9594140052795s, 7.6687839031219s, 7.580326795578s select: 7.9645628929138s, 3.0665209293365s, 3.0304710865021s DAL1.0 insert: 42.473783969879s, 43.072340011597s, 42.900885105133s delete: 25.484493017197s, 25.382812976837s, 25.41899895668s update: 74.74593091011s, 74.557103872299s, 74.246424913406s select: 14.060505151749s, 9.7374119758606s, 6.5931770801544s
  • 39. 6) 简单性能测试 : DAL2.x vs. Memcached a. 测试方法:每次获取 1 个,循环 10000 次,每次获取的记录都不相同。 DAL2.1.1: 10.839928150177s( 全部不命中的情况 ) 3.0760769844055s 3.1021270751953s 3.0667681694031s Memcached1.4.2: 1.9119760990143s 1.8506801128387s 1.8564429283142s 1.8201019763947s
  • 40. 6) 简单性能测试 : DAL2.x vs. Memcached( 续 ) b. 测试方法:每次获取 1000 个,执行 1 次,所有的记录都不相同。 DAL2.1.1: 0.038145065307617s 0.039067983627319s 0.041125059127808s Memcached1.4.2: 0.026659965515137s 0.026319026947021s 0.02648401260376s
  • 41. 6) 简单性能测试 : DAL2.x vs. Memcached( 续 ) c. 测试方法:每次获取 10000 个,执行 1 次,所有的记录都不相同。 DAL2.1.1: 0.64966702461243s 0.55020594596863s 0.52798008918762s 0.57868385314941s Memcached1.4.2: 0.28920984268188s 0.28875994682312s 0.28748893737793s 0.27671718597412s
  • 42. 7) 简单性能测试结果及分析 a. DAL2.x vs. DAL1.0 结果及分析: 在增、删、改、查四类查询当中, DAL2.x 都比 DAL1.0 有了很大的提升。原因在于:减少了一次 socket 请求、采用了异步消息处理机制、引入连接池及优化了算法等等。 b. DAL2.x vs. Memcached1.4.2 结果及分析: 从时间消耗的数量级来看, DAL2.1.1 和 Memcached1.4.2 属于同一个级别; 从时间消耗的绝对值来看, DAL2.1.1 还是有一定的差距。 那么这 1/3~1/2 的时间消耗都花在哪了?主要是在协议解析及查询分析上。
  • 43. 8) 案例:手机之家部署和使用 DAL 情况 应用 消息 队列 服务 M3 搜索 索引服务 搜索 更新 客户端 MySQL 计划任务 消息 队列 事件 监听器 DAL2.x 调度器 回调应用程序 读取消息 推送消息 发送更新任务 读写数据 写消息 读写数据 每分钟调一次
  • 44. 8) 案例:手机之家部署和使用 DAL 情况 ( 续 ) MySQL0 MySQL1 MySQL2 MySQL3 Cluster0 Cluster1 Cluster2 Cluster3 DAL Client App Service Pool
  • 45. 8) 案例:手机之家部署和使用 DAL 情况 ( 续 ) 以下是自近期升级或 reload( 重载配置和元数据 ) 以来四组 DAL 缓存服务的命中率统计: a) [rowCacheHits] => 1999443615(96.53%) [rowCacheMisses] => 71820652(3.47%) b) [rowCacheHits] => 728834651(82.44%) [rowCacheMisses] => 155230407(17.56%) c) [rowCacheHits] => 717269426(93.35%) [rowCacheMisses] => 51101159(6.65%) d) [rowCacheHits] => 217927450(74.06%) [rowCacheMisses] => 76326220(25.94%) 其中, b 组服务命中率低的原因是:上面跑的是论坛,全动态的,更新频繁; d 组服务命中率低的原因是:应用层又做了缓存了,到 DAL 的冷请求变多了。
  • 46. 8) 案例:手机之家部署和使用 DAL 情况 ( 续 ) 四组 DAL 缓存服务的垃圾回收情况: a) 5.2G 430610.121: [GC 430610.121: [ParNew: 970596K->44174K(990336K), 0.0256880 secs] 4481307K->3554885K(5184640K), 0.0258610 secs] [Times: user=0.19 sys=0.00, real=0.03 secs] 430620.486: [GC 430620.487: [ParNew: 976270K->48820K(990336K), 0.0262000 secs] 4486981K->3559531K(5184640K), 0.0263790 secs] [Times: user=0.19 sys=0.00, real=0.03 secs] 430634.904: [GC 430634.904: [ParNew: 980916K->50728K(990336K), 0.0299380 secs] 4491627K->3562274K(5184640K), 0.0301230 secs] [Times: user=0.21 sys=0.00, real=0.03 secs] a 组 GC 时间一般在 0.03s 左右。远远小于 0.2s ,符合预期。 b) 12G 416275.295: [GC 416275.295: [ParNew: 990336K->48297K(990336K), 0.0973960 secs] 10629874K->9712340K(12524672K), 0.0974940 secs] [Times: user=0.54 sys=0.02, real=0.09 secs] 416300.211: [GC 416300.211: [ParNew: 980393K->58240K(990336K), 0.1081660 secs] 10644436K->9750993K(12524672K), 0.1082560 secs] [Times: user=0.57 sys=0.02, real=0.11 secs] 416323.653: [GC 416323.653: [ParNew: 990336K->58240K(990336K), 0.1131280 secs] 10683089K->9781286K(12524672K), 0.1132320 secs] [Times: user=0.63 sys=0.02, real=0.11 secs] b 组 GC 时间一般在 0.1s 左右。小于 0.2s ,符合预期。
  • 47. 8) 案例:手机之家部署和使用 DAL 情况 ( 续 ) c) 3.7G 430107.117: [GC 430107.117: [ParNew: 488106K->27846K(495168K), 0.0482880 secs] 3289951K->2832064K(3640896K), 0.0485100 secs] [Times: user=0.15 sys=0.00, real=0.05 secs] 430124.541: [GC 430124.541: [ParNew: 493894K->19566K(495168K), 0.0484850 secs] 3298112K->2827443K(3640896K), 0.0487180 secs] [Times: user=0.15 sys=0.00, real=0.05 secs] 430140.861: [GC 430140.862: [ParNew: 485614K->22204K(495168K), 0.0491390 secs] 3293491K->2832961K(3640896K), 0.0493860 secs] [Times: user=0.16 sys=0.00, real=0.05 secs] c 组 GC 时间一般在 0.04s 左右。远小于 0.2s ,符合预期。 d) 6.2G 346635.015: [GC 346635.015: [ParNew: 985396K->51289K(990336K), 0.0575730 secs] 5606751K->4682230K(6377232K), 0.0577020 secs] [Times: user=0.32 sys=0.01, real=0.06 secs] 346684.600: [GC 346684.600: [ParNew: 983385K->58240K(990336K), 0.0652490 secs] 5614326K->4701406K(6377232K), 0.0653740 secs] [Times: user=0.35 sys=0.02, real=0.06 secs] 346737.473: [GC 346737.473: [ParNew: 990336K->42276K(990336K), 0.0550940 secs] 5633502K->4694264K(6377232K), 0.0552260 secs] [Times: user=0.31 sys=0.01, real=0.05 secs] d 组 GC 时间一般在 0.06s 左右。远小于 0.2s ,符合预期。
  • 48. 9) 案例分析 a. DAL2.x 的缓存命中率相比 DAL1.0 有了很大的提高。原因在于 DAL2.x 在并发处理方面略胜一筹。 b. JVM 的 GC 问题,往往为人所诟病。但从我们在生产环境下的实际运行结果来看, GC 对 DAL 来说并不是问题。我们有理由相信, JDK7 发布后, GC 对应用程序的影响将会变得更小。
  • 49. 一、关于 DAL 二、 DAL1.0 的产生 三、走近 DAL2 四、 DAL 带来了什么 五、未来计划 六、 Q&A 目 录
  • 50. DAL 带来了什么 a. DAL 极大地提高了开发效率。 b. DAL 极大地提高了程序的可维护性。 c. DAL 极大地提高了系统的响应速度。 d. DAL 极大地提高了系统的承载能力。 e. DAL 极大地提高了架构的应变能力。
  • 51. 一、关于 DAL 二、 DAL1.0 的产生 三、走近 DAL2 四、 DAL 带来了什么 五、未来计划 六、 Q&A 目 录
  • 52. DAL2.x 未来计划 a. 继续完善功能、提升性能 ; b. 支持更多的数据库,如 PostgreSQL, DB2 等 ; c. 提供更多的客户端,如 Python, Ruby 等 ; d. 和 Spring 、 Guice 集成 ; e. 数据库厂商中立的数据复制 ; f. 更多的协议开发,这样才能作为透明代理使用 ; g. 嵌入式 API; ...
  • 53. 一、关于 DAL 二、 DAL1.0 的产生 三、走近 DAL2 四、 DAL 带来了什么 五、未来计划 六、 Q&A 目 录
  • 54. 手机之家 : http://www.imobile.com.cn/ DAL TEAM: 高春辉 , 刘增禄 , 张庆城 , 何顺 , 许超前 , ___( 此位置空缺中 , 谁来填补 ?!) 我的博客 : http://www.longker.org/ 我的 Gtalk : [email_address] 我的 MSN : chaoranxu@hotmail.com