请问一个如何设计Cache(要求提高搜索速度)的问题

banq以及各位高手.
我们现在在做一个关于ip系统方面的问题,我现在遇到一些问题
我们用的数据库是oracle9i,开发工具jboss,问题如下:
1.在访问数据库方面,由于数据库较大(如1000万条),我们设计连接数据库的最低层时需要设计3个方面的功能:Cache,connectionpool,query对于connectionpool和query具体用到哪些类,如何去设计我们还是很清楚的,到了如何设计cache(要求5秒钟内能搜索到1000万条数据库的信息)遇到这样一个问题,如何去设计这个框架

以下是我们初步设计的方案:
首先设计一个Timer,然后遍历每个连接的状态,再设计一个连接池,以此来当连接关闭之后,我们直接从连接池中删除临时数据.

connection pool 网上一大堆,很成熟的东西干麻要自己开发?
query 是什么东东?

如果设计目标是快速的从1000万里面搜索出符合条件的记录,建议如下:
1、做好表设计,只要做好索引,1000万的记录不算大,再大10倍的表也小CASE
2、网上找LRU来做cache就好了,用LinkedHashMap也很容易实现

提高单个查询性能的关键是数据库的设计和sql的优化, 和java没关系,
connection和cache技术是用来提高并发访问的性能, 和单个查询性能没关系.
去看看oracle的文档关于patition和materialized view, CBO, skip index的介绍吧.

To yyanghhong:
首先谢谢你的建议,你所说的是如何设计数据库方面的,而我们现在oracle数据库已经做好了,而由于数据太多,我们就必须设计一个cache来缓冲客户的瓶颈问题,我们的要求是这样的;设计一个cache
1.客户传过来的数据如何在内存中保存
2.如何分辨出搜索数据的属性(类)
3.对于cache中内存是如何分区?如何查找哪个内存的分区?
4.内存如何分配查找数据(即如何给连接发出命令)?
5.内存数据库(如何做:数据如何存储?如何分类?如何排序?是否同步)
6.搜索的数据是否在cache,如果不在又要如何去发出命令呢
毕竟cache中所存储的数据只有很少一部分,所以如何对连接发出命令是很重要的

这些就是我们所要的做的.所以说如何去做这个CACHE就很重要了

用一些现成的cache系统吧, 比如JCS, OSCache, SwarmCache, JBoss TreeCache, Tangosol Coherence cache,
JCS比较流行, 但好象有点memory leak问题, OSCache不错, SwarmCache主要用在cluster中,效率不高, JBoss TreeCache 只支持read-only and transactional concurrency strategy,不支持 read-write concurrency strategy.Tangosol Coherence cache不熟

我们现在就是用是jboss中的cache tree,基本的我们已经设计完了
现在摆在我们面前的是,关于:如何把数据储存在内存和内存如何分配这个问题上还不是很清楚,请指点一下啊

>以下是我们初步设计的方案:
>首先设计一个Timer,然后遍历每个连接的状态,再设计一个连接池,以此来>当连接关闭之后,我们直接从连接池中删除临时数据.

连接池的开发和调试看似简单,其实是一个非常需要经验的技术,其涉及的线程和锁机制不是每个程序员都在短时间内能够掌握和精通,我已经碰到很多这样执著在连接池上的Java程序员,对此,我只能说南辕北撤。

使用现成的连接池和缓冲池技术,EJB容器都提供这两层基本机制,基本满足一般需求,对于特殊需求,可以使用一个专门外部的缓存产品。


>如何把数据储存在内存和内存如何分配这个问题上
缓存产品都提供一个接口方法,供你存入数据,缓存产品在运行时就住留在内存中,因此向缓存产品中加入数据,实际就是加入内存。

>1.客户传过来的数据如何在内存中保存
向缓存产品中加入数据,实际就是加入内存。不是每个客户传来的数据根据需要放在缓存中,缓存分Session和全局缓存,可以将每个客户传来的数据保存在自己Session缓存中,除非特殊需要,需要保存到全局缓存中。

>2.如何分辨出搜索数据的属性(类)
如何分类,取决你数据的组织形式,缓存一般由KEY和被缓存对象组成,如何建立一个树形结构依据情况,可以使用Collection实现。一般不推荐在内存组织过分复杂的数据形式。

>3.对于cache中内存是如何分区?如何查找哪个内存的分区?
你只需要关系缓存产品接口,无需了解内存,至于是如何在内存分区的,简易你研究一下JVM的垃圾回收机制,对于那些回收机制无法回收的对象实际一直存在内存中,实现了缓存。

>4.内存如何分配查找数据(即如何给连接发出命令)?
你只需知道缓存是一个HashMap,通过KEY可以搜寻到数据。

>5.内存数据库(如何做:数据如何存储?如何分类?如何排序?是否同步)
这好像一般我们做应用系统的不会去做。找一些这方面的产品

>6.搜索的数据是否在cache,如果不在又要如何去发出命令呢
不在Cache中,就从数据库中查询获取,建议你研究一下Jive的缓存体系,你应该明白Java的缓存了,我的书籍“java实用系统开发指南”也对缓存有一些专门描述。


其实,缓存最复杂的你没有提及到,就是如何保持缓存数据的新鲜性,对于一些特殊系统,如果及时新鲜性很高,又涉及多个服务器系统,例如,一个客户访问一台服务器,修改了数据,如何保证另外一台服务器中缓存的这个数据能够是修改了的数据?

Tangosol Coherence cache这方面做得不错,非常先进的。


banq:
首先谢谢你给我的意见
我们现在做的cache就是用的现成的缓存产品(即Jboss中的TreeCache),其他的从你所说的我能基本上能慢慢的做到,至于你最后所提到的用Tangosol Coherence cache来解决保存缓存数据的新鲜性,也就是我们所说的如何更新数据吧.不知道在jboss treecache在这个方面是如何来解决数据的新鲜性,还有你说到当一个服务器修改了数据后,是否另一台服务器缓存中是否修改了?我想这就是我们大家所说到的同步性的关系,对于你提到用Tangosol Coherence cache来解决这个方面,而我对于这个几乎没有接触到,而对于jboss treecache我倒是比较熟悉,但不知道如何通过它来解决这个方面的问题

呵呵,我也来灌灌水
java中的缓存一般都是基于对象的,所以不管那一种cache,后台都有一个Map或是多个Map来做数据集合(key+Obj),这个Map的选择关系到你的性能。很多Cache用的都是Apache的common collections,common collections里边有很多种Map,有先进先出的、垃圾回收的、高效并发的...
Cache是针对Obj,把1000多万数据对象放到一个cache里,又要保证线程安全,又要高效,这种cache估计很难找。必须找那种后台Map是分片管理的的Map,换句还说,逻辑上是一个map,实际上是很多不同的Map组成的。这样并发时不会过慢。你可以查一下Jboss的src,看看你用的Treecache内部用的是什么map,就像楼上人说得的,每一中cache都有他的针对性,所以估计多半你要改动一下他的代码,以保证thread safe和concurrent,因为他不是为cahce1000多万数据而准备的。

缓存数据的新鲜性实现起来并不难,在cluster中是通过UDP广播来实现的
,当一个node cache中的数据对象产生变化是,他会brondcast该对象的id
其他node收到广播时,从本地cache删除该id的对象,下次有人访问时要从新取,所以,缓存数据的新鲜性要依赖后台数据库来实现。用jGROUP实现广播很容易,看看swormcache的代码,很简单的。

自己做cache的确很faint,可是很多情况下还是要自己动手。

>很多Cache用的都是Apache的common collections,common collections里>边有很多种Map,有先进先出的、垃圾回收的、高效并发的...
>Cache是针对Obj,把1000多万数据对象放到一个cache里,又要保证线程安>>>全,又要高效,这种cache估计很难找。必须找那种后台Map是分片管理的的>Map,换句还说,逻辑上是一个map,实际上是很多不同的Map组成的。这样并>>发时不会过慢。
小弟初学,也来掺和几句,针对上面这个问题,为什么在查找时不临时CLONE一个对象呢,这样就不用一直对MAP进行锁定的操作。

每一个连接都要clone一下map?不行吧
clone很慢的,在这段时间里总要synchronized吧

呵呵,那不如就用Doug Lea的util.concurrent包中的ConcurrentHashMap吧!

对了,今天看了一下《thinking in java》关于CLONE的内容,发现list,map等的CLONE只不过是对对象进了浅层拷贝,应该不会很慢吧,总比在查找时一直锁定快吧。

oracle自己有一个CacheConnectionPool之类的东西,直接用这个就行了,没有必要再用别的pool产品

(具体包名记不得了,你装完oracle,在jdbc目录下有一些example,里面就有这个的例子)