MDA/MDD/TDD/DDD/DDDDDDD
posts - 536, comments - 111, trackbacks - 0, articles - 0
  BlogJava :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理

Case1-分库分表-传统关系数据库(转)

Posted on 2011-07-10 00:24 leekiang 阅读(851) 评论(0)  编辑  收藏 所属分类: 架构设计
firebody 写道:
java 代码
 

   1. 以前用hibernate主要是做一些表的映射、关联,更深层的应用就没有了,所以也没什么经验,拿个具体的情况来分析一下吧。   
   2.   
   3. 目前主要数据库是mysql,由于数据库存储限制:   
   4. 1、通常会把用户名和密码放一个库(负载相对较少,但也要依赖cache)。   
   5. 2、用户基本资料拆开多台DB按用户名或ID hash,用户扩展信息也拆开多台。   
   6. 3、用户积分因为太敏感,甚至使用了oracle来保证效率和稳定性(事实证明它比mysql慢。。它的C++绑定也更不稳定)。   
   7. 4、用户发帖是保存在文件的,数据库只保存文件链接发帖人等简单信息。   
   8. 5、用户之间的消息是放数据库的,当然也是按用户名hash到多台,这时候要查询我给别人的消息和别人给我的消息,就得从2个表里面查,因为你给别人的消息是按别人的用户名hash到某一台上,别人给你的是按你的用户名hash的,所以增加一条消息就得往2个库各写一条。   
   9.   
  10. 以上列举了一部分应用,当然由于库拆得比较散,基本上每个库都会有冗余字段。   
  11.   
  12. 上面这种情况下,能不能分析一下hibernate和ActiveRecord用得比较舒服的部分?   
  13.   
  14. 我在用rails的时候,ActiveRecord对于多数据库支持并不好,即使是有这样的方案也是非方的技巧。分表情况下表之间的关联基本上没法做,如果没有关联,ActiveRecord的意义只是帮我们生成SQL?   
  15.   
  16. 多级目录不是最大的问题,也不是阻碍性能的问题,俺只想找个最后的理由把RoR不适用这个项目说得更充分些。。。  

 

谢谢你能够提供更多的信息来参与讨论, 针对你提到的2),这样的情况下,按照我的理解,现有的java的orm框架无法针对不同库的表作映射。 activeRecord应该也没有考虑到这种情况。

不知道你们作出的分库的依据是什么,我觉得更合理的分库依据应该根据负载压力和模块独立性来分离,比如你提到的消息发送应该是统一的模块,按照用户名hash到不同的库的话,对于业务层开发带来一定的复杂度。

分表的话,java的orm有些策略可以绕着解决,比如用继承策略来解决。但是也是比较别扭。 不过,我更想了解的是你们作出的分表的依据是什么?

这样的情况下,模型的关联映射在现有的orm框架下确实太牵强了,即使用了,收到的效果也是很小的,模型也会随之退化到单实体+基本类型外键的维护上来,如果让我选择的话,基本上也是选择spring的jdbcTemplate了。

如果觉得java orm是促进开发效率的一个基本前提的话,那么在系统架构选择上,特别是数据库架构设计上,可能还要更慎重一些,因为不同于数据库底层开发,orm对于数据库的要求会有一些苛刻。为了最大化获得模型映射的效果,有一些建议不知道是否合理:

*  在考虑访问压力的情况下,尽量按照耦合紧密的原则分库,使得某一个库的表关联能够作充分的模型映射,而对于少数的外库关联仍然需要做手工的维护,不过已经简化到最小。

*  因为数据量大而分表的话,可以采用多态映射关联来做和多表的关联。


基本上分库主要原因都是和容量或性能有关,上亿用户,每个用户只保存一个用户名和密码,也有好几G的数据。

为了登录部分效率考虑,用户名和密码拆到一个库中,因为这部分读取并不是特别频繁,所以目前用主备方式,备的目的是主挂掉至少不会让用户无法登录,顶多无法注册而已。

用户的基本资料字段是固定的,但容量有些大,访问也比较频繁。之前用户没有中间层,所以拆库来提高效率。现在有中间层,拆库的意义也变了,领导不希望任何一台机器故障影响到所有用户,影响部分用户还是勉强可接受的。实际上随着用户的不断增加,即便是使用中间层也会有压力,毕竟中间层只是帮数据库挡了读取的压力,而读写比例通常情况下是10:1左右。

用户扩展信息,这个是一对多的,一个用户可自定义不同的字段,通常是用户有修改时更新一下,读取压力并不大,同样是因为中间把把读取压力都挡掉了,但容量非常大。

当然也考虑过如果有中间层,是不是数据库不用拆得这么细,目前也做过一些合并工作,不过意义并不大,因为所有数据库容量加起来以T计,不管是备份还是扩容甚至修复硬件故障都会影响用户很长时间,现在拆得这么细,通常一个点的故障只会影响一部分用户的一部分功能。目前硬件故障还是会经常有的,比如某国外品牌的服务器故障率非常高。扩容也是经常会有的,文件每天上传量就超过2T,每月都增加存储。数据库差不多每3月-6月都要重新拆分一次,因为容量。


分库分表最佳实践大总结
一、随着企业业务的增长,访问量和用户等数据的增加,传统的关系数据库已经不能满足需求

分表分库就成了节省成本、和良好扩展性的必然选择

网上也有很多开源的分表分库的软件,也公司自己开发实现

而终其原理和步骤都无外乎三步:

  即首先sql解析路由,再根据路由确定分片,然后结果集合并

  所遇到的分表分库的难点大都是对分布式事务的支持分片后的分页

和排序


二、实现方式大都在两个层面:

即在应用层 代表有hibernate shards,ibatis shards,guzz

和 在jdbc之下 对应用层完全透明的 如amoeba


三、那么企业在分表分库的实践中该如何选择呢?

假如您是一开始就想全新的分表分库 公司没打算做自己的分表分库框架,那么推荐用guzz,

这个类似于hibernate 和 ibatis的框架,很多网站都在用,缺点是技术团队需要重新学习一套框架

跟旧的系统很难兼容;


假如您的系统很乱,分表分库规则很简单,并且数据库是mysql

推荐用amoeba ,虽然有oracle版本,但目前不是很成熟;


假如您的技术团队一直用hibernate ,或企业现在的很多项目现在都用hibernate做的

那么推荐用hibernate shards,这个类似hibernate,学习成本低,能跟

hibernate兼容

目前国内有在hibernate  shards上封装的成功案例,

缺点是list查询时遍历所有数据片,而不是根据sql规则确定的数据片。

这个bug及在hibernate shards上如何扩展问题我已解决,附件是解决的架构图,

需要源代码的或详细可以联系我;


ibatis shardshibernate shards类似,也可借鉴本人所设计的架构

思想 欢迎有志之士详聊


附:
一、hibernate shards
优点:
1、实现跟其他成熟框架的集成如spring

2、能利用公司现有的hibernate的技术优势
3、目前国内有成功案例在hibernate  shards上封装
的商业软件
4、能够快速开发
缺点:
1、暂不支持垂直分区
2、list查询遍历所有表分片


只有注册用户登录后才能发表评论。


网站导航: