正是因为事务,所以效率通常来说没有一台数据库服务器高。

>>在崩溃的情况下 数据不一致问题就不会发生,因为可以靠事务保证,要么全部持久化包括内存更新全部完成,要么内存也不更新,多个数据库也不更新,你可以了解一下分布式事务这些。

这样的话,因为缓存更新和数据持久化是一个事务,要等到数据库写入完成才可以完成缓存的写操作。也就是说缓存对更新没有任何性能提高,相反还可能有些下降。

这种说法和banq前面提到的不一样。
>>那么我们为什么要追求在内存中进行并发写操作呢?因为高性能追求啊,高性能是无止境的,一个频繁修改的状态数据是在内存缓存改快呢?还是通过tcp/ip网络跑到数据库中修改,然后大家都到那里去读,哪个更快呢?一目了然。

到底是在内存里做修改,还是一定要持久化?总不能讨论性能的时候在内存里做,考虑安全讲事务,要先持久化。

[该贴被usejava于2009-05-08 10:00修改过]

>到底是在内存里做修改,还是一定要持久化?总不能讨论性能的时候在内存里做,考虑安全讲事务,要先持久化。

这两个步骤可以分开异步实现,比如使用JMS这样的分布式事务,又提高性能,又能保证安全性。

这个如果是异步一定出现数据丢失的问题。
更新了内存,如果忽然掉电或者硬件损坏肯定数据损失了,如果持久化了岂不是效率更低了??

分开异步进行怎么保证事务。
例如帐户更新:
1。取钱,帐户余额减少。此时缓存变化,但异步的持久化没完成。
2。系统崩溃,缓存丢失。
3。系统恢复,从数据库读取余额,还是原来的。

也许我对异步事务理解不深,不知道如何避免以上情景发生。

答案是必须同步持久化,这是同一个事物。

必须同步持久化性能岂不是更差。又要写数据库,又要更新缓存。如果是分布式,各个服务器都要更新。

必须持久化的地方,务必立即持久化,那是必须的。
banq的帐户里有1万元,ACoder去取了8000,usejava紧接着也去取了8000元。如果每个人的帐户都像banq那样,那不到一年,金融危机就会发生。
火车票全国联合售票,banq、ACoder、usejava都买到了2009年5月8日111次11号车厢11号上铺。怎么办?要么哥仨打一仗,谁拳头硬,谁睡;要么哥仨挤在一起睡。

那么什么时候可以不持久化呢?我认为为了保持数据完整性,所有更新操作必须持久化,但是这样的话缓存只会使性能更差。化这么大代价搞缓存有什么意义,只为了提高读的性能吗?

给大家讲讲JMS异步分布式事务,如果还有疑问,请各位再查查资料,因为JMS已经大量成熟应用,相信一定能够解决各位疑问:

1. 发送者发送消息到目的地,如果这一过程是包含在一个事务中,那么接受者只有等待到这个事务结束commit后才能读取到消息。当这个事务roll back,消息将从目的地删除。如下图一。

图一中update本地database可以看成更新本地缓存,更新本地缓存和发送更新DB消息在一个事务中,一旦消息发送成功,就由下面消息接收者负责来完成,而消息发送是非常快的,所以和更新本地缓存操作放在一个事务中,不影响缓存更新性能。

2 .当在一个事务中读取消息时,这个消息在这个事务中可用,但是并未从目的地中删除,而是留在目的地只是不会被其它接受者看到。当事务commit后,消息才完全从目的地删除。如果事务roll back, 消息将还是留在目的地(可以一直留在目的地JMS的数据库中),这样就可以被另外一个事务读取。这称为replay。通过配置可以决定一个消息被几次重新递交给接受者。什么时候停止递交等,或者通知数据库管理员:数据结构出问题,和业务情况不一致了,必须进行调整。如下图二

3. 如果发送者必须确认接收者的数据库更新是100%完成,可以用多个JMS Queue串联起来,如图三。

[该贴被banq于2009-05-09 08:06修改过]

[该贴被banq于2009-05-09 08:07修改过]




JMS本身就是一个消息中间件,虽然我没有用过,但是我用过CICS、TonglinKQ,MQ,还有一些开源的消息中间件,消息中间件的基本原理就是保证接收方一定并确认收到发起方的消息(消息可能包括操作),也就是一个消息就是一个事务(暂时可以这么看待,有的时候是很多消息一个事务)。
首先你说的第一点,更新数据库跟更新缓存是在一个事务中,也就是说它的效率只取决于其中最慢的那个操作,只有最后一个操作做完了才可以提交这个事务,那么对于性能上有什么提高那??依然有赖于您看不起的数据库的速度。缓存即使很快更新完毕依然处于锁定状态,否则就是脏读。

其次、您这种设计有些地方不合理,单点故障更加明显,说的明白一些就是增加了事务的提交不成功的概率,因为不管是缓存的服务器还是持久化的服务器,只要有一个服务器出现问题,就会导致你整个服务的失败,这样的设计其实是增大了系统的危险性,如果我有资源进行热备,那么我需要更多的资源进行热备(因为服务器变多了),从成本角度不是很可取。

再次、从您的设计来看是在无法看出不优化数据库而只以来缓存会对系统有什么帮助??这与您始终称道的缓存为王的概念是相悖的。而且缓存在这里起到的作用是什么??只是在查询的时候提供一个辅助作用。这种系统只有在读多写小的情况下效果比较明显,而对于频繁更新的数据起不到什么作用的。而且说实话,多台服务器内存更新不见得比IO速度快,中间要经过网络寻址,传输,本地内存更新,返回等一些列的操作,特别是对于一个大集群,本身网络数据量就会导致系统瘫痪。

最后、我想说说异步消息的作用,不要随意的用异步消息代替同步消息,异步消息的适用范围是应用服务器需要大量运算的情况,而不是任意情况都要使用。

同意ACoder的看法。
我也认为数据库不提交不能完成缓存更新,否则读取缓存数据可能是错误的,因为无法保证数据库一定能正常更新。也就是说,我不认为异步方式可以提高性能,除非默认为异步的数据库更新不会出错。这是不可能的。

又增加JMS服务器,整个系统的可靠性更低。和我前面提到的一样,缓存,JMS和数据库互相独立,整个系统的可用概率是各个部分可用概率的乘积,独立部分越多,系统越不可靠。

这么看来缓存只是提高了读取速度。而数据库也有缓存。考虑到缓存里是对象,数据库缓存里是数据,可能节约的只是由数据生成对象的时间。这样的话,采用专门的缓存服务器不太合算。

banq讲的是消息的缓存。消息的缓存是很简单的,它的需求性也是很明确的。看不出这里面有什么伟大性。

对于banq说的第三点“如果发送者必须确认接收者的数据库更新是100%完成,可以用多个JMS Queue串联起来”。在写少读多的情景下确实没问题,但这样还不如采用传统的方案-缓存从DB取数据。如果更新事务频繁的话,性能肯定有问题。
对于第二点,消息失败的情况,通知dba有什么用。是不是也写一个类似DBMS的Cache管理系统,来查找对象状态。
banq,对于考虑到并发和同步的Cache集群,我一直怀疑它的性能和可靠性。现在有这样的成功案例么?

'假设应用集群和数据库的正常概率都是0.9,那么整个系统的正常概率只有0.9*0.9=0.81。所以说,系统独立的部分越多,可靠性一般越低。'

这种算法和集群的概念是不符合的,集群是指多个冗余的服务器而不是把同一个服务器拆分,每个服务器提供同样的服务,这样肯定是提高了可靠性,降低了故障率。


我觉得大家都没有好好学操作系统,缓存的概念从cpu到os都有,这些都是很成熟的微观上的实现。

如果把范围放大,分布式系统就是操作系统的宏观表现,把pc总线换成是网络,把处理器和总线,硬盘的通信换成tcp/ip协议。抽象来说道理都是一样的。 把数据缓存到cpu,缓存到硬盘 和缓存到网络根本就没有区别。


网络就是计算机,能储存数据的不一定非是数据库。

不是我崇拜国外的技术,而是我们太落后了。可以预见的未来十几年,中国技术基本没戏。我们将长期处在“山寨”阶段。建议还是多学学英语,多看看老外的blog吧。