>但是我希望缓存能更加可控,允许控制缓存的使用,甚至跳过缓存。当然这要对应用透明

我前面说了,缓存是开辟对象的计算空间,对缓存要更可控,就是对对象更可控。

我们平时OOP编程,其实都是对对象进行操作,这些对象都是假设运行在内存中,而缓存不过是特殊化的一种内存,所以,谈到透明性,缓存内存是最好的,因为它一点都没有形成我们对Object操作的障碍和阻碍,中间没有隔阂,这个透明性比数据库要强多,你操作数据库中数据,必须使用数据库专用方式,比如SQL语句,但是你操作缓存中对象,有让你使用内存缓存专用方式吗?缓存是大者无形了。

缓存本身有现成的中间件产品,比如Terracotta可以更可靠地完成,Terracotta通过多台服务器同时运行形成真正7x24永不停机运行,所以,没有停机一说,内存中数据就没有丢失担忧,况且Terracotta也有对象存储持久化,也提供对缓存进行监测和tunning功能,缓存的管理工具因为和业务对象剥离了,所以比数据库管理工具更安全,更简单,更强大。

usejava谈到透明性 可靠性观点非常好,这些都是我们软件的追求目标,所以,方向是走对了,关键是我们如何理解透明性和可靠性,我们讲究伸缩性也是为了可靠性,因为任何一个单点都有风险,所以只有伸缩扩张了,并行计算了,才降低单点风险,当然可靠性还有通过事务和锁机制来完成。

关于可靠性 透明性 伸缩性这些具体定义有分歧的,可另开帖子讨论。本帖主要围绕缓存主题展开的。

[该贴被banq于2009-05-24 15:18修改过]

大家对缓存的观点越来越精辟,userjava对缓存使用的看法正中我在freeze框架中应用。freeze框架中为了解决缓存、事务、数据安全及可靠性,引入了对应用透明的几种模式:
1、五种缓存模式:控制对象缓存粒度及可否缓存;
2、两种中锁模式:控制锁的方式,和缓存模式一起使用。
3、对象版本:检测对象是否改变,重新加载对象
4、级联模式:控制级联的的对象是否加载或更新
5、对象管理器:对象管理器对应用开放,在应用的任何地方可以访问到缓存对象或缓存对象。
[该贴被davin于2009-05-27 19:47修改过]

世界流量访问量排名前十位的MYSPACE架构师谈缓存对伸缩性的提高:

http://www.jdon.com/jivejdon/forum/messageList.shtml?thread=34214&message=23122752#23122752

从前面缓存讨论我们可以看出,缓存主要是通过计算和存储的分离,提高系统的伸缩性Scalable,而有人提出使用内存对象数据库,这种还是以数据库为一个单一盒子概念,还是封装了计算和存储,无法实现计算和存储的分离,因此也就没有高Scalable而言。
[该贴被banq于2009-05-29 15:00修改过]

面向数据库编程,导致最终所有的任务都是受限于IO,这样最后就只能依靠垂直伸缩来提高系统吞吐量。而我们通过缓存使得原本受限于IO的任务,改为内存计算,这样其实就是受限于CPU,受限于内存,这样以来使得系统中受限于IO和受限于CPU的任务合理的分配,从而更好的提高伸缩性。
[该贴被xmuzyu于2009-05-29 21:17修改过]

请不要对自己不熟悉的领域妄加评论,谢谢。

>>面向数据库编程,导致最终所有的任务都是受限于IO

面向数据库编程不等于频繁读写数据库。即使不用OO,也可以把数据读到内存里进行大量计算,然后写回数据库。这种情况下,同样受限于CPU。

举个极端的例子。我一个纯PL/SQL程序,在4CPU服务器上,经过优化后,运行时间从8小时减少到1个多小时。程序执行时,CPU可以几乎保持25%占用,开三个session同时运行,和单个session相比时间变化不大。

你说我这个根本没有OO和缓存的应用受限于什么?

>>即使不用OO,也可以把数据读到内存里进行大量计算,然后写回数据库。这种情况下,同样受限于CPU。

不用OO,只是缓存数据,这样还不如不用缓存。不知道你有没有实战过,我在实战的过程中,不要说不用OO,OO用的不好,缓存的并发都很难控制。

>>>不用OO,只是缓存数据,这样还不如不用缓存。
这是在骂绝大多数IT人,骂他们傻了几十年(从有缓存起到OO出世)。如果骂对了,世人皆浊你独清,你就是当代最伟大的IT人。但愿你骂对。
缓存并非因OO而生,而是现在OO需借助缓存。
慢慢来,先弄清这缓存是什么?在OO里到底缓存的是什么东西?

to beepbug

请把握这个个帖子的主题。这个帖子的主题就是缓存业务对象。当然缓存存在的地方很多,但是业务对象缓存是这个帖子的主题。

帖名是“关于缓存的思考”,对不?
缓存的是什么都没整明白,缓存啥呢?
不要空对空,说点具体的,来点切实的。具体了,切实了,我们少了许多迷糊。
1)你先确定一下,你的缓存是不是以对象为单元?还是其它什么东西?
这点闹明白了,我们再讨论第二点。

to beepbug
帖名是“关于缓存的思考”,对不?
缓存的是什么都没整明白,缓存啥呢?
不要空对空,说点具体的,来点切实的。具体了,切实了,我们少了许多迷糊。
1)你先确定一下,你的缓存是不是以对象为单元?还是其它什么东西?
这点闹明白了,我们再讨论第二点。

请你看看帖子的内容再发帖,不要咬文嚼字。我们讨论了那么多都是对业务对象的缓存,你说不用OO,业务对象都没有,何来缓存业务对象。

如果按照你那么说,缓存的地方太多了,CPU有高速缓存,JVM有高速缓存,类加载器也有缓存,浏览器有缓存,web服务器也有缓存,数据库也有缓存等等,这些都不是这个帖子的主题,这个帖子的主题是如果通过良好的面向对象设计,形成业务对象模型,然后通过缓存来缓存业务对象,然后进行内存计算。

ps:讨论问题会有一个环境,我"关于缓存的思考"也有一个环境.请你理解一下这个环境。

[该贴被xmuzyu于2009-05-30 13:03修改过]

我说“不要空对空,说点具体的,来点切实的。”,意思就是“不要咬文嚼字”。
没人“说不用OO。”
“如果按照你那么说,缓存的地方太多了”后面的一大堆东西,我也没说过,也没质疑过你。既然你说了,那请顺便说说,你的缓存,与这许多缓存之间的差别。不用详细说,先说说各种缓存都缓存的什么东西。
还有“业务对象”,请明确说明,是什么东西?就是代码里的class?还是别的什么?
我以为,这些搞清楚了,我才能去理解缓存的意义。否则,看了你的一大篇,还是云里雾里的。可能是我的理解力问题,我到现在还没弄清楚缓存的是什么。

我在这里看到的缓存物,有“对象”、“事件”、“业务对象”。希望有个明确的说法。


缓存又称cache,意为 快速贮存区,就是可以告诉访问的一块区域
引用以前的话
缓存缓存,一个“存”,一个“缓”,“存”自然是存在内存,别忘记还有一个“缓”,“缓”的又是什么?缓的就是那个"比内存访问慢很多的"的那个访问方式(可以是数据库访问,也可以是文件访问,也可以是网络访问)。
比如hibernate中的一级和二级缓存,就是很好的例子

>>先说说各种缓存都缓存的什么东西。
这个不是此贴的主题。

>>还有“业务对象”,请明确说明,是什么东西?就是代码里的class?还是别的什么?
它是class,当然是class,因为我用的是java。但是这个class是特殊的class,是经过良好的设计的。比如你看我的主题贴子里面,关于jivedon里面form和formState的设计,以及jivedon里面FormThread,FormMessage的设计。

这个是jivedon里面的设计。

下面我说说2007年一个真实项目中的一点想法。那个项目是和浙江大学的几个朋友一起给台湾某公司做的一个SNS型的系统。在那个项目中,我们设计了一个个人主页类,PersonalPage,这个类是聚合根,它的状态分为可变和不可变的,可变的是主页上的最近访客列表,不可变的是用户的一些基本信息,以及新鲜事(新鲜事的具体设计,现在也记不大清楚了,反正那个时候是很麻烦),那么我就先说一些这个最近访客列表,只要有一个人访问了用户的个人主页,那么这个个人主页对象就保存到了全局的缓存中,下一个用户访问的时候,只需要改变这个个人主页对象的可变的部分vistorsSet,这个vistorsSet具体就保存了最近访客的信息,但是这个最近访客列表是全局并发访问的,这就要求通过锁来保护整个聚合根PersonalPage的不变量,我们那个时候好像是采用并发的set来完成的,好像是ConcurrentSkipListSet来实现的。

以上是一个具体的例子。这个帖子主要就是如何通过面向对象的设计,设计出对象,然后对象放入缓存(因为对象的构造要从DB里面构造,而有些状态是不经常变化的,如果每次访问都通过数据库来构造就很耗费性能),而每次并发更新只需要更新对象的可变部分,不可变部分不需要改变,(具体实现就是通过锁分离技术或者细粒度的锁,也可以采用JDK底层的并发容器来实现)

还有就是说说具体些代码的不好的习惯,以前写代码,手比脑子快,习惯是写个类,然后立马快捷键过去了,getter/setter全部生成了,这其实是非常可怕的,这容易造成对象状态的暴漏,所以现在我的类,一般很少有gett方法,对对象的状态产生改变的职责,一定要保证对象的不变量,这样无论怎么调用,缓存中的那个对象的状态不会受到破坏。

最后,我想说的就是,业务对象的建模,业务对象缓存,在加上针对具体业务的细粒度的内存锁来设计系统,这样才是有针对性的设计。