20120613联动优势数据访问层DAL架构和实践4(刘胜)最新特性

3,004 views

Published on

说明:
和已有DAL软件(如许超前手机之家DAL、陈思儒Amoeba/贺贤懋Cobar等)不一样,在前端访问方式的选择上,抛弃JDBC方式,而是为同一个dalet数据服务,同时提供自定义TCP长连接和HTTP长连接两种接口。
因而通过抛弃JDBC可以获得多方面的好处——
1)可减少S端协议解析和查询分析的开销;
2)也简化C端编程。
3)后端存储就不再限于RDB了,而可以是任意NOSQL、文件、缓存、甚至是Tuxedo等在线服务。
4)可以实现无状态了,更容易横向扩展。
5)从接口上就可消除join等关键字的误用,避免引起服务端负担过重。

Published in: Design
2 Comments
29 Likes
Statistics
Notes
No Downloads
Views
Total views
3,004
On SlideShare
0
From Embeds
0
Number of Embeds
2
Actions
Shares
0
Downloads
0
Comments
2
Likes
29
Embeds 0
No embeds

No notes for slide

20120613联动优势数据访问层DAL架构和实践4(刘胜)最新特性

  1. 1. 数据访问层DAL架构和实践(4)新的特性 Version-4.20120613 刘胜liusheng@umpay.com 联动优势B办公区 北京市西城区安德路甲104号证通商务楼F6层(100120)
  2. 2. 2 *版本历史  V1.20091123 基本概念,设计目标,关键技术,参考实现  V1.20091124 关键技术:编程语言,序列化,结果集  V1.20091125 关键技术:客户端接口,负载均衡,权衡  V1.20091203 关键技术:结果集序列化(测试比较)  V1.20091208 服务端存储方式,客户端访问接口,编程语言  V1.20091208 HA-JDBC,负载均衡  V1.20091209 +分布式存储引擎  V1.20091222 调整:概念/理念/方案/参考/实践  V1.20091222 +TCSQL,DbCached  V1.20091224 +客户端代码(PHP)。调整结构,去掉参考部分。  V1.20091224 【数据访问层DAL概念和实践1(刘胜)】  考:架构经验(淘宝,eBay)  V2.20100112 +参考:DB2复制,Tungsten Replicator  V2.20100114 *DAL设计目标,DB分片  V2.20100301 【(刘胜)NoSQL数据库知识图.mm】  V2.20100325 删除部分内容,突出DAL实现方面。  V2.20100330 【数据访问层DAL概念和实践2(刘胜).ppt】  V2.20100408 *中间层编程语言,TODO, CAP原则和NoSQL系统  V3.20100419 +概念:CAP原则和NoSQL分类;  V3.20100419 *概念:What and Why?;*设计0:DAL初步路线图*设计4 :服务的组织风格/传输协议  V3.20100419 *思考:初步架构设想2;*思考:淘宝经验(Session和CAP 优先)  V3.20100421 *实践:配置;客户端代码(+local);+读写分离;+预编 译;  V3.20100423 +参考MysqlProxy,BeansDB  V3.20100423 【数据访问层DAL架构和实践3(刘胜).ppt 】  V3.20100510 *实践:配置:vrdb/ds特定参数,DalServer/jmx等。。 。其他问题。  V3.20100510 +容错:Byzantine将军问题,BFT容错协议  V3.20100526 +实践:客户端(生成PO,自动注入)  专利:一种面向资源的分布式数据访问服务装置-专利交底 书-UMPay刘胜-v1.1批注.doc  专利:一种面向资源的分布式数据访问服务装置-专利申请 书-UMPay刘胜-v3.1(TD1007146F)-请发明人审核.doc  专利:一种面向资源的分布式数据访问服务装置-专利申请 书-UMPay刘胜-v3.7(TD1007146F)-LX-9.21.doc  -----------  V3.20100719 +版本持续改进  V3.20100806 +JMX管理功能,+性能测试和功能测试,*SOA 组织风格,+ROA和REST实践,+数据集分页技术  V3.20100816 +访问MemCached,*软件架构主题,。  V3.20110105 *设计4:DAL中间层编程语言  V3.20110301 +实践:新的认证方式  V3.20110617 +概念:NoSQL分类(按实现机制)  -----------  V4.20120301 +新特性:依赖注入,SQL注入、  V4.20120301 +新特性:日志时间分离、连接数控制  V4.20120613 【数据访问层DAL架构和实践4(刘胜)】  V4.20120613 +思考题,新特性  -----------
  3. 3. 3 *概念:软件架构主题  2009年软件架构主题!  架构模式:3&4层New  服务架构:SOA WOA  存储方式:RDB NoSQL  编程语言:编译型动态语言  应用类型:普通社会化  处理方式:集中式P2P  架构方式:封闭架构开放服务链  2010年软件架构主题?  架构模式:云计算五层架构  The Hardware Layer  The Virtualization Layer  The IaaS Layer  The PaaS Layer  The SaaS Layer  服务架构:ROA  存储方式:NOSQL 【一家之言】 NoSQL Non-Relational DB NOSQL Not-Only RDB
  4. 4. 4 *概念:什么是DAL  概念:数据访问层DAL 【Layer=Services】  【维基百科】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.  DAL是一系列服务的集合,是DAO在大型系统中的自然延伸,是SOA的具体实现。  好处:  简化客户端接口,规范数据操作【透明性分片】  保持客户端接口,动态升级服务端实现【SOA】  支持对巨量数据的访问【缓存;读写分离;分片(分库/分表)】  服务的治理【认证/管理/权限/监控/分析/优化/…】  功能需求:  访问代理【Proxy】  读写分离【RAIDb-1镜像,每个库都是全库。写库是单点】  数据分片【RAIDb-0分区,每个库都是子库。】  高可用性【支持Quorum-NWR模型——多个写库】  特性需求:  平台中立【DAL服务器,可部署在多种平台上】  语言中立【DAL客户端,支持Java、C/C++、PHP、Flex等多种语言。】  数据库中立【1)多种数据库类型;2)多个数据库版本?】  资源共享【1) 共享DataSource连接池; 2)共享Cache。】  访问日志【1)提供SqlLog可用于性能瓶颈分析;2)提供BackLog可用于数据恢复。】  访问控制【1)用户认证;2)连接管理;3)权限控制。】  读写分离【FullDB】  数据分片【分表,分库】  访问集群【负载均衡:HA-Proxy、JGroup】
  5. 5. 5 +概念:大型网站架构演变 数据中心:也是一 种服务,未必使用 DB,也可能是文件 ,内存。 DAL:数据访问层 服务,隔离特定的 数据库,屏蔽分库 ,分区,分片。 大型网站架构演变: 第一步:物理分离WebServer和数据库 第二步:增加页面缓存 第三步:增加页面片段缓存 第四步:数据缓存 第五步:增加webserver 第六步:分库 • 根据应用逻辑、用户ID 、时间来切分 • 数据库分区(Partition) • 数据库分片(Sharding) 第七步:分表、DAL、分布式缓存 第八步:增加更多的webserver 第九步:数据读写分离和廉价存储方案 第十步:大型分布式应用、廉价服务器群 • 分布式文件系统:GFS、HadoopDFS • 分布式存储:BigTable • 分布式计算:MapReduce、Hadoop 参考: http://www.blogjava.net/BlueDavy/archive/2008/09 /03/226749.html 大型网站架构演变和知识体系
  6. 6. 6 DAL 代理? +规划:大型数据库架构规划  数据存储规划  根据事务与否:  是:RDBMS集中存储  否:NOSQL分布存储  根据应用分库:  根据数据分片:  横向拆分:根据ID拆分用户表  纵向拆分:根据时间拆分交易表  根据读写类型:读写分离  根据业务类型:  OLTP——行式数据库(在线库)  OLAP——列式数据库(历史库)  高可用性数据存储架构(适用不同场景)  Share-Storage主备架构:存储是单点  Share-Nothing主从架构:写库是单点  Share-Nothing主主架构:写库非单点  Share-Nothing双主多从:读写可分离  关键技术组件:  数据访问层DAL  协议:CM20长连接/HTTP连接  前端:异步处理,支持大并发  后端:同步调用,无需访问外部  框架:Dalet  数据复制工具(推vs 拉)  单DB2到单DB2(结构完全一致)  单DB2到单DB2(结构不完全一致)  单DB2到多DB2(部署多套即可)  单DB2到多MySQL(异构库)  单DB2到多NoSQL(异构库)
  7. 7. 7 负载层 CDN 区域负载 (可选) F5/LVS +Nginx/ Haproxy Web前置集群综合前置FSL 异 步 订阅 同 步 服务层缓存层持久层 综合前置 FSL SMS,Email,IM,… 通知和反馈 Memcached + Membase 二级缓存 应用切分 水平切分 垂直切分 读写分离 双主多从 F5/LVS +Nginx/ Haproxy 主备机制 JMS Camel 通过DAL访问 NOSQL DB Hadoop / HBase … NameNode2 复制 Master DB (行式)在线交易库 Master / Slave,分片,集群 DataNodes 同NameNode1 步 异 步 页面缓存 Squid Varnish OSCache 静态资源 合作机构 银行 移动 商户 分布式服务集群 应用服务:ASL 基础服务:BSL 数据访问:DAL 监控服务定时服务:TSL 集群 +规划:总体技术规划系统视图 … 读 (列式)离线分析库 写 读… 复 制 Slave DB
  8. 8. 8 *设计:DAL演化路线图  第一阶段目标:访问代理  平台中立【DAL服务端,基于Java开发,可部署在多个平台上】  语言中立【DAL客户端,支持多种语言访问(JAVA/PHP/FLEX/…)】  厂商中立【支持多个数据库厂商;支持多个数据库版本?支持非RDB存储?】  第二阶段目标:服务治理  资源共享【共享连接池;共享缓存(Memcached/EhCached)】  权限控制【身份认证,连接管理,访问控制】  访问日志【SqlLog或BackLog】  监控优化【性能瓶颈分析和优化】  第三阶段目标:读写分离  读写分离【主从结构,需要额外的DB复制技术】  访问集群【负载均衡】  第四阶段目标:数据分片【针对RDB实现数据切分】  数据库分区(Partition)集中式/不能垮DB/Scale-Up/单点【厂商相关,不推荐】  数据库分片(ShardingP)分布式/垮多个DB/Scale-Out/无单点【厂商中立】  分库【虚拟库,不同表存在不同的实际库中】  分表【虚拟表,将同一库中多张小表虚拟成一个大表】  例:select * from db.A.1, db.A.2, db.A.3 where …  分库+分表【虚拟表,将不同库中多张小表虚拟成一个大表】  例:select * from db1.A,db2.A,db3.A where …  第五阶段目标:非结构化存储【针对NoSQL(RO/CO/KV/DO)的访问】  实现:三备份/NWR/多版本/… 【无需额外的DB复制,使用NWR模型】
  9. 9. 9 +背景:已有的中间层技术方案  方案1:Mysql-Proxy@MySQL官方  不支持分库分表,且性能较差。  方案2:Atlas@Qihoo360(王超)  基于mysql-proxy-0.8.2版  方案3:Amoeba@盛大(陈思儒)  for {MySQL | Aladdin | MongoDB}  不支持事务/存储过程/分库分表/输出大结果集。  方案4:Cobar@AliBaBa(贺贤懋)  基于amoeba-0.34版  开源版只支持MySQL,不支持读写分离。  方案5:TDDL@Taobao  复杂度相对较高,文档较少。  只开源动态数据源,不开源分库分表。  方案6:S3@Amazon  基于标准REST和SOAP接口的超级SAN存储
  10. 10. 10 设计0:DAL关键技术  关键技术的权衡和选择  1,SOA组织风格: 【ROA和REST】  2,中间层编程语言: 【Java vs C/C++】  3,后端存储方式: 【NO-RDB】  4,前端访问接口: 【NO-JDBC,NO-SQL】  No-JDBC  抛弃复杂的jdbc,服务端更容易解析  抛弃复杂的jdbc,客户端更容易使用  No-SQL 【用sqlid/callid替代sql语句】  抛弃复杂的sql语句,解析更容易,执行更安全。  5,协议(传输协议+数据协议)  数据传输协议【HTTP/TEXT/UM32/UM16/CM16/CM20】  序列化技术【xml/json/phprpc/amf3/java+gz/hessian2+gz】  结果集表示【List<Map<String,Object>>】  6,负载均衡: 【避免单点】  监控管理:  1.监控用户触发请求的成功率  2.监控随着数据量增长,单个请求的响应时间  3.监控分布式系统的单点线程并发数  4.监控分布式系统的点与点之间的报文请求成功率 NO=Not Only
  11. 11. 11 *设计1:SOA组织风格  三种SOA的组织风格  WOA【SOAP/XML-RPC/RSS/…】  广义:Web Oriented Architecture  狭义:WebService Oriented Architecture  ROA【RESTful HTTP/RSS/ATOM】  广义:Resource Oriented Architecture  狭义:RESTful-HTTP Oriented Architecture  REST:REpresentational State Transfer  MOA【ESB】  广义:Message Oriented Architecture  其他:Mobile Oriented Architecture  其他:Microsoft Oriented Architecture  几种SOA的组织风格的比较 组织风格WOA ROA/REST MOA/ESB 核心概念(面向动词)远程过程调用(面向名词)远程资源访问(副词)消息传输 标准新标准(SOAP/WSDL/WS-*) 现有标准(HTTP/XML/RSS) N/A 问题域覆盖全部的应用场景覆盖大部分应用场景N/A 内容协商不支持支持N/A
  12. 12. 12 *设计1:ROA和REST实践  REST设计准则:  将所有事物抽象为资源,分别对应唯一(不变的)URI; 【类似TDD,针对URI来设计】  将所有资源链接在一起; 【如,表示层HTML链接】  使用标准方法(HTTP)操作资源;  资源有多重表述形式; 【=》内容格式协商:1)根据HTTP头Accept信息;2)根据URI后缀】  强制采用无状态通信方式(stateless)。【参考: 大用户量的Session保持问题(淘宝) 】  RESTful API  Select doList() 【GET /rest2/resource】  Insert doCreate() 【POST /rest2/resource】  Select doSelect() 【GET /rest2/resource/id.xml】  Update doUpdate() 【PUT /rest2/resource/id.xml】  Delete doDelete() 【DELETE /rest2/resource/id.xml】  其他实现:  Restlet/Axis2/Cetia4/sqlREST/REST-art/JRest4Guice/GlassFish-Jersey(基于JAX-RS/JSR- 311)  BS3实现:Rest1【仅支持Servlet容器】  com.bs3.ext.rest.Servlet4Rest 【Servlet容器】  BS3实现:Rest2【仅支持HTTP协议:Servlet容器,或BS3/Mina2】  com.bs3.ext.rest2.RestletEngine4Servlet 【Servlet容器】  com.bs3.ext.rest2.RestletEngine4Mina2 【BS3框架】  BS3实现:Rest3/Dalet【支持多协议多服务:CM20/HTTP/…】  com.bs3.app.dal.engine.DalEngine2Restlet 【BS3框架】
  13. 13. 13 *设计2:DAL前端访问接口  你真的需要JDBC吗?  有状态的JDBC? 【ResultSet保持连接】  复杂的交互方式? 【Connection、Statement、ResultSet,事务】  你真的需要SQL吗?  SQL 【关系数据库,标准查询语言】  SQL/JOIN 【JOIN对性能影响很大】  其他选择  HQL 【Hibernate Query Language】  JDOQL 【JDO Query Language】  RESTful-DB 【CUID=Create Update Insert Delete】  NoSQL-DB 【=> 概念:CAP原则和NoSQL分类】  Dynamo@amazon,BigTable@google,Hypertable@baidu,Cassandra@facebook,Voldemort@linkedin, PNuts@yahoo,TokyoCabinet,Dynomite,Redis,MongoDB,CouchDB/erlang,HBase,Riak,Tin,Flare, Lightcloud/python,KiokuDB,Scalaris,Kai,ThruDB,......  自定义数据服务层——从DAO到DAL(Data Access Layer=Services)  抛弃复杂的JDBC接口=》Map请求+Object响应【语言中立,服务端易解析,客户端易使用】  抛弃完整的SQL功能=》采用:SQLID+参数【限制访问权限,解析更容易,执行更安全】  参考:  http://robbin.javaeye.com/blog/524977 NoSQL数据库探讨之一  http://journal.uggedal.com/nosql-east-2009---summary-of-day-1  http://www.oschina.net/p/mongodb 分布式文档存储数据库MongoDB/json(非RDB中功能最丰富)  http://www.blogjava.net/xjtuwz/archive/2009/12/20/306711.html NoSQL & MongoDB  http://www.oschina.net/p/couchdb 面向文档的数据库CouchDB/ErLang  http://www.oschina.net/p/monetdb 内存数据库MonetDB  http://www.oschina.net/p/hypertable 一个BitTable的开源实现  http://blog.evanweaver.com/articles/2009/07/06/up-and-running-with-cassandra/ 介绍Cassandra  http://hi.baidu.com/beibeiboo/blog/item/5418ff35533b061b91ef3908.html 分布式存储引擎Dynamo
  14. 14. 14 *设计3:DAL后端存储方式  你真的需要RDB吗?  RDB的核心功能?  1,存储【替代——数据中心:RDB,CO,DO,KVS,BFS】  2,事务【替代——?——(无可替代)】  存储模型:  Relational DB(Row-Oriented) 【有模式:适于OLTP的行式数据库,即关系型数据库】  *Column-Oriented DB 【有模式:适于OLAP的列式数据库】 (对比)  Doucument-Oriented DB 【无模式(Schema-Free)】  *Key-Value-Store 【小数据:BDB/Memcachedb/Tokyo Cabinet/…】  *Big-File-Stroe 【大数据:GFS,Hadoop】  存储介质:  Five-Minute Rule for I/O 【Disk is Tape;Flash is Disk;RAM Locality is King. --Jim Gray 2006】  Web2.0时代  新需求:RDB无法满足的需求  High Performance 【对数据库高并发读写】  Huge Storage 【对海量数据的高效存储和访问】  High Scalability & High Availability 【高可扩展性和高可用性】  旧需求:非必须的RDB特性  数据库事务一致性需求;  数据库的写实时性和读实时性需求;  对复杂的SQL查询,特别是多表关联查询的需求  两种弱一致性理论:1)BASE理论;2)Brewer’的CAP理论(一致性,可用性,分布冗余)  参考  http://www.julianbrowne.com/article/viewer/brewers-cap-theorem  http://robbin.javaeye.com/blog/524977 NoSQL数据库探讨之一  http://www.dbanotes.net/arch/five-minute_rule.html 关于I/O 的五分钟法则(Five-Minute Rule)  http://www.dbanotes.net/techmemo/ssd_trend.html SSD 趋势小窥 RDB和CO的对比 ? 数据库重构更容易!
  15. 15. 15 +概念:NoSQL数据库知识图
  16. 16. 16 +概念:NoSQL分类(按CAP原则)  CAP原则  Availability:Each client can always read and write.  Consistency:All clients always have the same view of the data  Partition Tolerance:The System works well despite physical network partitions.  Data Models  (RO) Relational (comparison) 【适于OLTP】  (CO) Column-Oriented 【适于OLAP】  (KV) Key-Value  (DO) Doucument-Oriented  (GO)Graph-Oriented 【适于SNS】  NoSql实例的分类:  C-A System:  (RO) RDBMs,Aster Data,Greenplum  (CO) Vertica  A-P System:  (KV) Dynamo,Voldemort,Tokyo Cabinet,KAI  (CO) Cassandra,  (DO) SimpleDB,CouchDB,Riak  C-P System:  (CO) BigTable,Hypertable,HBase/Hadoop  (DO) MongoDB,Terrastore  (KV) Scalaris,BerkeleyDB,MemcacheDB,Redis  C-A-P System:  (RO) C-JDBC/Sequoia  参考:  http://www.javabloger.com/article/about-mongodb-pdf-ppt.html mongodb入门介绍  http://nosql-database.org/ 官方网站 Availability (可用性) Consistency (一致性) Partition tolerance (分布式) C+A Pick Two ! C+A+P
  17. 17. 17 +概念:NoSQL分类(按实现机制)  1.key-value存储:Tokyo Cabinet/Tyrant, Redis, Voldemort, Oracle BDB  应用场景:内容缓存,主要用于处理大量数据的高访问负载,也用于一些日志系统。  数据模型:Key指向Value的键值对,通常用HashTable来实现。  强项:查找速度快。  弱项:数据无结构,通常只被当作字符串或者二进制数据。  2.列式数据库: Cassandra, HBase, Riak  应用场景:分布式的文件系统。  数据模型:以列簇式存储,将同一列数据存在一起。  强项:读性能强;每列都是索引,查找速度快;可扩展性强,更容易进行分布式扩展。  弱项:写性能差,功能相对局限。  3.文档型数据库:CouchDB, MongoDb  应用场景:Web应用(与K-V类似,但Value是半结构化的,数据库了解Value的内容)  数据模型:Key-Value对应的键值对,Value为半结构化数据  强项:数据结构要求不严格,表结构可变,无需要像RDB一样需要预先定义表结构。  弱项:查询性能不高,而且缺乏统一的查询语法。  4.图结构数据库:Neo4J, InfoGrid, Infinite Graph  应用场景:社交网络,推荐系统等。专注于构建关系图谱  数据模型:图结构  强项:利用图结构相关算法。比如最短路径寻址,N度关系查找等  弱项:经常要对整个图做计算才能得出所需信息,该结构不太好做分布式的集群方案。  参考:http://blog.nosqlfan.com/html/1727.html 如何选择最适合你的NoSQL数据库
  18. 18. 18 *设计4:DAL中间层编程语言  背景:  Linux2.6引入NPTL,支持内核级多线程 ,Java应用服务器的网络处理性能提升 了5倍【Robbin范凯】  Linux下Java6通过libevent库,和 memcached性能相当【许超前】  在Linux2.6中Java6的Selector采用 epoll机制实现【Alan Bateman】  Djava.nio.channels.spi.SelectorProvid er=sun.nio.ch.EPollSelectorProvider  结论:【Java6】  网络延迟:(10..100)ms  并发连接:~100K  吞吐量:~30K request/s  参考:  http://timyang.net/programming/c-erlang- java-performance/ 关于 C,Erlang,Java和Go的性能测试【注:已更新 ,用Netty替代Mina进行比较,后者实现了更 多的协议栈。】  http://www.javaeye.com/topic/13042 讨论(robbin)  http://blogs.sun.com/alanb/entry/epoll
  19. 19. 19 *设计5:数据传输协议  可用协议  文本协议HTTP 【效率较差】=》HTML5/WebSocket  文本协议TEXT 【扩展性差(rn结尾)】  二进制协议:UM16/UM32 【PHP等语言访问不便】  半文本协议:CM20 【语言中立】《=memcached协议(文本|二进制)  自定义协议  VER 4 【=CM20】  FMT 4  请求:= XMAP,PROP,JAVA,H1SP(=hessian),H2SP(=hessian2),BURP(=burlap)  响应:= JAVA,J2GZ  响应:= XS2X,XS2J, BURP,H1SP,H1GZ,H2SP,H2GZ  响应:= GSON,JACK,AMF3,PHPC,  EC 2 【Cipher加密={00|D1|D3|A2}+CBC+Pkcs7Padding】  CS 2 【Charset字符集={GB|U1|U2|B5}】  LEN 8 【报文总长度,文本格式,最大约99M】  BODY ? 【任意数据,长度=(LEN-20)】
  20. 20. 20 设计5:序列化方式(比较)  要求:【小,快,多语言】,  实践:【MyStream.java】  XStream2Xml,XStream2Json,Jackson,TStreamAdaptor, JavaRpc,JavaRpcZip,JavaRpcGz,PhpRpc,AMF3,Hessian, Hessian2,HessianGz,Hessian2Gz,Burlap,JavaDeflater  结论:  初步比较  xstream/xml使用不同driver时: xpp<xppdom<stax<dom<jdom  xstream/json比xstream/xml更慢!  phprpc和hprose/AMF3不能处理复杂对象!  其他比较:  Avro@Apache 【Hadoop】  Thrift@Apache 【Facebook】  ProtoBuf@Google 【需要编译】  Caucho:Hessian1/Hessian2和Burlap  json@Jackson 【格式中立】  gson@Google 【格式中立】  bson@mongodb 【C,PHP,Python,Ruby】  AMF3@Adobe 【小而慢】  Java/Serializable与Externalizable  压缩技术:Zip,GZip,Deflater  参考:  http://code.google.com/p/thrift-protobuf-compare/ wiki/Benchmarking 几种序列化机制的性能比较  http://labs.chinamobile.com/mblog/225_30690 大数据 的数据格式Avro  20091102关于RPC和序列化技术 Total Time = Creating an Object + Serializing + Deserializing
  21. 21. 21 设计5:结果集RowSet  RowSet和ResultSet比较  ResultSet  只能向前滚动和只读的。都是有连接的。  RowSet  都是可滚动的和可更新的。非连接(可离线操作)。  RowSet接口说明  JdbcRowSet  唯一保持连接的RowSet。  CachedRowSet  离线增删改查,串行化,支持事件监听,分页等。  WebRowSet  可以序列化/反序列化到XML文件中。  FilteredRowSet  可通过设置Predicate可提供数据筛选和过滤。  JoinRowSet  提供类似SQLJOIN的功能(目前只支持InnerJoin)  参考:  http://www.ibm.com/developerworks/cn/java/j-lo-java6rowset/ index.html Java 6 RowSet 使用完全剖析  http://tech.it168.com/jd/2008-07- 04/200807040958443.shtml RowSet简单入门
  22. 22. 22 设计5:结果集序列化(比较)  示例代码:  DataSource ds = new DbArgs("root", "mysql", "jdbc:mysql://localhost/paydb").injectDsAlias("c3p0");  CachedRowSet crs = MyDB.doQuery4RowSet(ds, sql);  List<Bean> rlist = MyDB.doQuery4List(ds, sql, Bean.class, -1);//call:MyUtil.inject2bean()…  List<?> rlist = MyDB.doQuery4List(ds, sql, -1, null);//null = new RowMapper2Map0()  执行效率:【select name,passwd,regTime from tusers,返回7条记录】  doQuery4RowSet() 耗时29698(us)=44,48,1344,27640,81,64,477 【很慢】  doQuery4List(Bean) 耗时17662(us)=35,29,674,16712,35,30,147 【较慢】  doQuery4List(Map) 耗时2326(us)=19,22,617,1463,38,26,141 【推荐】 效率比较 (Unit=usec) doQuery4RowSet doQuery4List(Map) 大小序列化时间反序列化时间大小序列化时间反序列化时间 XStream2/xml 9749C 27841 34752 2101C 1271 1973 XStream2/json 4791C 208816 14863 915C 2462 2774 Jackson/json 失败394C 143833 15806 PhpRpc/bin 7328B 19022 13190 643B 1769 672 JavaRpc/bin 6037B 21676 5240 734B 1938 920 Hessian/bin 7389B 42236 14769 656B 518 842 Hessian2/bin 3363B 6393 9438 374B 345 345 Hessian2/gzip 1484B 1654 2884 168B 469 244 AMF3/bin 失败223B 26100 22509 【结论】XStream2/json和Jaskson有时反序列化失败。而PhpRpc只处理java基本类型,AMF3使用ASObject类型 。【建议】采用List<Map<?,?>>保存数据,使用JavaRpc或Hessian2+gz来序列化。
  23. 23. 23 设计6:负载均衡  负载均衡:LVS > HA-Proxy > Nginx  内核级静态分发:LVS 【三种模式:NAT,TUN,DR】  应用级静态分发:Nginx 【HTTP层,简单加权轮询】  应用级智能分发:HA-Proxy 【HTTP+TCP层,后端探测,Cookie插入】  参考:  http://hi.baidu.com/zeorliu/blog/item/239eb601eefda20c1c95836c.html
  24. 24. 24 *设计6:逻辑架构(设想) WebApp +restlet2 +servlet 服务 BS3框架 +restlet2 +dalet 服务 Nginx Nginx LVS 基 础 服 务 层 B S L 资 源 服 务 分布式存储 memcached mongodb hbase、gfs DB2 MySQL Nginx分发机制 1,根据path负载均衡 2,根据http头 3,根据path分发 其他服务 +jsp +asp +php 中间件或服务 Tuxedo CICS ESB 三种LVS实现方式 1,IPVS-NAT 2,IPVS-TUN 3,IPVS-DR 应 用 服 务 层 A S L 调 度 服 务 同步 HA Proxy 同步/异步 HA Proxy dalet 同步 负载均衡层LBL 应用服务层ASL 基础服务层BSL 复 制 dalet dalet LBL
  25. 25. 25 +专利,应用场景 1 应用逻辑层2 数据访问层DAL Java应用 Php应用 Ruby应用 协议1/序列化1 协议1/序列化2 协议2/序列化3 Asp应用协议2/序列化4 2 数据访问服务 21 NIO 网络 协议 适配 器 22 数 据 服 务 引 擎 23 数 据 服 务 容 器 3 数据资源层 JDBC RDB1 API …… Method + URI 2 数据访问服务 xxxx应用21 22 23 Dalet 一种面向资源的分布式数据访问服务装置 31 RDB集群 RDB2 RDB3 不同厂商: db2/mysql/ … RDB4 不同功用: 读库/写库 在线/离线 32内存数据库集群 33文档数据库集群 34缓存集群 35文件系统 2 数据访问服务
  26. 26. 26 +专利,DAL的层次 1 应用逻辑层2 数据访问层DAL Java应用 Ruby应用 Asp应用 2 数据访问服务 21 NIO 网络 协议 适配 器 22 数 据 服 务 引 擎 23 数 据 服 务 容 器 3 数据资源层 JDBC RDB1 API …… 2 数据访问服务 xxxx应用21 22 23 Dalet 一种面向资源的分布式数据访问服务装置 31 RDB集群 RDB2 RDB3 不同厂商: db2/mysql/ … RDB4 不同功用: 读库/写库 在线/离线 32内存数据库集群 33文档数据库集群 34缓存集群 35文件系统 2 数据访问服务 IF1 Method+URI DAL相关 IF1 Php应用
  27. 27. 27 +专利,系统架构图 1 应用逻辑层2 数据访问层(DAL) 1 应用系统(DAL) 2 数据访问服务(1) 21 NIO网络 协议适配器 22 Dalet引 擎 211 消息头 解析器 212 消息体 解析器 221 资源 分发器 222 操作 映射器 23 Dalet容器 ● Dalet1 ● Dalet2 … http 11表现层 12逻辑层 13持久层 Method+URI 1应用系统(DAO) 11表现层 12逻辑层 13持久层 http 3 数据资源层 2 数据访问服务(2) RDB1 RDB2 Cache File IF2 21 22 23 IF1 IF3 DAO
  28. 28. 28 +专利,部署架构(云) CM20/JSON LB 2 数据访问 服务 ●Dalet1 ●Dalet2 … 数据访问层 DB2 MySQL 分布式 内存缓存 Memcached 分布式 文件系统 GFS LB HTTP/XML 负载均衡层数据资源层 应用逻辑层 JDBC API … 2 数据访问 服务 ●Dalet1 ●Dalet2 … 2 2
  29. 29. 29 -实践:服务端代码单服务(废弃)  服务端主程序  public class DalServer2 {  private static final MyLog _log = MyLog.getLog(DalServer2.class);  public static void main(String[] args) throws Exception {  MyUtil.setJmxIntegration(true);//启用jmx管理,需javassist和ognl库。  DalServer server = new DalServer();  server.setInitVrdb("/com/umpay/v3/dal/dal_vrdb.properties");  server.setInitRest(“/com/umpay/v3/dal/dal_rest.properties");  server.setInitAuth("/com/umpay/v3/dal/dal_auth.properties");  server.setInitUri(“cm20://0:8016”); //或者server.setInitUri(8016);  server.start();  //server.refresh(); //刷新相关配置:{auth,rest,sqlid等}...无法更新vrdb配置  //server.restart(); //重启整个服务:= stop()+start()...可更新vrdb配置  _log.info("服务%s", server.getService());  _log.info("测试%s/%s", server.getURI(), "dal/sqlid/testdb/sql_select.xml");  _log.info("测试%s/%s", server.getURI(), "dal/sqlwr/vdb.testdb/sql_select.xml");  _log.info("测试%s/%s", server.getURI(), "dal/prepareid/testdb/PrepareName1.xml");  }  }  自定义Restlet实现(废弃,改Dalet)  服务端JMX管理:jconsole
  30. 30. 30 -实践:服务端主程序多服务(废弃)  服务端主程序  public class DalServers2 extends DalServers {  private static final MyLog _log = MyLog.getLog(DalServers2.class);  public DalServers2(String cfg) throws IOException { super(cfg); }  protected Service4Mina2s createService(URI uri, HP4RpcInf proc) {  Service4Mina2s s = super.createService(uri, proc);  s.setSoLinger(0);//立即释放端口。  s.setReadIdle(61);  return s;  }  public static void main(String[] args) throws Exception {  DalHelper.setJmxIntegration(false);//启用jmx管理,需加入javassist-3.7.ga.jar和mina-ognl-2.7.2.jar库。  //DalHelper.setBioCodecMaxSize("cm20", 999999);//协议解析器最大报文长。  DalHelper.setRowListMax(99); //限制行结果的最大数。  DalHelper.setRowTitleLower(true); //强制行结果的字段名,转为小写后,方便转为Bean对象。  //DalHelper.initConfig(Dalet4Sqlid.class, “com/umpay/v3/dal/dal_psqlid.properties”);//废弃  DalHelper.initConfig(Dalet4PSqlid2.class, "com/umpay/v3/dal/dal_psqlid.properties");  DalHelper.initConfig(Dalet4MCache.class, "com/umpay/v3/dal/dal_mcache.properties");  DalHelper.initConfigAuth("com/umpay/v3/dal/dal_auth.properties");//servers.setInitAuth  DalHelper.initConfigVrdb("com/umpay/v3/dal/dal_vrdb.properties");//servers.setInitVrdb  DalServers servers = new DalServers2("/com/umpay/v3/dal/dal_rest.properties");//使用  servers.start("cm20://0:8020");  servers.start("http://0:8080");  }  }  自定义Restlet实现(废弃,改Dalet)  服务端JMX管理:jconsole
  31. 31. 31 +实践:服务端主配置多服务(推荐)  特点:  优点:直接通过配置文件传递参数,修改DalServers不再允许继承,方便版权保护。  缺点:无法修改Service4Mina2s相关参数。【改进:使用IoC配置beans.properties】  服务端主程序  java com.bs3.app.dal.engine.DalServers dal.properties  服务端主配置(dal.properties)  server.0 =cm20://0:8020  server.1 =http://0:8080  #server.2 =SSL.cm20://0:8021  #server.3 =ssl.http://0:8081  #server.4 =ssl2.cm20://0:8023  #server.5 =ssl2.http://0:8082  dal.jmx = 2  dal.row.to.lower=0  dal.row.max.list=990  #dal.bio.max.size=999990  cfg.auth=com/umpay/v3/dal/dal_auth.properties  cfg.vrdb=com/umpay/v3/dal/dal_vrdb.properties  cfg.rest=com/umpay/v3/dal/dal_rest.properties  com.bs3.app.dal.engine.Dalet4PSqlid=com/umpay/v3/dal/dal_psqlid.properties  com.bs3.app.dal.engine.Dalet4MCache=com/umpay/v3/dal/dal_mcache.properties  com.umpay.v3.dal.Dalet4PSqlid2=com/umpay/v3/dal/dal_psqlid.properties  服务端JMX管理:jconsole
  32. 32. 32 *实践:服务端配置(vrdb)  dal_vrdb.properties Quorum容错算法: 数据至少备份N份 写入至少W份 读入至少R份 要求:W+R>N  # vdb.testdb = NWR111,wdb,rdb1,rdb2 # One-Write/Multi-Read 【Read/Write Splitting】  # vdb.testdb = NWR331,db1,db2,db3 # Multi-Write/Multi-Read 【Quorum】  vdb.testdb4HA = NWR331,testdb,testdb1,testdb2,testdb3  vdb.testdb = NWR111,testdb,testdb1,  vdb.crmusr = NWR111,crmusr,crmusr,  ########## [bonecp,c3p0,dbcp,proxool,DriverManager,SingleConnection]  rdb.datasource.alias = bonecp # 【配置alias或class之一即可】  #rdb.datasource.class = org.springframework.jdbc.datasource.SingleConnectionDataSource  #rdb.datasource.class = org.springframework.jdbc.datasource.DriverManagerDataSource  #rdb.datasource.class = org.logicalcobwebs.proxool.ProxoolDataSource  #rdb.datasource.class = org.apache.commons.dbcp.BasicDataSource  #rdb.datasource.class = com.mchange.v2.c3p0.ComboPooledDataSource  #rdb.datasource.class = com.jolbox.bonecp.BoneCPDataSource  ##########  testdb.jdbc.username=root  testdb.jdbc.password=  testdb.jdbc.url=jdbc:mysql://localhost:3306/testdb?useUnicode=true&characterEncoding=GBK  #testdb.jdbc.url=jdbc:log4jdbc:mysql://localhost:3306/testdb # 【调试】记录详细日志  #testdb.jdbc.driver=org.gjt.mm.mysql.Driver #【可选】自动识别 {mysql,db2,oracle,mssql,derby,hsqldb,sqlite,h2,sybase,informix,postgresql,odbc,log4jdbc}  testdb.pool.max=20 #  testdb.pool.min=4 #  testdb.pool.wait=5000 # 【单位:毫秒】  testdb.partitionCount = 2 # 【可选】针对bonecp的特殊参数  testdb.maxConnectionsPerPartition=10 # 【可选】针对bonecp的特殊参数(2×10 = 20)  testdb.minConnectionsPerPartition=2 # 【可选】针对bonecp的特殊参数(2×2 = 4)  testdb.releaseHelperThreads = 2 # 【可选】针对bonecp的特殊参数
  33. 33. 33 *实践:服务端配置(rest3)  直接SQL模式【直接使用SQL语句,查询或者更新,无法控制权限】  # cm20://localhost:8016/dal/query/testdb  /dal/query.xml= com.bs3.app.dal.Dalet4Cm20Query  /dal/query/{dbname}= com.bs3.app.dal.Dalet4Cm20Query  /dal/update.xml= com.bs3.app.dal.Dalet4Cm20Update  /dal/update/{dbname}= com.bs3.app.dal.Dalet4Cm20Update  间接SQL模式【使用URI参数组成SQL语句,只适应简单查询,已废弃】  # cm20://localhost:8016/dal/select/testdb.xml/tusers/*/1  /dal/select/{dbname}/{tables}/{fields}/{wheres}= com.bs3.app.dal.Dalet4Cm20Select  使用RESTDB模式【把table映射为一个REST资源(未完)】  # cm20://localhost:8016/dal/restdb.xml  /dal/restdb/{dbname} = com.bs3.app.dal.Dalet4Cm20Restdb  /dal/restdb/{dbname}/{table} = com.bs3.app.dal.Dalet4Cm20Restdb  使用SQLID模式【远程方法调用RPC模式(推荐)】  # cm20://localhost:8016/dal/sqlid/testdb/findAll.xml  #/dal/sqlid/{dbname} = com.bs3.app.dal.engine.Dalet4Sqlid  #/dal/sqlid/{dbname}/{sqlid} = com.bs3.app.dal.engine.Dalet4Sqlid  #/dal/sqlrw/{dbname}/{sqlid} = com.bs3.app.dal.engine.Dalet4SqlidRw  #/dal/sqlrww/{dbname}/{sqlid} = com.bs3.app.dal.engine.Dalet4SqlidRww  #/dal/prepareid/{dbname}/{sqlid} = com.bs3.app.dal.engine.Dalet4Prepareid  #/dal/callid/{dbname}/{sqlid} = com.bs3.app.dal.engine.Dalet4PrepareCall  #/dal/sqlidn1/{dbname}/{sqlid} = com.bs3.app.dal.engine.Dalet4SqlidN1  #/dal/sqlidn2/{dbname}/{sqlid} = com.bs3.app.dal.engine.Dalet4SqlidN2  /dal/psqlid/{dbname}/{sqlid} = com.bs3.app.dal.engine.Dalet4PSqlid  /dal/mcache/{keyid} = com.bs3.app.dal.engine.Dalet4MCache 已合并为 DaletPSqlid
  34. 34. 34 +实践:服务端配置(auth)  认证方式  1,三步:Connect,Auth,(Request)* 【Poll模式连接池:类似SMPP/CMPP方式】  2,两步:Connect,(Auth & Request)* 【Push模式连接池:类似HTTP-Auth方式】  验证算法  算法【mac = bcd(md5(path|pass|from|nonce) 】  String src = String.format("%s|%s|%s|%s", authPath, authPass, authFrom, nonce);  String md5 = MyUtil.bcd(MyUtil.md5(src.getBytes()));  注:  Nonce 要求:1)不重复;2)递增(非顺序递增) 【建议使用long型时间戳】  authPath 包含了userId信息,如/dal/login/lius.xml。  authFrom 为客户端IP地址,该信息从socket上获取,不在报文中传递。【Ha-Proxy?】  authPath 包含了userId信息,如/dal/login/lius.xml?nonce=1234  认证和授权的配置文件(dal_auth.properties)  # ROLE.right = this.getClass().getSimpleName()+",";  guest.PASS=guest  guest.ROLE=Dalet4Sqlid2,,,,,  lius.PASS=liuspwd  lius.ROLE=Dalet4Sqlid, Dalet4SqlidRw,Dalet4Prepareid,,,  #lius.FROM=127.0.0.1,10.10.41.220 【废弃】  Lius.LIMIT=9 【新增特性】
  35. 35. 35 *实践:服务端配置(psqlid)  dal_psqlid.properties  #####################  #PUT.set_charset_ci = SET COLLATION_CONNECTION='utf8_general_ci'  PUT.set_names = SET NAMES {charset}  PUT.set_charset = SET CHARACTER SET {charset}  PUT.set_charset_ci = SET COLLATION_CONNECTION='{charset_ci}'  #####################  # INSERT INTO {tables} ("f1", "f2", ...) VALUES ("v1", "v2", ...)  # UPDATE {tables} SET 'f1'='v1','f2'=v2 WHERE {wheres}  GET.sql_select = SELECT {fields} FROM {tables} WHERE {wheres} {others}  PUT.sql_insert = INSERT INTO {tables} ({fields}) VALUES ({values})  PUT.sql_update = UPDATE {tables} SET {fieled_values} WHERE {wheres}  #####################  GET.users_findAll = select {fields} from tusers  GET.users_findOne = select {fields} from tusers where id='{userid}'  PUT.users_delete = DELETE FROM tusers where id='{userid}'  PUT.users_insert = INSERT INTO `tusers` (`id`, `passwd`, `payPasswd`, `regTime`, `lastLogTime`, `name`, `sex`, `certType`, `certNum`, `addr`, `zipCode`, `email`, `tel`, `state`, `tuseraccount_id`) VALUES ('{userid}', '{passwd}', '{payPasswd}', '{regTime}', '{lastLogTime}', '{name}', '{sex}', '{certType}', '{certNum}', '{addr}', '{zipCode}', '{email}', '{tel}', '{state}', '{tuseraccount_id}')  dal_callid.properties id是保留字,最好不要用做参数名,改userid。  GET.psql_test1 = select * from tusers where id={userid.string}  PUT.call_getseq = call mobile.getseq({name.string}, {out.seq.int})  PUT.call_PRiskControl_XE = call 参数名,含类型信息! 参数名,含返回信息。 MOBILE.PRiskControl_XE({busitype.string},{provcode.string},{areacode.string},{consign.int},{rolltyp e.string},{balsign.int},{balkeep.int},{mobileid.string},{amount.int},{xiaopaysign.int},{merid.string}, {goodsid.string},{merltdsign.int},{condaypayedswitch.int},{maxnum.int},{within.int},{out.grade.int },{out.ret.int},{OUT.msg.string}) OUT不区分大小写。
  36. 36. 36 -实践:PHP客户端(验证测试)  <?php  error_reporting (E_ALL);  $address = '127.0.0.1';  $service_port = 8016;  $socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);  if ($socket<0){ echo "n<br/>socket_create() failed: reason: " . socket_strerror($socket); }  $result = socket_connect($socket, $address, $service_port);  if ($result<0){ echo "n<br/>socket_connect() failed.nReason: ($result) " . socket_strerror($result);}  $in_xml0 = "<?xml version='1.0' encoding='GB2312'?><request><Accept-Type>PHPC</Accept- Type><METHOD>GET</METHOD><URI>/dal/select/testdb.xml/tusers/*/1/1/1</URI></request>";  $in_body = formatcontent($in_xml0);  $in_head = "CM20XMAP00GB00000" . (20+strlen($in_body));  socket_write($socket, $in_head, 20);  socket_write($socket, $in_body, strlen($in_body));  while ($out = socket_read($socket, 2048)) { echo $out; }  socket_close($socket);  function formatcontent($text){  $trans = get_html_translation_table(HTML_SPECIALCHARS);  $trans = array_flip($trans);  $text = strtr($text, $trans);  return $text;  }  ?>
  37. 37. 37 实践:客户端(远程和本地)  测试用例(DalClientsTest2类)  static void main_init() throws Throwable {  //MyLog.configure("dal_log4j.properties", true);  MyLog4j.configure("log4j.properties", true);  MyUtil.setDynamicLoading(5000);  DalHelper.setRowTitleLower(true);  DalHelper.setBioCodecMaxSize("cm20", 999000);  DalHelper.initConfigVrdb(cfg_vrdb);//"/com/umpay/v3/dal/dal_vrdb.properties"  DalHelper.initConfigAuth(cfg_auth);//"/com/umpay/v3/dal/dal_auth.properties"  DalHelper.initConfigRest(cfg_rest);//"/com/umpay/v3/dal/dal_rest.properties"  DalHelper.initConfig(Dalet4PSqlid.class,cfg_psqlid);//"/com/umpay/v3/dal/dal_psqlid.properties"  }  public static void test_local_vs_remote() throws Exception {  Map<String,String> args = new HashMap<String,String>();  args.put("tables", "tusers");  args.put("fields", "count(*) AS COUNT");//= [{COUNT=1}]  args.put("wheres", "id='13801092024'");  args.put("others", "");  DalApi4Inf api_remote = DalClientFactory.newRemoteApi(dal_uri, dal_fmt, 1, 5);  test_api(api_remote, "GET", "/dal/sqlid2/testdb/sql_select.xml", args, LinkedList.class);  //DalApi4Inf api_local = DalClientFactory.newLocalApi0(null, null, args, “testdb”); //【废弃】只支持sqlid模式  DalApi4Inf api_local = DalClientFactory.newLocalApi2(null, null, null, null); //【推荐】根据uri分发  test_api(api_local, "GET", "/dal/sqlid2/testdb/sql_select.xml", args, LinkedList.class);  api_remote.close(); //关闭  api_local.close();//关闭  }  static void test_api(DalApi4Inf api, String method, String uri, Map<String,String> args, Class<?> clz) throws Exception {  boolean modified = "PUT".equalsIgnoreCase(method);  Object ret = (modified ? api.doPUT(uri, args, clz) : api.doGET(uri, args, clz));  _log.info("### test_api(%s) = %s", uri, ret);  return ret;  }
  38. 38. 38 +实践:客户端(工厂模式)  新增DalClientFactory类  public static void close(DalApi4Inf api);  public static DalApi4Inf newRemoteApi(String uri, String fmt4, int min, int max);  public static DalApi4Inf newRemoteApi(String uri, String fmt4, int min, int max, String authUri, String authPwd, String authIp);  public static DalApi4Inf newLocalApi2(String cfgVrdb, String cfgRest, String cfgAuth, String cfgPsql);  public static DalApi4Inf newLocalApi0(String cfgVrdb, String cfgPsql, Map<String,String> args, String dbname);// @deprecated  注意:  1,用newLocalApi2替代newLocalApi0方法,后者只支持Dalet4Sqlid类。  1,不要每次创建,尽量缓存。  2,在多ClassLoader环境下,无法通过static确保唯一,单子模式失效。  3,及时释放资源,如在WebApp关闭时,调用DalClientFactory.close方法。
  39. 39. 39 +实践:客户端(读写分离和预编译)  读写分离  api.doGET("/dal/sqlrw/vdb.testdb/sql_select.xml", args, LinkedList.class);  api.doPUT("/dal/sqlrw/vdb.testdb/sql_insert.xml", args, Integer.class);  预编译  配置(callid.properties)  GET.PrepareName1 = select * from tusers where id={userid.string}  public static void test_prepareid() throws Exception {  DalApi4Sqlid api = new DalApi4Sqlid(new URI(uri), 2, 5, “H2GZ”, “GBK”, 1234L);  api.setAuth("/dal/login/lius.xml", "liuspwd", "127.0.0.1");//【增加登录信息】  String uri = "/dal/prepareid/testdb/PrepareName1.xml";  Map<String,String> args = new HashMap<String,String>();  args.put(“userid.string”, “13801092024”);//【名字中包含类型信息,不支持datetime】  //args.put("arg1.int", "1234");  //args.put("arg2.long", "1234");  //args.put("arg3.byte", "1234");  //args.put("arg4.float", "1234");  //args.put("arg5.double", "1234");  //args.put("arg6.boolean", "1234");  Object ret = api.doGET(uri, args, LinkedList.class);  api.close();  _log.debug("# prepareid(%s) = %s", uri, ret);  } 参数名,含类型信息!
  40. 40. 40 +实践:客户端(生成PO和属性注入)  生成PO对象  public static void test_sqlid_PoGenerator() throws Exception {  PoGenerator.setInitVrdb("/com/bs3/app/dal/engine/dal_vrdb.properties");  PoGenerator.setUseNumber(true);//使用Integer还是int方式。  PoGenerator g = new PoGenerator();  g.setPackage("com.umpay.v3.dal.po2");  g.setPackageBase("./src");//定义PO文件的基路径  g.setDbType(“db2”);//db2不支持where 0子句。  g.genPo(PoGenerator.getConnection("crmusr"), "umpay.t_user", "*", false);  g.setDbType(“mysql");  g.genPo(PoGenerator.getConnection("testdb"), "user", "id,username", false);  g.genPo(PoGenerator.getConnection("testdb"), "user", null, true);//生成文件  g.genPo(PoGenerator.getConnection("testdb"), "tweets", null, true);  g.genPo(PoGenerator.getConnection("testdb"), "followers", null, true);  g.genPo(PoGenerator.getConnection("testdb"), "following", null, true);  }  根据PO对象注入属性值  List<Map<String,String>> rlist = (List<Map<String,String>>) api.doGET("/dal/sqlid/testdb/user_findAll.xml", args, LinkedList.class);;  for(Map<String,String> map: rlist) {  User user = new User();  MyUtil.inject2setter(user, map, false);//将属性值注入user对象。  _log.info("# inject2setter() = %s", user);  }
  41. 41. 41 +实践:JMX管理功能(+演示)  工具:jconsole  组件:MBean  分组:Service4Mina2s-8020-Cm20Codec  Service4Mina2s  属性:SessionsCount/SessionsCountMax/…  操作:restart()/disconnectAll()/disconnectIP(ip)  ProtocolCodecFilter  ExecutorFilter  属性:poolSize/maximumPoolSize/…  NioSocketAcceptor或NioSocketConnector  属性:readIdleTime/maxReadBufferSize/…  组:NioSocketSession@127.0.0.1  NioSocketSession  操作:close()  分组:Service4Mina2s-8080-HttpCodec  。。。  其他:Bonecp  TODO:根据USER对Session分组。
  42. 42. 42 +实践:性能测试和功能测试  20100719 测试(张文凌)  测试环境:58/Linux,语句:values current,连接池c3p0  测试结果:  JDBC1:线程数100,每线程500请求,耗时6122,吞吐量:8167/s 【线程只用一个连接,全部完成后再释放】  JDBC2:线程数100,每线程500请求,耗时9996,吞吐量:5002/s【线程每次从连接池获取/释放/…】  Local:线程数100,每线程500请求,耗时54675,吞吐量:914/s【DalApiLocal】  Local:线程数100,每线程500请求,耗时61178,吞吐量:817/s【DalClient4Local】  Remote:线程数100,每线程500请求,耗时73078,吞吐量:758/s  20100729 测试(刘胜)优化DalEngine后  测试环境:220/WinXP,连接池bonecp,去掉mpsp.log日志,去掉GET控制台日志。  测试结果:本地模式  # test_sqlid_performance() 连接数(1..50),线程数50,每线程500请求,耗时13094ms,吞吐量:1909/s 地址:/dal/psqlid/uselect/db2_select_now.xml  # test_sqlid_performance() 连接数(1..50),线程数50,每线程500请求,耗时3922ms,吞吐量:6374/s 地 址:/dal/psqlid/testdb/mysql_select_now.xml  # test_sqlid_performance() 连接数(1..50),线程数50,每线程500请求,耗时3985ms,吞吐量:6273/s 地 址:/dal/psqlid/testdb/mysql_select_now.xml  # test_sqlid_performance() 连接数(1..50),线程数50,每线程500请求,耗时3750ms,吞吐量:6666/s 地 址:/dal/psqlid/testdb/mysql_select_now.xml  测试结果:远程模式(DalServer在本机)  0729.113557.625 [main] INFO L:50 DalClientsTestNio - 【BIO】连接数(50..50),线程数50,每线程 800请求,耗时32579ms,吞吐量1228/s cm20://localhost:8020/dal/sqlid2/testdb/sql_select.xml  0729.113707.968 [main] INFO L:50 DalClientsTestNio - 【BIO】连接数(20..20),线程数20,每线程 2000请求,耗时30593ms,吞吐量1307/s cm20://localhost:8020/dal/sqlid2/testdb/sql_select.xml  0729.114938.375 [main] INFO L:50 DalClientsTestNio - 【BIO】连接数(50..50),线程数50,每线程 800请求,耗时33016ms,吞吐量1211/s cm20://localhost:8020/dal/sqlid2/testdb/sql_select.xml  参考:  20100707(张文凌)DAL性能测试结果.xlsx.et 【Win/Linux,Local和Remote,JDK5/JDK6】  20100730(纪鑫宇)DAL功能测试结果.xlsx 【类型支持,功能支持,读写分离,字符集支持】
  43. 43. 43 +实践:结果集分页技术  方式:  1,iBatis或Hibernate  2,直接修改psqlid配置文件的sql语句。  样例:通过PoGenerator生成PO对象以及SQL模板  代码:见【实践:客户端(生成PO和属性注入) 】  方法:  String sql_query_first(String dbtype,String table,String fields,String wheres,String orders,int n);  String sql_query_limit(String dbtype,String table,String fields,String wheres,String orders,int offset,int n);  类型:MySQL/PostgreSQL/SQLite/HSQLDB/H2  queryFirst = SELECT {fields} FROM tusers WHERE {wheres} ORDER BY {orders} LIMIT 15  queryPage = SELECT {fields} FROM tusers WHERE {wheres} ORDER BY {orders} LIMIT 15 OFFSET 0  类型:DB2  queryFirst = SELECT {fields} FROM umpay.t_user WHERE {wheres} ORDER BY {orders} FETCH FIRST 15 ROWS ONLY  queryPage = SELECT * FROM (SELECT RANK() OVER( ORDER BY {orders}) AS i_,{fields} FROM umpay.t_user WHERE {wheres}) AS T_ WHERE i_>0 FETCH FIRST 15 ROWS ONLY  #queryPage = SELECT * FROM (SELECT ROWNUMBER() OVER( ORDER BY {orders}) AS i_,{fields} FROM umpay.t_user WHERE {wheres}) AS T_ WHERE i_>0 FETCH FIRST 15 ROWS ONLY 【ROWNUMBER()=ROW_NUMBER() 】  类型:Oracle  queryFirst = SELECT {fields} FROM mobile.tarea WHERE {wheres} ORDER BY {orders} WHERE ROWNUM<=1  queryPage = SELECT * FROM(SELECT T.*,ROWNUM RN FROM (SELECT {fields} FROM mobile.tarea WHERE {wheres} ORDER BY {orders}) T WHERE ROWNUM<=15) WHERE RN>0  参考:  http://en.wikipedia.org/wiki/Select_(SQL)
  44. 44. 44 +实践:访问MemCached*  相关配置  Dal.properties  com.bs3.app.dal.engine.Dalet4MCache=com/umpay/v3/dal/dal_mcache.properties  Dal_rest.properties  /dal/mcache = com.bs3.app.dal.engine.Dalet4MCache  /dal/mcache/{keyid} = com.bs3.app.dal.engine.Dalet4MCache  Dal_mcache.properties  mcache.server.0=localhost:11211  mcache.weight.0=5  mcache.initConn=2  mcache.minConn=2  mcache.maxConn=20  mcache.maxIdle=188000  mcache.maxBusyTime=122000  mcache.maintSleep=5000  mcache.socketTO=3000  mcache.socketConnectTO=9000  mcache.failover=false  mcache.nagle=false  mcache.aliveCheck=true  mcache.hashingAlg=3 【CONSISTENT_HASH】  测试用例:  DalClientsTest2.test_dalet4mcache()  GET http://localhost:8080/dal/mcache/id.xml?x-accept-charset=GBK&x-accept-format4=GSON  POST http://localhost:8080/dal/mcache/id.xml?x-accept-charset=GBK&x-accept-format4=GSON  GET http://localhost:8080/dal/mcache/id.xml?x-accept-charset=GBK&x-accept-format4=GSON&METHOD=POST&VALUE=123&CMD=replace  相关参数:  Keyid在uri中定义  Value只能是String类型,通过VALUE值传送。  方法与method相关(GET=get,PUT=set)。【通过增加CMD参数来支持get/set以外的其他方法。】  其他特性:1,动态更新配置。2,一致性HASH算法
  45. 45. 45 +实践:新的认证方式(多IP和Nonce)  原因:  引入负载均衡层,地址不再唯一确定。  未来可能存在其他认证。  改进:  1,支持逗号分隔的多authIP格式:ip1,ip2,ip3,… 【多IP源】  2,更新rest配置,根据authPath获取dalet来完成认证。【多算法】  3,改进authType算法,消除authNonce项。【精简数据项】  旧:bcd(md5(authPath|authPwd|authIP|nonce))  新:bcd(md5(authPath?nonce=x|authPwd|authIP|null))  新旧版交叉兼容性分析:  0,客户端(旧)访问服务端(旧)  算法:bcd(md5(/dal/login/user.xml|pwd|IP1|nonce))  校验:1)获取RemoteAddress;2)IP相同;3)获取nonce非null;4)计算MD5相同。  1,客户端(旧)访问服务端(新) 【兼容】  算法: bcd(md5(/dal/login/user.xml|pwd|IP1|nonce))  校验:1)获取authFrom项;2)IP包含; 3)获取nonce非null; 2)计算MD5相同。  2,客服端(新)访问服务端(旧) 【不兼容】  算法: bcd(md5(/dal/login/user.xml?nonce=x|pwd|IP1,IP2,IP3|null))  校验:1)获取RemoteAddress;2)IP不相同;2)获取nonce为null;3)计算MD5相同。  其他问题:  增加authIP新IP地址? 【不拒绝,只记录告警日志用于审计】
  46. 46. 46 *小节:版本进展和TODO列表  V0.5 DONE 验证原型:  MyStream,CM16,DalServer,ClientApi  V0.9 DONE 基本实现  协议改进CM16=>CM20,优化字符集处理  支持ActiveTest报文处理。  定义DbPool4Vrdb替代DbPool4Args使DataSource参数可配置。  定义NamedProperties统一动态加载配置,定义DalEngine2基类。  使用Sqlid模式,支持参数化SQL,增加ClientApi类型  支持Exception处理,直接序列化返回给Client端。  增加Login处理【=》合并Sqlid和Auth功能,每次都带验证信息,增加IP验证。】  V1.0 DONE 功能完善  定义DalApi4Local支持Sqlid模式的本地操作,可部分替代iBatis功能。  定义Restlet4Cm20SqlidWR服务,支持读写分离。  定义Restlet4Cm20Prepareid服务,支持预编译SQL功能。  压力测试:本机MySQL测试:~450#/s =》需要改进:提高到1000#/s。。。DONE  结果缓存:本机HashMap缓存: =》需要改进:使用JVM外的缓存(如EHCached,Memcached)  动态配置:可动态配置auth/rest/sqlid =》需要改进:无法动态配置vrdb。。DONE:通过jmx重启服务。  访问日志:生成SqlLog =》DONE:分离出:查询日志SqlGetLog,更新日志SqlPutLog  V1.5 TODO  管理控制:用户认证,连接数限制,强制关闭客户连接,JMX管理。  优化客户端API接口:【使用poll模型替代push模型。支持批处理。使用单独的登录请求。支持多HOST负载均衡。】  增强服务端Rest功能:定义RestletCm20Callid支持存储过程操作。  V2.0 TODO  支持更多的分片模式。(按ID分片;按时间分片;按索引表分片;)  支持NoRDB存储方式(memcached,TTServer,mongodb,db4o)  支持NWR模型来提高可用性。
  47. 47. 47 +小节:版本持续改进Q3  Restlet/Dalet  Dalet4Sqlid  Dalet4Sqlrw  Dalet4PrepareSql  Dalet4PrepareCall Dalet4Sqlid  Dalet4SqlidN1/N2/N3/…  Engine/Servers  DalEngine  DalEngine4Xml /dal/psqlid/vdb.testdb/sql_select.xml Dalet4PSqlid  DalEngine4XmlRest 【支持单格式{XmlAny}/单协议{CM20}/单服务】  DalEngine2 【引入NamedProperties】  DalEngine2Restlet 【支持多格式{XmlAny|XProps}/多协议/多服务,简化HTTP访问】  ClientAPI  远程:DalClients.DalApi4Sqlid  本地:DalClients.DalApi4Local => DalClient4Local  其他  支持JMX管理:Service4Mina2/Filter{Codec|Executor}/NioAcceptor/NioSession  生成PO对象,属性注入【MyUtil.inject2setter(Map, PO)】  支持BLOB/CLOB类型【BLOB=>Byte[],CLOB=>String】  例:update umpay.T_MER_CNF set mercert=blob('2131324124124124124') where merid='5632‘  连接池(Push和Poll模式)  BioSockPoolPoll: 使用Poll模式,直接获取连接,提交请求,等待接受响应。(不支持ActiveTest操作)  BioSockPoolCall: 使用Push模式,将请求委托给BioSockPoolCall完成。  BioSockPoolService: 持有BioSockPoolCall句柄。支持ActiveTest线程。  字符:对GBK/GB18030生僻字的支持。  分页:通过PoGenerator生成分页语句(支持mysql/db2/oracle/…)  支持访问MemCached 【支持哈希一致性算法】
  48. 48. 48 +小节:版本持续改进Q4  服务端:  Dalet4MCache 增加CMD参数支持set/get以外方法  Dalet4Mongo 支持MongoDB存储  Dalet4RestKvs 支持REST模式存储到内存Map中。  Dalet4RestRdb 支持REST模式存储到Rdb中。  TODO  Dalet4Lock 分布式锁服务  Dalet4ShardInt 按照Int类型ID进行分片  Dalet4ShardDate按照Date类型ID进行分片  多表查询  select * from user_0 union all select * from user_1;
  49. 49. +新需求:基础支付平台项目 49  背景:基础支付平台(核心账务系统)  前台:FSL前置服务层(协议适配,配置工具)  中台:ASL应用服务层(业务网关,支付网关)  后台:BSL基础服务层(数据访问,核心账务) 业务网关 通信前置 FSL 调度服务 ASL 核心系统 数据服务 DAL 基础服务 BSL DB Tuxedo 支付网关 BSL 支付网关 通信前置 FSL 通信前置 FSL 网银直连 银企直连 通信前置 FSL 接入前置 WEB 管理服务 MML 综合管理服务系统(管理/监控/安全/认证/…)  方法:一致性  将现有DAL产品,改造成DAL平台。  用一套框架实现三个服务子系统。  架构一致,开发一致,测试一致。 ALL in ONE 调 度 和 路 由 ASL
  50. 50. 50 +新特性:从DAL产品到DAL平台  DAL软件产品  主要模块  DalServers(配置dal.properties)  DalClient(DalLocalAPI,DalRemoteAPI)  PoGenerator  产品特性  支持两种协议(CM20,HTTP)  支持两种处理(同步,异步)  支持多种序列化和gzip压缩  文本格式:Burlap,XStream,GSON,Jackson等  十六进制:Java,Hessian,Hessian2,Phpc,AMF3等  支持三种模式:标准SQL,预编译SQL,存储过程  支持读写分离等特性  DAL服务平台  BeansServer(配置beans.properties)  支持依赖注入和参数配置,方便二次开发  支持参数注入到dalet中  有限状态机FSM模型  前端支持CM20和HTTP协议(NIO方式)  后端支持CM20和HTTP协议(异步调度) 改 造 中
  51. 51. 51 +新特性:依赖注入和IoC容器  问题:  配置少而僵化dal.properties  缺少依赖管理  改进:  实现IoC容器BeansContext/BeansContext2  配置多且灵活beans.properties  实现依赖注入  组件创建  Setter注入  构造子注入  初始化和销毁方法  循环依赖  预启动和延迟加载  容器注入:Map,Properties,List  基础  平台中立:多编程语言  内容协商:多种序列化  属性注入:DataSource
  52. 52. 52 +新特性:高可用mcache访问  实现  Dalet4MCache  特性:直接访问  Dalet4MCacheAW  特性:永远可写,尝试多次写入  配置:mcache.aw.max = 3  Dalet4MCacheNWR  特性:永远可读,参考NWR模型  配置:mcache.ar.nwr = 331 保留3个备份(n<w+r)  问题:  如何确定最终存储在哪个mcache节点?  确保多个备份,不在同一mcache节点。
  53. 53. 53 +新特性:防止SQL注入  实现:  扩展Dalet4PSqlid为Dalet4PSqlidSafe类。  覆盖hasSqlInject()方法。  使用  从Dalet4PSqlidSafe继承。
  54. 54. 54 +新特性:缺省参数(动态SQL)  目的:实现iBatis动态SQL效果  实现:支持sqlid参数的缺省值  格式:method.psqlid.参数名= {具体值| 字段名}  扩展:参数名=字段名,参数值=字段名  where子句:字段名=字段名【true】  update子句:字段名=字段名【不修改】  配置:  GET.sql_test3 = select * from `{tablename}` where id>={userid} AND age={age}  GET.sql_test3.tablename = tusers  GET.sql_test3.userid = lius  GET.sql_test3.age = age
  55. 55. 55 +新特性:限制用户连接数  实现  Dalet4BaseAuth读取LIMIT参数(缺省值99)  DalMina2H4Rpc配置userLimit属性。  配置  修改dal_auth.properties增加  hfrisk.LIMIT=1  修改beans.properties  ServerIoHandler.class= com.bs3.app.dal.engine.DalMina2H4Rpc  ServerIoHandler.passive= true  ServerIoHandler.processor= @DalEngine  ServerIoHandler.userLimit= @DalUserLimit  DalUserLimit.class=com.bs3.app.dal.engine.DalUserLimit
  56. 56. 56 +新特性:批处理模式  需求(张峻嘉)多条SQL同一事务(非批次)  实现:修改Dalet4PSqlid 支持事务性多表更新  配置:psqlid.properties  已实现——sqlid必须以小写batch开头,值为多条普通sql语句,格式如: sql1;sql2;sql3,暂不支持预编译sql方式。  未实现——sqlid必须以小写pbatch开头,值为单条预编译sql语句,参数Map 中为arg#1=v1,arg#2=v2格式。  需求(贺林)相同SQL不同参数(批执行)  实现  定义Dalet4PSqlidN处理预编译批处理多次提交DB(SELECT和UPDATE)  定义Dalet4PSqlidNBatch处理预编译批处理一次提交DB(非SELECT)  配置:和psqlid类似,以psql开头  参数:{1.arg1/1.arg2/…} + {2.arg1/2.arg2/…} + {…}  样例:见DEMO中DalClientsTest2.test_batchs()
  57. 57. 57 +新特性:获取DB连接时间  需求(张峻嘉)提供连接池大小限额的决策支持  功能:日志中分别记录获取DB连接时间、执行SQL时间  实现:修改SQL日志输出格式。  配置:无
  58. 58. 58 +新特性:预编译动态表名0720  问题  在对SQL预编译时,需获取数据库表名,通过表结构来决定执 行计划,否则执行失败。  解决  对于预编译SQL和存储过程模式,区分两类参数:  以下划线开头的参数,在预编译前直接替换为具体参数值。  非下划线开头的参数,在预编译前替换为问号,作为参数。  配置  GET.sql_test2 = select * from `{table.string}` where id={userid.string} ——成功  GET.psql_test2 = select * from {table.string} where id={userid.string} ——失败  GET.psql_test3= select * from `{_table}` where id={userid.string} ——成功
  59. 59. 59 +新特性:在Spring中配置DAL客户端  关于DalApi4SqlidDecorator的问题。  1,混杂两种复用模式:继承和使用,可去掉一种。  2,无需新类也可在spring中配置使用。  <bean id=" DalApi4Sqlid" class="com.bs3.app.dal.client.DalClientFactory" factory-method="newRemoteApi">  <constructor-arg type="java.lang.String" value="cm20://localhost:8020/"/>  <constructor-arg type="java.lang.String" value="JAVA"/><!-- ={JAVA|J2GZ|XS2X|XS2J|JACK|GSON|BURP|H1SP|H1GZ|H2SP|H2GZ|...} -->  <constructor-arg type="int" value="1"/>  <constructor-arg type="int" value="5"/>  <constructor-arg type="java.lang.String" value="/dal/auth/lius.xml" />  <constructor-arg type="java.lang.String" value="liuspwd"/>  <constructor-arg type="java.lang.String" value="10.10.36.53,127.0.0.1"/>  </bean>
  60. 60. 60 Q结&束A:Q&A  现场问题——?  1,  2,  3,  思考题——  1,什么是DAL?  2,为什么要用DAL?  3,目前的DAL有哪些功能特性?  4,何时使用DAL本地调用接口?  5,何时使用DAL远程调用接口?  6,如何在自定义dalet中获取其它组件?  7,如何在自定义dalet中获取DAL本地调用接口?
  61. 61. 61 参考索引  参考:  20081113大型分布式系统架构技术简介(刘胜)中级.pdf  20081211大型软件系统开发综述(刘胜)中级.pdf  20090219网络信息安全和认证技术(刘胜)中级.pdf  20090625服务器框架的概念和实践(刘胜)初级.ppt  20090625分布式认证和授权技术(刘胜)初级.ppt  《2009系统架构师大会(演讲稿)》  20090914系统架构师2009大会归来(刘胜)暨头脑风暴.ppt  20091024手机之家的数据访问层实践(许超前).ppt  20091024高性能Web服务器Nginx及相关新技术的应用实践(张宴).ppt  20091102关于RPC和序列化技术的比较.txt  20091224数据访问层DAL概念和实践1(刘胜).ppt  20100326数据访问层DAL概念和实践2(刘胜).ppt  20100423第一届UMPAY技术大会(刘胜)基于SOA的DAL架构和实践.ppt
  62. 62. 62 参考:Dynamo概念  术语:  Q=虚拟节点数;S=实际节点数;N=数据备份数 ;  W=要写入至少W份才算成功;  R=要读入至少R份才算成功;  问题1:实现动态扩容  算法:Consistent-Hashing算法  问题:实际节点的负载能力不一样。  改进:引入虚节点(Q >> S*N)  问题2:确保数据可靠  备份:N>=3,要求备份在不同实节点。  算法:NWR模型与同步和异步备份  数据一致性:W+R>N (即R>N-W,每次读取都至少读 到一个最新版本,从不会是一份旧数据)  高可写环境:N=3,W=1,R=N  高可读环境:N=3,W=N,R=1  版本一致性:多版本数据,Vector-Clock算法  服务端保留所有版本,用Vector Clock记录版本信息 。  当读取操作发生的时候返回多个版本,由客户端的业 务层来解决这个冲突合并各个版本。  最简单的策略:最近一次的写覆盖以前的写。  问题3:消除单点故障  参考:  http://hi.baidu.com/zeorliu/blog/item/98486 7f0a4b55bc97931aaf2.html 介绍Amazon的 Dynamo  论文:『amazon-dynamo-sosp2007.pdf』 NoSQL接口设计: get(key) getAll([key1,key2,key3,keyN]) put(key,value,version) delete(key) delete(key,version)
  63. 63. 63 参考:Dynamo关键技术  分布式设计的需求和概念  1.Eventual consistency 【过程松,结果紧】  过程中允许部分不一致;  但是在事务处理结束或者有限的时间内保持事务的一致性。  2.可用性,容错性,高效性。【通过NWR平衡】  3.分布式设计中两类一致性问题:  单点数据读写一致性:通过数据存储的服务端控制即可(类似于DB的控制)  多点数据读写一致性:通过消息传播的方式来实现(类似于JGroup在多播通 道传播同步消息)。  4.冲突解决。【数据多版本】  要点:  1. Consistent hashing算法支持分布式多节点  a,支持不同能力节点的权重设置。  b.动态新增或者删除节点时,减少数据复制。  c.动态新增或者删除节点时,平均压力分摊。  2. Vector clock管理数据多版本
  64. 64. 64 参考:Dynamo关键技术  分布式Key-Value存储Dynamo:  特点  完全去中心化,人工管理工作很小。  总是可写,可根据读写情况进行调整NWR来优化  采用的都比较成熟的技术来处理可扩展性和可用性问题  问题:Partitioning  技术:改进的Consistent Hashing  优点:Incremental Scalability  问题:High Availability for writes  技术:Vector clocks with reconciliation during reads  技术:Version size is decoupled from update rates.  问题:Handling temporary failures  技术:Sloppy Quorum and hinted handoff  技术:Provides high availability and durability guarantee when some of the replicas are not available.  问题:Recovering from permanent failures  技术:Anti-entropy using Merkle trees  技术:Synchronizes divergent replicas in the background.  问题:Membership and failure detection  技术:Gossip-based membership protocol and failure detection.  技术:Preserves symmetry and avoids having a centralized registry for storing membership and node liveness information.  参考:  http://hi.baidu.com/zeorliu/blog/item/984867f0a4b55bc97931aaf2.h tml 介绍Amazon的Dynamo  http://www.allthingsdistributed.com/2007/10/amazons_dynamo.html 『amazon-dynamo-sosp2007.pdf』
  65. 65. 65 +参考:豆瓣网BeansDB  主页:http://code.google.com/p/beansdb/  为什么做BeansDB?  其它Key-Value选择  Memcachedb,tokyotrant,主从复制【不便于Fail-Over】  其它类Dynamo选择  Dynomite:erlang完整实现,内存效率可能有问题  Voldemort:Java部分实现  最初的动机:  存储大量图片【MogileFS比较慢】  BeansDB相对Dynamo的简化  简化服务器端,在客户端实现Routing功能。  简化版本管理,用单版本号+时间戳  简化数据拆分,手动管理数据分布  简化协议,使用mc兼容协议  简化server端实现,tc+memcached  简化同步,外部定时任务实现  特性:  高可用:通过多个可读写的用于备份实现高可用  最终一致性:通过哈希树实现快速完整数据同步(短时间内数据可能不一致)  容易扩展:可以在不中断服务的情况下进行容量扩展。  高性能:异步IO和高性能的KeyValue数据TokyoCabinet  可配置的可用性和一致性:通过N,W,R进行配置  简单协议:Memcache兼容协议,大量可用客户端
  66. 66. 66 +容错理论  The Byzantine Generals Problem Leslie Lamport, Robert Shostak, and Marshall Pease ACM TOPLAS 1982  Practical Byzantine Fault Tolerance Miguel Castro and Barbara Liskov OSDI 1999  参考:  http://blog.sina.com.cn/s/blog_483452da0100brdm.html 拜占庭将军问题  http://www.pmg.csail.mit.edu/bft/ 【论文集】  http://people.csail.mit.edu/cowling/hq/  http://userweb.cs.utexas.edu/users/dahlin/projects/bft/  Byzantine fault tolerance(Liskov).ppt  Byzantine fault tolerance - Rice University.ppt  BFT Protocols Under Fire.pdf  BFT Protocols Under Fire(nsdi_talk).pdf  Conflict-free-quorums.pdf  HQ Replication.pdf  。。。
  67. 67. 67 +容错:Byzantine将军问题  概念(The Byzantine Generals Problem)  问题:设计一个协议,一个司令要送一个命令给他的n-1个副官,使得:  IC1.所有忠诚的副官遵守同一个命令。  IC2.如司令是忠诚的,则每一个忠诚的副官遵守他送出的该命令。  约定:忠诚的将军将遵守协议,而叛徒则可能破坏协议,尽可能的干绕其它人的判断。叛徒是匿名 的。而且最后不需要确定谁是叛徒。  目的:要让爱国的将军达成一致,而非找叛国的将军。  结论:  1 叛徒数m大于或等于将军总数n的1/3时,拜占庭问题不可解。  结论:当n<=3m时,将军们无法达成一致,即不存在同时满足IC1和IC2的协议。  2.用口头信息(Oral Message,OM),叛徒数少于1/3,拜占庭问题可解.  口头信息的三个条件:  A1) 传送正确。【TCP】  A2) 接收者知道是谁发的。【认证】  A3) 沉默(不发信息)可被检测。【丢包】  结论:当n>=3m+1时,可以让将军们可以达成一致。此时共需要信息交换轮数m+1.  3 用书写信息(Signed Message),至少两个忠诚,拜占庭问题可解  在口头信息的基础上, 书写信息又增加了两个条件  A4) 忠诚司令的签名不能伪造,内容修改可检测。【签名】  A5) 任何人都可以识别司令的签名, 叛徒可以伪造叛徒司令的签名。【??】  结论:当n>=m+2时,可以让将军们可以达成一致,此时共需要信息交换轮数m+1.  总结:OM(n,1)中n>=4;SM(n,1)中n>=3; 【3备份】  参考:  原文:http://yaowei211.blog.sohu.com/30757545.html
  68. 68. 68 +容错:BTF Basic protocol  BFT: Protocol overview  Client c sends m = <REQUEST,o,t,c>σc to the primary. (o=operation, t=monotonic timestamp)  Primary p assigns seq#n to m and sends <PRE-PREPARE,v,n,m> σp PBFT main ideas: •Static configuration (same 3f+1 nodes) •To deal with malicious primary to other replicas. (v=current view, i.e., replica set)  If replica i accepts the message, it sends <PREPARE,v,n,d,i> σi to other replicas. (d is hash of the request). Signals that i agrees to assign n to m in v. •Use a 3-phase protocol to agree on sequence number  Once replica i has a pre-prepare and 2f+1 matching prepare •To deal with loss of agreement messages, it sends <COMMIT,v,n,d,i> σi to other replicas. At this point, correct replicas •Use agree a bigger on quorum an order (2f+of 1 requests out of 3f+within 1 nodes) a view. •Need to authenticate communications  Once replica i has 2f+1 matching prepare and commit messages, it executes m, then sends <REPLY,v,t,c,i,r> σi to the client. (The need for this last step has to do with view changes.)
  69. 69. 69 +容错:Byzantine容错协议  BFT(Byzantine-Fault-Tolerance)Approach  agreement-based 【Replica广播】  BFT基本协议【Practical BFT,3段协商】。。。  LBFT协议【LBFT1和LBFT2】。。。。。。。  Zyzzyva【3f+1,3 one-way latencies but need 3f+1 responsive 】  quorum-based 【Client协调】无并发写冲突时更优  Q/U 【Query/Update, 5f+1,1 roundtrip(SOSP 2005) 】  HQ 【Hybrid Quorum,3f+1, 2 roundtrips(OSDI 2006) 】 PBFT [OSDI'99] Q/U [SOSP'05] HQ [OSDI'06] BAR [SOSP'05] BFT2F [NSDI'07] Zyzzyva [SOSP'07] Shepherd [SOSP'07] A2M [SOSP'07]
  70. 70. 70 +容错:LBFT1和LBFT2  目的:简化协议,提高效率  环境:  参考:  Diverse Replication for Single- Machine Byzantine-Fault- Tolerance.pdf
  71. 71. 71 -容错:设计DAL的LBFT3协议(废弃)  交互协议(写操作)  DAL.C发送写操作请求PUT。  DAL.S获得vdb中的写库wdb。  DAL.S对wdb执行写操作,记录wlog作为恢复日志。  DAL.S对活动读库集[rdb1,rdb2,…]执行写操作。  DAL.S对非活动读库[rdb3]记录写操作到Q{rdb3}。  DAL.Q执行队列任务,完成写操作。  。。。未完。
  72. 72. 72 参考:数据库分区技术  DB2的Shared-Nothing架构(v9.0+)  数据库被分区到集群的每个节点上。每个节点都有一个数据的唯一子集 ,所有访问这些数据的都要到这个节点。  数据并行操作的性能,取决于数据被合理的分区。  每个分区被各自的处理器进行管理。  系统可以使用双磁盘子系统,保留一个物理备份,来防止某个节点错误 影响系统可用性。不过此时依然会显著的降低整体性能。  它的Shared-Nothing指的是在运行期间对数据的所有权,而不是物理 上的关系。如果某个子集使用的皮率很高,则会降低整个系统的吞吐量 和性能。  RAC的Shared-Cache架构  RAC让磁盘可以被所有的节点链接来解决这个问题。  数据库文件在所有的节点间逻辑共享。每个实例都可以访问所有的数据 。  共享磁盘访问可以通过硬件链接或者操作系统层提供一个所有节点上设 备的单一视图。如果多个节点同时链接相同的数据块,事务共享磁盘数 据库系统使用磁盘I/O来同步多个节点的数据访问,比如通过一个写入 块的锁来防止其他节点访问同样的数据块。  磁盘可以进行分区管理,不过如果没有很好的分区,则会显著的影响性 能,并增加维护连续数据缓冲区的开销。  RAC使用了Cache Fusion, 一个共享一致性缓冲技术,通过高速的内部 连接的来维持共享一致性缓冲。Cache Fusion利用了集群里面所有节 点的缓冲来服务于数据库事务。  补充:  Greenplum也采用Shared-Nothing架构。  参考:  http://coderarea.net/html/shujukukaifa/DB2/2009/0310/58281.html DB2 和Oracle体系结构  http://en.wikipedia.org/wiki/Partition_(database)  http://tolywang.itpub.net/post/48/306675 理解oracle rac cache fusion
  73. 73. 73 开放系统的存储: 》内置存储 》外挂存储【按连接的方式分】 》》直连式存储(Direct-Attached Storage,简称DAS) 》》网络化存储(Fabric-Attached Storage,简称FAS)按传输协议分 》》》网络接入存储(Network-Attached Storage,简称NAS) 》》》存储区域网络(Storage Area Network,简称SAN) 参考:数据库分片技术  分片(Sharding)和分区(Partition) 存储依赖可跨DB,可跨物理主机可跨表空间,不同物理属性,不能跨DB存储 数据划分根据时间,范围,面向服务等根据范围,Hash,列表,混合分区等 存储方式分布式集中式 扩展性Scale-Out Scale-Up 可用性无单点存在单点(DB本身) 价格低廉适中(DAS直连式存储),昂贵(SAN存储区域网络) 应用场景常见于Web2.0网站多数传统应用  实现分片: 分片(水平分区) 分区  开源Sharding软件: 分片模式: 1.按功能划分(垂直切分) 2.按某一字段值的范围划分(水平切分) 3.基于HASH的切分 4.基于路由表的切分  MySqlProxy+HScal,Hibernate Shards,Spock Proxy,HiveDB,PL/Proxy,PyShards  自定义分片:所有的DAO操作至少需要增加一个参数(date或者id)  按时间分片(交易日表):1)操作原始表,定期归档成日表;2)直接操作日表; 【推荐2】  按ID分片(用户表) :针对主键字段,使用递增ID,每500万条记录单独分片【如QQ号】  按字段分片(索引表) :针对索引字段,以增量方式建立独立的索引表并分片【可选】  参考:  存储技术:http://www.it.com.cn/f/server/053/21/89080.htm 浅议DAS、NAS、SAN三种模式。  分片技术:http://www.dbanotes.net/database/database_sharding.html 开源数据库Sharding技术(2008.7); http://hi.baidu.com/jabber/blog/item/e39ef81f1bca2df3e1fe0b3d.html HiveDB,一个横向切分MySQL海量数据 的框架(2008.7);http://www.ibm.com/developerworks/cn/linux/database/mysql-ha/index.html 基于MySQL的 数据库集群系统的实现(2003.3);http://www.360doc.com/content/090314/23/96202_2810788.html 读 “DB-Sharding@Netlog”看DB Scale Out(2009.3);
  74. 74. 74 参考:数据库复制技术  DB2的SQL复制  多种来源:  多个目标(跨DB)  DB2的Q复制  单一来源  单一目标(仅DB2)  基于可靠消息队列
  75. 75. 75 参考:Tungsten Replicator
  76. 76. 76 参考:架构经验(淘宝,eBay)  淘宝网架构经验(淘宝网架构师黄裳) :  1、适当放弃一致性【最终一致性,补偿交易】  2、备份和隔离解决稳定性问题【Embrace Inconsistency 】  3、分割和异步解决性能问题【Asynchrony Everywhere】  4、自动化降低人力成本【Automate Everything】  5、产品化管理  eBay架构经验:  1、Partition Everything 【分布式】  2、Asynchrony Everywhere 【异步化】  3、Automate Everything 【自动化】  4、Remember Everything Fails 【避免单点:1增加冗余;2层次化】  5、Embrace Inconsistency 【弱一致性】  6、Expect (R)Evolution 【演化而非革命】  7、Dependencies Matter 【依赖关系】  8、Be Authoritative 【?权威】  9、Never Enough Data 【?】  10、Custom Infrastructure 【定制基础架构】  参考:  http://www.dbanotes.net/arch/taobao_arch.html 来自淘宝的架构经验
  77. 77. 77 *参考:淘宝经验(Session和CAP)  问题1:巨量用户会话保持的四个方式:  1.粘性session 【一个用户的session保持在同一台机器上】  可能买家和卖家有交互,不利于通信,  下次再次登陆,还得是原来的机器,不利于负载均衡;  2.session复制【将session复制到多个机器,一致性差】  3.集中式session 【服务器压力大】  4.不用session改写cookie 【有些信息无法写在cookie】  cookie < sessionid = 1234  cookie < sessionid = mcache://domain:port/path/1234.ext  注:淘宝采用的是3和4相结合的方案  问题2:关于CAP优先级问题(淘宝)  支付业务:(C>A>P)优先一致性,其次可用性,最后关注分片。  读写分离:主库Oracle,从库Mysql,跨DB复制技术。  应用拆分:隔离非关键应用和非关键数据。  参考:  http://blog.hjenglish.com/eshow/articles/1493835.html 2009的SD2.0大会见闻
  78. 78. 78 参考:开源C-JDBC概念0  综合方案1:定制jdbc驱动;定制jdbc服务;  Sequoia是c-jdbc项目的延续(因和SUN的jdbc商标冲 突而改名),该项目发端于INRIA(法国国家计算机和 自动化研究院)的sardes项目。2003年提出了RAIDb的 概念,并开发c-jdbc作为软件实现,RAIDb借鉴了RAID 的思想,采用灵活的数据库复制技术和集成中间件, 以廉价、异构的数据库构建冗余数据库集群,从而提 供高可扩展、灵活的高性能集群。  参考  http://c-jdbc.ow2.org/ HA DB clusters with JDBC(已 改名Sequoia 2.10.10 http://sequoia.continuent.org  http://linux.softpedia.com/progDownload/Sequoia- Download-477.html下载  http://forge.continuent.org/jira/browse/SEQUOIA 问题,代码库:cvs -z3 - d:pserver:anonymous@sequoiadb.cvs.sourcefo rge.net:/cvsroot/sequoiadb co -P modulename )  http://liuye.javaeye.com/blog/224496 异构数据库中间 件sequoia(c-jdbc)初体验  http://www.continuent.com/community/lab-projects/ sequoia Important Update on Sequoia  Note: Sequoia is no longer actively developed or supported by Continuent. Our main open source project is Continuent Tungsten. Please consider Continuent Tungsten as an alternative.  It is important to understand that Sequoia has a number of trade-offs that limit its usefulness because of the performance impact and lack of application transparency. Tungsten processes updates more quickly, handles a wider range of SQL, works over a WAN, and permits direct database access without proxies.
  79. 79. 79 参考:开源c-jdbc概念1  RAIDb  RAIDb concept  Redundant Array of Inexpensive Databases  RAIDb controller  gives the view of a single database to the client  balance the load on the database backends  RAIDb levels offers various tradeoff of performance and fault tolerance  RAIDb levels  RAIDb-0 【分区】  Partitioning  no duplication and no fault tolerance  at least 2 nodes  RAIDb-1 【镜像】  mirroring  performance bounded by write broadcast  at least 2 nodes  RAIDb-2  partial replication  at least 2 copies of each table for fault tolerance  at least 3 nodes SQL requests RAIDb controller table 1 table 2 & 3 table ... table n-1 table n SQL requests RAIDb controller Full DB Full DB Full DB Full DB Full DB SQL requests RAIDb controller Full DB table x table y table x & y table z
  80. 80. 80 参考:开源c-jdbc概念2  RAIDb  RAIDb levels composition  RAIDb-1-0  no limit to the composition deepness  C-JDBC  overview  Middleware implementing RAIDb  100% Java implementation  open source (LGPL)  Two components  generic JDBC driver (C-JDBC driver)  C-JDBC Controller  Read-one, Write all approach  provides eager (strong) consistency  Supports heterogeneous databases 【异构DB】 RAIDb-0 controller table w table x & y SQL requests RAIDb-1 controller table z RAIDb-0 controller table w table y RAIDb-0 controller table x table y table z table x & z table w
  81. 81. 81 参考:开源HA-JDBC  特性  支持任何通过JDBC的数据库访问。  高可用性/容错  其集群可关闭某个节点而不破坏一个的事务。  允许热激活或关闭某数据库节点,而不丢失服务。  运行时加减数据库节点的能力。  能被配置为自动失败激活数据库节点  通过分布式各个节点提高并发的读性能。  完全支持JDBC 3.0 and 4.0功能集。  利用数据库无关的策略同步一个失败的数据库节点  通过暴露JMX管理接口来管理数据库和集群。  使用LGPL开源协议。  依赖库  JGroups - 可靠的广播通信框架  Quartz - enterprise job scheduler  JiBX - an XML binding framework  SLF4J  参考:  http://wutaoo.javaeye.com/blog/146982 介绍(图)  http://ha-jdbc.sourceforge.net/faq.html#faq- N1010F How does HA-JDBC compare to Sequoia?
  82. 82. 82 参考:开源HadoopDFS  Hadoop  HDFS具有高容错性。  HDFS适合大数据集应用,并且提供了对数 据读写的高吞吐率。  HDFS是一个master/slave的结构  在master上只运行一个Namenode  在每个slave上运行一个Datanode  HDFS支持传统层次文件组织结构。  Namenode管理着整个分布式文件系统。  HDFS采用三副本策略。  一个放在本节点上,  一个放在同一机架中的另一个节点上,  一个副本放在另一个不同的机架中的一个 节点上。  参考:  http://www.cnblogs.com/wayne1017 /archive/2007/03/18/668768.html Hadoop学习笔记  http://www.blogjava.net/killme2008/ archive/2008/06/05/206043.html HadoopDFS架构和设计要点
  83. 83. 83 参考:开源DataNucleus架构  参考:  http://code.google.com/intl/zh-CN/appengine/docs/java/overview.html GAE for Java  http://www.datanucleus.org/products/accessplatform/architecture.html DataNucleus
  84. 84. 84 +参考:MySql-Proxy读写分离  参考:http://jan.kneschke.de/2007/8/1/mysql-proxy-learns-r-w-splitting/  读写分离认证模式
  85. 85. 85 参考:开源Amoeba  服务端方案1(自定义服务接口)  数据中心也是一种服务。  通过DAL服务访问数据,无需jdbc。  实现类似以前DbServer之类的服务。  服务端方案2(基于JDBC通信接口)  http://amoeba.meidusa.com/ Amoeba  Amoeba for MySQL【仅MySQL,性能较高】  Amoeba for Aladdin【任意DB,性能稍差】  参考:  http://www.infoq.com/cn/articles/inter view-chensiru-amoeba 专访开源项目 Amoeba架构师陈思儒  http://hi.baidu.com/zeorliu/blog/item/ e0f315d12a15dfd5572c84be.html 试用 log4jdbc监控SQL的执行情况(zt)+开源项 目Amoeba
  86. 86. 86 参考:手机之家DAL  http://www.javaeye.com/wiki/interview/1931-data-access- layer 采访分布式数据访问层(Data Access Layer) 作者许超前  http://www.longker.org/ 许超前博客

×