一个缓存应用场景,希望大家进来讨论下

10-11-01 flylampard
有一个这样的场景,用户鼠标在页面上点击一个动作,反应到后台可能需要update多张表信息。当数据比较多,和并发上去了。可能会让数据库的压力比较大。所以这里我想到了缓存。因为以前比较少接触到这方面的知识。所以来jdon向大家求教。我看了一上memcached的一些资料,大部分的同学都说在单台服务器上可能效果并没有那么明显(因为我们现在的应用只会发在单台服务器上)然后还有一些问题没有想明白。我的问题如下:

1、这种场景什么样的缓存框架或者缓存架构比较适合

2、因为用户的点击可能是引发的数据update当内存的信息update后,缓存框架(比如memcached好了)在自动update到数据库这个环节中需要注意哪些问题。

3、正常关闭服务器的时候,缓存是怎么样处理,是不是需要自己去监听容器关闭事件。然后再把数据同步到DB

希望对这方面有经验的同学能讨论下给些建议。banq老师请赐教啊^_^。希望能在jdon不断学习。。

[该贴被flylampard于2010-11-01 01:49修改过]

[该贴被flylampard于2010-11-01 01:49修改过]

1
ronalfei
2010-11-01 10:13
很容易吧.很多方法可以选择呢.

最容易实现的就是把sql写成文件,通过异步导入的方式就可以减轻数据库压力了.

要不就通过一个消息队列来实现.消息队列服务器的选择就多了.

无论是什么方式,他们都是异步的,相对于客户端就无阻塞的.

而你提到的memcache是不适合这样的场景的..

我不是搞java的,只能说那么多了.

flylampard
2010-11-01 11:58
放到这种队列中进行异步处理可能不太适合。因为我这需要立即看到效果,最好不能超过2S以上的延迟。。

flylampard
2010-11-01 12:07
我在描述详细点吧。应用是一个web game.所以不能有太延迟的现象。。昨天晚上还看到banq的一个贴子。中间提到EHCache的单机缓存能力很好。。那么我的疑问又出现了。像memcached它是开启一个新的守护线程。那么EHcache可能要伴随容器。那么比如tomcat最大支持的内存可能只有几G。那么EHCache就要分走一部分。而memcached这种是用的机器的内存。当然这个并不是问题。只是我的一个想法而以。

banq
2010-11-01 12:15
2010年11月01日 01:36 "flylampard"的内容
反应到后台可能需要update多张表信息。当数据比较多,和并发上去了。可能会让数据库的压力比较大。 ...

就这个简单功能,可以使用AJAX异步和后台异步架构,具体源码可以见JiveJdon中阅读次数的更新这一功能,具体文章:以JiveJdon案例说明对象职责和SOLID原则应用

简单来说,对于更新来说,使用mongoDB这些NOSQL比memcached要好,因为你是写,不是读。

flylampard
2010-11-01 13:48
2010年11月01日 12:15 "banq"的内容
...

谢谢banq.我刚才研读了下修改阅读数这个地方的代码,应该是ThreadViewCountManager这个类里的initViewCounter方法。里面的逻辑是先用一个ConcurrentHashMap来缓存进来的update任务。然后用thread去跑。然后慢慢的去write。 不知道我有没有理解对。

说实话 我以前也想过这个解决方案。之前的一个项目也是这样做的。只是形式上有一点点不一样。。

总之。谢谢banq的提点。这下豁然开朗了。这是一条路子。会去尝试解决这个问题。关注jdon2年多了。终于有机会问问题了。以前只是学习。。^_^

flylampard
2010-11-01 14:03
2010年11月01日 12:15 "banq"的内容
具体源码可以见JiveJdon中阅读次数的更新这一功能 ...

但有一点还不太明白。。在代码中

public void initViewCounter(ForumThread thread) {

Long threadId = thread.getThreadId();

ViewCounter viewCounter = thread.getState().getViewCounter();

viewCounter.getLock().writeLock().lock();

try {

int count = -1;

ViewCounter viewCounterOld = concurrentHashMap.get(threadId);

if (viewCounterOld == null) {

count = getFromDB(threadId);

} else

count = viewCounterOld.getViewCount();

thread.setViewCount(count);

concurrentHashMap.put(threadId, viewCounter);

} finally {

viewCounter.getLock().writeLock().unlock();

}

}

这个方法中。。concurrentHashMap 本身是线程安全的,这里为什么还要加锁来控制。。还有一个saveItem也就是把这些数据更新到DB中也有锁的控制

flylampard
2010-11-01 18:10
2010年11月01日 12:15 "banq"的内容
就这个简单功能,可以使用AJAX异步和后台异步架构,具体源码可以见JiveJdon中阅读次数的更新这一功能 ...

刚才研读 “以JiveJdon案例说明对象职责和SOLID原则应用” 中间提到论坛帖子的阅读数是不是那么核心影响论坛整体功能的一个值。。

我的这个场景就是修改的这个值是比较重要,出现差错就会地客户带来损失。这个地方不知道大家还有没有一些建议。

fw2003
2010-11-03 11:48
感觉如果用户对数据的实时性以及响应性要求高的话

LZ的这个问题可以:

1.将需要展现的数据缓存起来,先更新内存中的对象以便用户能够立即看到结果

2.后台异步开启线程做数据库的写操作,将内存中的对象同步到数据库

3.如果失败,回滚事务并恢复内存中的对象(重新从数据库中查询1次获取更新前的数据并同步到内存),当然如果使用SPRING的话,也可在出现异常后自动重试事务

[该贴被fw2003于2010-11-03 11:52修改过]

猜你喜欢