论坛首页 Java企业应用论坛

关于系统性能的思考

浏览 27535 次
精华帖 (12) :: 良好帖 (3) :: 新手帖 (7) :: 隐藏帖 (0)
作者 正文
   发表时间:2009-05-07  
icewubin 写道
狂放不羁 写道
1 RDBMS有坚实的数学理论基础。相反的面相对象的数据库在数学理论方面欠缺。还有您推荐的<<pojo in action>>以前看过但是没看完,最近在看。个人觉得很多和POEAA很像,也可以说是POEAA的实践版本。

2 缓存和数据库确实不是一个级别,JVM也确实有限制,但是之所以叫缓存那就是暂时存储一部分数据,大小限制也没事,只是一部分,不是全部。

3 缓存同步确实是存在问题,但是session同步也存在严重的问题,我说缓存一方面集群环境下是减少session同步问题,如果不集群的情况下,缓存可以减少数据库操作。比如tomcat那种多机备份策略,同步更加有问题。而对于分布式缓存的同步由分布式缓存系统来完成。其它的应用服务器采用不同的策略,以前看过TSS上一篇文章,揭开J2EE集群神秘面纱,写的很好。


4 hibernate缓存我也不喜欢使用,除了一些不常变化的数据,比如一些地址等的信息。我一般是以前在service层通过开源的缓存系统,通过拦截器或者代理模式来做缓存,并且目前我做的一个项目是通过Repository(DDD概念)和builder模式控制了缓存。

5 正是您所说的不是每个项目都适合SNA的,这里的缓存也可以是SNA中那种缓存服务器的缓存,也可以采用jbosscache torrecotte等分布式缓存系统


6 这样主要是减轻了hibernate向RDBMS映射的痛苦(尤其是业务对象设计的关联比较多的时候,每次hibernate都要生产N多sql。


7 现在开源的缓存系统有很多,我并没有自己开发分布式的缓冲,只是通过封装好的业务对象模型来实现状态的并发更新,所以我说面向对象的设计不仅对于设计一个好的对象模型很重要,同时对于设计对象模型的缓冲也很重要,一个没有经过良好设计的,状态到处暴漏的丑陋的模型,即使用了缓存,也是自找苦吃,状态并发更新的情况下,头痛死了。对于并发编程方面,我个人比较推荐<<java 并发编程实践>>

8 在数据库集群的时候也存在同样的问题。

1.pojo in action中的离线悲观锁,看一看,很有意思的。

2.对呀,既然暂存一部分数据,必然有缓存失效的问题。
缓存作为生存空间,这不就是相当于自己另外造了一个ORM么?只不过你认为Hibernate让你不满意而已。
我总感觉楼主的缓存概念太局限在JVM中了,前台squid+memcached的页面缓存结构和后台的数据库如何做缓存的都应该适当了解一下。

3.问题就是,你认为单机的结构,能够很顺利的迁移到多机的,基于分布式缓存系统的框架下,这个愿望是美好的,实际操作却是非常痛苦的。自己造这种级别的轮子是需要很多的实战经验的,例如单例模式的陷阱等等。

6.Hibernate映射RDBMS不需要很痛苦,简单映射,不使用高级功能,仍然面向过程好了,pojo in action中的script pattern没什么不好啊,java不太适合充血模型的,大多还是写在Service中的Script Pattern而已。

我发现楼主不太了解Hibernate,虽然hibernate达不到你理想中的ORM,但是在一个事务中,合理的编程,Hibernate也是不会触发多余的sql,实际上在尽量不触发sql上,Hibernate是做了大量的工作的。而你说Hibernate会触发大量的sql,我只能说你们使用上有问题。

而由于这个原因使得你期望重造轮子,唉。。。

7.恩?两个问题,第一,同一个JVM中的并发编程,和多台机器中不同的JVM中的程序互相通讯是两码事吧,<<java 并发编程实践>>帮不上太多的忙吧。第二,多台机器之间的通讯(即使是建立在成熟的分布式缓存产品之上),实际的调试和测试成本仍然是高得惊人。
恩。。。你是单机吧,第二点我说了没啥用,这样说好了,单击情况下,假如我用SSH做项目,一般不会有并发问题的,是不是因为你自己在造ORM工具这个大轮子的时候,碰到了很多并发问题呢?

8.数据库集群可以另开一个很大的话题了,这里不讨论。


哈哈,老哥上班时间满充足的。

1 正好还没看到这里哈。

2 缓存的有很多种,但是我这里的主要意思还是业务对象model缓存。

3 我和朋友现在自己接的一个项目打算实战一下分布式缓存,虽然钱少,但是主要是锻炼哈(台湾客户满扣的呵呵),还有那个单例模式,确实是的,单例是相对于类加载器的,我在我的另外一篇帖子里也说了这个问题。如果在采用EJB的情况下,web容器和ejb容器的类加载器体系很容易造成单例实例非单例。

6 java确实不太适合做富模型,但是就是我在实战中采用富模型的情况下,使用hibernate导致很多sql,并且hibernate要想往一个one-to-many的集合中增加数据,首先要取出所有的数据才能增加,这点不知道你有什么好的办法,我的解决方法目前都是设计到many一端数据太多的情况下,直接用jdbc操作了。

7 我其实没有自己制作ORM大轮子,重复发明轮子我也没有那个能力也不想。采用SSH开发,对于无状态的操作当然没有并发问题,但是一旦模型放到缓存中就有并发问题了,真正的业务模型对象是有状态的,并且状态很多,不变量约束有很多状态构成,这个时候就要求严格的面相对象的设计,封装非常重要。其实我所说的仅仅是利用已经有的轮子(开源缓存系统)和良好的面相对象设计来设计系统而已。

1 请登录后投票
   发表时间:2009-05-07  
ithero 写道

楼主不要见叶就是森林,至于你说领域模型举例那个Forum好像也是jdon中的例子。高性能高并发的应用设计。不是抽象几个概念就能解决的。不过下面大家的跟贴中部分牛人的思路很正。



对,jdon中的那个帖子也是我发的。
0 请登录后投票
   发表时间:2009-05-07   最后修改:2009-05-07
狂放不羁 写道
6 java确实不太适合做富模型,但是就是我在实战中采用富模型的情况下,使用hibernate导致很多sql,并且hibernate要想往一个one-to-many的集合中增加数据,首先要取出所有的数据才能增加,这点不知道你有什么好的办法,我的解决方法目前都是设计到many一端数据太多的情况下,直接用jdbc操作了。

看来楼主Hibernate实战经验不够啊。

Hibernate因为过于灵活,用法可以千奇百怪的,我只写一些个人观点:
1.因为关系型数据库的关系,不要过于幻想把Hibernate封装成完全OO的框架,只把他当成一个非常非常高级的SQL生成器是最好的方式,我是这么认为的。也就是说,你编程的时候,大脑中就是一条条sql,当然在我脑中是hql,我比较熟了(QBC、QBE、QBDC我都很熟)。

2.从细节上来讲,我不赞成配置一对多,基于使用EntityDao(单dao设计,这个EntityDao可以直接使用,也可以继承之后实例化),一句话就能轻易查询一对多的信息,没必要配置在映射配置中,我一般只在映射配置中放多对一的信息,其他的几乎都不使用,偶尔用用多对多(极少)。只要EntityDao设计的好,或者再做个父类,一般性的service编程(不需要DAO编程),已经很简单了,虽然是面向sql的编程,带一点点OO的样子。利用Hibernate的update和delete命令,完全可以自己封装出,既高效,又还算OO的操作方式。

其实数据库中并没有一对多的关系,硬是要那么操作,当然容易造成性能问题。以你说的一对多添加的例子,假设是小组中加个同学吧。
StudentService.java:
    public void insert(String groupId, Student student) {//假设ID是String的,之所以把这个参数单独传进来,往下看就知道了
        student.setGroup(new Group(groupId));//假设Group有这个构造函数
        studentDao.insert(student);
    }

这段代码其实是以同学为主导思想的,那个groupId这所以这样,主要目的是便于复用,只需要传一个groupId就行了,不会担心发生什么性能问题,这个方法确保只触发一条insert sql,而且还能减少web层编程的复杂度,web层对于小组信息只要获取一个groupId即可。(当然这里还隐含了“小组-同学”管理页面UI的设计问题,不同的UI操作方式对后台方法的需求也不太一样)

3.然后在POJO和VO(或者叫DTO)的选择上是2-8原则,大部分的业务操作,CRUD,pojo足够了,少部分的特殊操作,如复杂查询,则用VO来传递信息到web层。

4.从我对Hibernate的了解成来说,我认为你现在想解决的问题,hibernate的作者也想解决,但是因为关系数据库的问题,在实际实践中,碰到了很多阻力(所以Hibernate对处理某一种问题,往往提供了N多种的解决办法,这既是它的优点也是它的缺点,学习成本高啊),必须要自己掌握平衡点,做选择,例如一对多的思维方式用不用,二级缓存用不用、saveOrUpdate用不用,merge方法是否真的有必要等等。

hibernate对于对象状态的控制和对象图的控制其实已经还算不错了,不管你是否承认是否造轮子,我认为你很难做的封装能比Hibernate更好。
0 请登录后投票
   发表时间:2009-10-02  
我借此帖提出自己的疑惑。

在域模型中,缓存技术很重要,但是,我一直有一个不明白的地方,因为领域模型中一个Aggregate的生命周期基本上要靠Factory和Repository来控制,特别是后者。

那么,就是说,一个Aggregate的不论是根还是子对象更改之后,需要真正提交更新的时候是要通过Repository对一个Aggregate从头到尾完全遍历来进行具体的更新操作。所以,这时候使用Application的缓存,有一个问题就是,当多个线程同时修改同一个Aggregate的时候,如何做到线程安全,或者说,如何提供线程锁?

就如同LZ所说,如果对Value Object进行锁是很好,也是DDD作者提倡,但是,问题是加在那里?

我一直不太知道这两个问题的解决方法。有人告诉我对每一个线程创建一个新的Aggregate(缓存的话,应该是克隆),但是,这样子就是说,一个系统中会存在大量的拥有相同全局ID的Aggregate根对象,这是不是违反了DDD的基本原则呢?因为DDD书中明确标明,区别Entity的方法在于Identity而不是内存中的Reference(就是指针地址)。
0 请登录后投票
   发表时间:2009-11-25  
icewubin 写道


我发现楼主不太了解Hibernate,虽然hibernate达不到你理想中的ORM,但是在一个事务中,合理的编程,Hibernate也是不会触发多余的sql,实际上在尽量不触发sql上,Hibernate是做了大量的工作的。而你说Hibernate会触发大量的sql,我只能说你们使用上有问题。

而由于这个原因使得你期望重造轮子,唉。。。
。。。



同意楼上的观点,当系统有几十万甚至几百万代码的时候,不能指望所有的代码性能都是非常优化,并且协同工作时也是最优的。
这时用好hibernate不仅不会有多余的sql,而且比自己写的jdbc代码少很多倍的sql访问。hibernate的一级cache机制做得非常好的,很有用
0 请登录后投票
   发表时间:2010-01-14  

兄台讲的和  jforum 好类似。

0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics