论坛首页 Java企业应用论坛

关键字:查询,事务,粒度

浏览 23120 次
该帖已经被评为良好帖
作者 正文
   发表时间:2008-08-27  
ab -c 100 –n 1000 http://xxxx.xxx.xxx/xxx
这个测试是怎么做的,用工具吗?

在回复中找到了!
0 请登录后投票
   发表时间:2008-08-27  
apache 装上就有了
0 请登录后投票
   发表时间:2008-09-01  
楼主,你没发现你这个getObject方法本身就是一个错误么?而你却把这个方法代码级的错误延伸到事务上去了,佩服佩服。。。。。

首先,你这个方法的正确逻辑应该是第一次执行时,缓存中没有数据,然后从数据库中去查数据并放入缓存。之后的方法执行都会直接从缓存中获得数据。也就是说,应该只有一个connection对象会被使用一次。而你得出的结论确实有多个connection被使用。你不觉得这首先就是你方法的代码级别出现了错误,造成了这个后果么?

再看代码。因为没考虑到并发问题,你这个方法代码在多线程情况下,明显会造成多次重复的查询数据库,而这个查询数据库的动作原本只应该执行仅一次而已。

建议你换个方法来诠释你的主题。这个getObject方法明显不适合你这个主题。你要对这个方法里的ObjectDao.getfromDB方法进行封装,最好是封装成一个FutureTask,直接利用FutureTask的get方法来获得并发时的阻塞效果,防止多次重复执行查询数据库。
0 请登录后投票
   发表时间:2008-09-01  
wym0291 写道
楼主,你没发现你这个getObject方法本身就是一个错误么?而你却把这个方法代码级的错误延伸到事务上去了,佩服佩服。。。。。

你从什么地方看出来这个getObject方法本身是错误的????
错在哪里,我也挺佩服你的,大家都没有看出来,就你看出来了.

wym0291 写道
首先,你这个方法的正确逻辑应该是第一次执行时,缓存中没有数据,然后从数据库中去查数据并放入缓存。之后的方法执行都会直接从缓存中获得数据。也就是说,应该只有一个connection对象会被使用一次。而你得出的结论确实有多个connection被使用。你不觉得这首先就是你方法的代码级别出现了错误,造成了这个后果么?

从你这段话里可以看出来你还不明白我在说什么,我很少用"建议"这个词,因为这让人有种据高凌下的感觉,但是我真的建议你再把文章看两遍



wym0291 写道

再看代码。因为没考虑到并发问题,你这个方法代码在多线程情况下,明显会造成多次重复的查询数据库,而这个查询数据库的动作原本只应该执行仅一次而已。

这里即使有产生并发,最多就是多查两遍数据库, 查完之后就不会再查了,显然这个是小问题,因为这并发的几次查询都是一样的数据.如果加同步,那么不管是查数据库还是缓存都有锁的开销,显然我的选择是在真正并发的时候拿掉锁,宁可多查两遍数据库
0 请登录后投票
   发表时间:2008-09-01  
ahuaxuan 写道
wym0291 写道
楼主,你没发现你这个getObject方法本身就是一个错误么?而你却把这个方法代码级的错误延伸到事务上去了,佩服佩服。。。。。

你从什么地方看出来这个getObject方法本身是错误的????
错在哪里,我也挺佩服你的,大家都没有看出来,就你看出来了.

wym0291 写道
首先,你这个方法的正确逻辑应该是第一次执行时,缓存中没有数据,然后从数据库中去查数据并放入缓存。之后的方法执行都会直接从缓存中获得数据。也就是说,应该只有一个connection对象会被使用一次。而你得出的结论确实有多个connection被使用。你不觉得这首先就是你方法的代码级别出现了错误,造成了这个后果么?

从你这段话里可以看出来你还不明白我在说什么,我很少用"建议"这个词,因为这让人有种据高凌下的感觉,但是我真的建议你再把文章看两遍



wym0291 写道

再看代码。因为没考虑到并发问题,你这个方法代码在多线程情况下,明显会造成多次重复的查询数据库,而这个查询数据库的动作原本只应该执行仅一次而已。

这里即使有产生并发,最多就是多查两遍数据库, 查完之后就不会再查了,显然这个是小问题,因为这并发的几次查询都是一样的数据.如果加同步,那么不管是查数据库还是缓存都有锁的开销,显然我的选择是在真正并发的时候拿掉锁,宁可多查两遍数据库


我之所以说错误,就是你的代码没有实现你的设计目的。我用建议只是因为你的帖子刚开头就让人看到一段有问题的代码,实在让人感觉有点草率。

.....很明显,你对并发问题一点不敏感,从你回答中也可以看出,你对如何解决这种并发也是知之甚少。上面我已经提过了可以提供类似FutureTask来构建一种基于任务的阻塞,你估计连查都没查一下这种方法的使用,就来谈开销。还说最多就是多查两便数据库。。。。。你还是去实践一下,你就测下100个并发,看看到底查了几次数据库,看了结果我想你就不会说的这么轻松。

还有一点,在你最后的回复中也体现了你对缓存使用的不明确。为什么你要使用缓存来避免数据库的操作?很多时候是因为数据库查询的开销很大。而你却忽视这种开销,说是选择拿掉锁。在真实环境中,面对这种开销很大的数据库操作,你的代码很可能就造成一次资源占用的峰值,带来的连锁反映也可能是致命的,对企业来说就是钱的问题。

最后的结果可以预料。开销大的数据操作,在很多并发的情况下,几乎同时执行了大量并发数据库操作,后果不用说了吧。。。。
0 请登录后投票
   发表时间:2008-09-02  
wym0291 写道
楼主,你没发现你这个getObject方法本身就是一个错误么?而你却把这个方法代码级的错误延伸到事务上去了,佩服佩服。。。。。

首先,你这个方法的正确逻辑应该是第一次执行时,缓存中没有数据,然后从数据库中去查数据并放入缓存。之后的方法执行都会直接从缓存中获得数据。也就是说,应该只有一个connection对象会被使用一次。而你得出的结论确实有多个connection被使用。你不觉得这首先就是你方法的代码级别出现了错误,造成了这个后果么?

再看代码。因为没考虑到并发问题,你这个方法代码在多线程情况下,明显会造成多次重复的查询数据库,而这个查询数据库的动作原本只应该执行仅一次而已。

建议你换个方法来诠释你的主题。这个getObject方法明显不适合你这个主题。你要对这个方法里的ObjectDao.getfromDB方法进行封装,最好是封装成一个FutureTask,直接利用FutureTask的get方法来获得并发时的阻塞效果,防止多次重复执行查询数据库。

高手,我理解你的意思了
0 请登录后投票
   发表时间:2008-09-02  
wym0291 写道

我之所以说错误,就是你的代码没有实现你的设计目的。我用建议只是因为你的帖子刚开头就让人看到一段有问题的代码,实在让人感觉有点草率。

.....很明显,你对并发问题一点不敏感,从你回答中也可以看出,你对如何解决这种并发也是知之甚少。上面我已经提过了可以提供类似FutureTask来构建一种基于任务的阻塞,你估计连查都没查一下这种方法的使用,就来谈开销。还说最多就是多查两便数据库。。。。。你还是去实践一下,你就测下100个并发,看看到底查了几次数据库,看了结果我想你就不会说的这么轻松。

还有一点,在你最后的回复中也体现了你对缓存使用的不明确。为什么你要使用缓存来避免数据库的操作?很多时候是因为数据库查询的开销很大。而你却忽视这种开销,说是选择拿掉锁。在真实环境中,面对这种开销很大的数据库操作,你的代码很可能就造成一次资源占用的峰值,带来的连锁反映也可能是致命的,对企业来说就是钱的问题。

最后的结果可以预料。开销大的数据操作,在很多并发的情况下,几乎同时执行了大量并发数据库操作,后果不用说了吧。。。。


楼主只是拿一段sample代码来说明一下查询事务的粒度问题,和并发的关系并不是很大。

你既然那么关心并发问题,那么请拿出代码来解决问题。莫非你所有的查询操作全都是做同步处理的?
0 请登录后投票
   发表时间:2008-09-02   最后修改:2009-03-17
wym0291 写道

首先,你这个方法的正确逻辑应该是第一次执行时,缓存中没有数据,然后从数据库中去查数据并放入缓存。之后的方法执行都会直接从缓存中获得数据。也就是说,应该只有一个connection对象会被使用一次。而你得出的结论确实有多个connection被使用。你不觉得这首先就是你方法的代码级别出现了错误,造成了这个后果么?

我很奇怪,你怎么不正面回答我的问题呢,我说你上面这段话是错误的,你怎么不响应,反而转移话题呢,搞不懂。

wym0291 写道

我之所以说错误,就是你的代码没有实现你的设计目的。我用建议只是因为你的帖子刚开头就让人看到一段有问题的代码,实在让人感觉有点草率。


这段话就更搞笑了,我在文章中说得非常清楚,这是一段伪代码,代表一段业务逻辑,你有见过这种java代码吗。


wym0291 写道

.....很明显,你对并发问题一点不敏感,从你回答中也可以看出,你对如何解决这种并发也是知之甚少。上面我已经提过了可以提供类似FutureTask来构建一种基于任务的阻塞,你估计连查都没查一下这种方法的使用,就来谈开销。还说最多就是多查两便数据库。。。。。你还是去实践一下,你就测下100个并发,看看到底查了几次数据库,看了结果我想你就不会说的这么轻松。

这段我就更无语了,不知道从哪里看出来我对并发问题不敏感了,还我对并发知之甚少,你至少也要知道我才能下结论吧,从一句话就看出来了,我看你比较喜欢妄结论。

先不说这段代码是否有锁的问题(因为它本身只是伪代码,代表我们的业务逻辑而已)即使直接在方法上加锁也是没有关系的,根本用不着futuretask,因为只有很少的线程会被阻塞,什么时候阻塞呢,就是在查db,放memcached的时候阻塞,一旦这个操作完成,其他请求的线程根本不需要等多长时间,所以直接在方法上加同步就行了,如果该类的其他方法用到这个锁,那么使用锁分离技术,在这个方法上加其他锁就可以了,问题其实很简单啊。

为什么说在这个方法上加同步是没有问题的,我详细阐述一下:
首先这个方法有一个getfromdb操作,耗时大概15毫秒,有一个getfromcache操作,耗时不到1毫秒,而getfromdb只需要一次,也就是说在其后的请求中,这个方法大概就是1-3毫秒可以搞定,这个方法时非常非常的快,阻塞其他请求线程的几率非常的小,为什么这么说,因为tomcat并发能力本来有限,比如我们预定是1000/s的话,我一个请求方法消耗在3毫秒,网络消耗在100毫秒,那么线程直接阻塞的情况几乎没有可能发生,即使发生一两次也根本没有问题,不会影响全局。所以说你说的futuretask是多次一举


wym0291 写道

还有一点,在你最后的回复中也体现了你对缓存使用的不明确。为什么你要使用缓存来避免数据库的操作?

我对缓存的使用不明确?唉,这一点让看的贴的人去评断吧。

补充:如果想知道我对缓存的使用是否明确,请看这个帖子:

引用



引用


最后的结果可以预料。开销大的数据操作,在很多并发的情况下,几乎同时执行了大量并发数据库操作,后果不用说了吧。。。。


我可以很负责任的告诉你,这段代码跑的很好,而且我很负责任的告诉你,这个系统并发很大,8台tomcat撑着呢,看看,是不是又妄下结论了?

-----------------------------------------------------
引用
建议你换个方法来诠释你的主题。

其实你还是不明白本文的主题是什么,本文主题是事务的问题,并不是锁的问题,你一个劲的在说锁,可见你不知道事务才是本文的主题,而恰恰你在这点上的观点是错误的,你居然认为这个方法在并发的事务环境中只用了一个connection
0 请登录后投票
   发表时间:2008-09-02  
其实,楼主的逻辑确实有错误,wym0291说的也没错。
楼主这个例子虽然不是太恰当,但也确实说清楚了要表达的观点。
但是wym0291说的是有道理。至少理论上我这么认为。
而且你说的在方法上加锁可以,因为你的getFromDb方法只需要15毫秒。但是如果你这个getFromDb方法要抓的数据量很大呢,可能远不止15毫秒吧。不过只要你自己对自己这个方法了解,那加锁没有问题。

还有,他不是认为你的方法只使用了一个connection,他的意思是正确的方法(或者说正确的业务逻辑)应该只使用一个connection.
0 请登录后投票
   发表时间:2008-09-02  
terranhao 写道
其实,楼主的逻辑确实有错误,wym0291说的也没错。

请问那段伪代码中的业务逻辑错在哪里?
我希望你在指出别人有错误的同时能阐述错误在哪里,可以吗。


wym0291有没有说错大众自有评断,你仔细看我在上上楼对他的话的点评了吗,就这样还没错?我无语了

terranhao 写道


还有,他不是认为你的方法只使用了一个connection,他的意思是正确的方法(或者说正确的业务逻辑)应该只使用一个connection.

wym0291 写道

首先,你这个方法的正确逻辑应该是第一次执行时,缓存中没有数据,然后从数据库中去查数据并放入缓存。之后的方法执行都会直接从缓存中获得数据。也就是说,应该只有一个connection对象会被使用一次。而你得出的结论确实有多个connection被使用。你不觉得这首先就是你方法的代码级别出现了错误,造成了这个后果么?


我把你们的两段话放在一起,你自己看吧,明明是事务粒度的问题,居然说到代码级别的错误上去了,我还能说什么呢。

看我红色标注的地方,尤其是“而你得出的结论确实有多个connection被使用”,但是事实上就是如此啊。这完全就是一个事务粒度的问题,我很期待你拿出你的正确的代码来证明你的观点
0 请登录后投票
论坛首页 Java企业应用版

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