今天我在weibo上发布了albian将放弃支持缓存同步后,引起了以前的伙计们一片的谈论声。有认为缓存同步不是一项好的解决方案的、也有认为没有缓存同步将无法使用本地缓存的、还有担忧一台机器的本地缓存各自为政导致全站缓存状态错乱的......,但是很不幸,albian还是决定不支持本地缓存的同步。
缓存:主要的目的是用来为了让客户得到更高的响应。这是没有错的。但是从架构人员来说,当你考虑使用一种方案来实现某一目的时,你不能只从一点看,约束条件有很多。比如金钱投入、扩展性(这个很重要)等等。
缓存从架构上分,又有本地和分布式之分。本地缓存一般存储在提供服务的机器上,最大的优点就是进车内通讯,得到数据几乎没有时间差;分布式缓存从名字上就能知道缓存是分布在不同的机器上的,目前业界比较流行的做法是使用memcached或者类似的软件,它的优点就是可以线性接近无限的扩展,而且保证存取缓存数据时不会因为数据量的增大而损耗性能。然后是缺点:本地缓存最大的问题是扩展性:表现在几个方面:缓存的状态更新怎么办?缓存的大小限制,等等。分布式缓存的最大问题可能就是一台服务down数据库压力剧增时怎么办?频繁操作分布式缓存性能怎么样?等等。
先说本地缓存。支持使用本地缓存的XT基本上是为了效率出发,因为本地缓存的存取基本上不需要考虑时间消耗,所以用起来非常爽。如果你只有10台之内的服务器,这个架构基本上没有问题。就算是增加上缓存内对象状态的考虑(这个问题就是:如果有2台以上的服务器同时存了一个A对象,当第一台机器上的A被改变时怎么让第二台或者第三台甚至更多台机器也知道A对象已经被更改了?),问题也不大。我们增加一个服务,专门用来同步各个对象的状态:架构如图所示:
步骤是这样的:
1.同步服务器和业务服务器全部启动起来,业务服务器向同步服务器注册,告知同步服务器业务服务器已经准备完毕;
2.某一机器上的A对象被更改了,它会通过网络通知同步服务器,告诉同步服务器,A对象已经被更改;
3.同步服务器的得到了A对象被更改的消息后,首先从内存中得到刚刚注册的并且还健在的业务服务器;
4.通知所有的健在业务服务器,A对象已经被更改,你们需要更新;
5.业务服务器得到通知后,启动更新程序,从数据库中获取最新的A对象的信息,并且缓存;
同步大概的步骤就是这样的。问题有以下几点:
1.延迟。网络通讯是需要有时间的,同步中,至少经过了3个网络传输步骤,时间的延迟会比较长;
2.扩展性不好。我业务服务器少这套机制还能抗住,一旦我业务服务器多呢?很多人可能会说,增加同步服务器,对,就是这个策略,但是你还要更改业务代码,把不同的对象按照你的逻辑分发到不同的同步服务器,然后再通知业务服务器。但是如果业务服务器有200台呢?你一台同步服务器通知200台需要多少时间?
3.容灾新不强。如果有一台同步服务器down掉你怎么办?这个好像有解决办法。在同步服务器集群上套小集群,采用pxois算法,应该可以搞定;
4.每台业务服务器都要从数据库中load一遍同样的数据,而且几乎是在同一时刻完成,数据库的压力也会增加;
5.业务服务器上占用过多的内存浪费不说还会导致我们单机处理业务的量下降。业务服务器最主要的还是处理业务请求,假设一个进程使用2G内存可以处理500个请求,然后本地缓存消耗掉2g,我们一台8G的机器本来可以同时跑3个进程,现在却只能跑2个,无形中损耗掉500个业务的处理量;
而如果我们换成分布式的系统架构,我们的架构将会是这样子:
步骤如下:
1.程序起来的时候,需要将需要的数据全部冲入缓存;
2.起来业务服务器,什么都不用做;
3.当更改一台业务服务器上的A对象时,再更改完后同时把A对象更新到分布式缓存集群;
4.当另外的业务服务器需要A对象时,从分布式缓存集群中获取;
5.重复3-4;
分布式也有缺点:
1.每次读取都要时间;这也许是一个问题。但是目前从测试的结果看,10k的数据从memcached中获取时间为0.4毫秒;
2.如果一台缓存服务器down掉,那么数据库压力就会增大,并且可能会存在需要重新导入数据的风险;
从目前分析的本地缓存和分布式缓存来看,本地缓存问题比较多,而且最重要的是扩展性没办法很好的搞定。对于一个定位于企业级应用的架构而言,失去了扩展性意味着当数据量上去的时候,很多事情就束手无策了。所以albian最后还是放弃了同步。
其实从albian的角度出发,albian的IAlbianObject本身就是为了网络传输的考虑而设计的,albian推荐使用贫血对象,业务和数据结构分开。类似于数据就像是水管中的水,而业务流程就像水管。水(对象)从水管进口(GUI)流入,经过水管(业务流程),流向蓄水池(数据库)或者再次回给客户(回流)。这样当数据量上去(水大的时候)的时候,我们就可以想水管工那样在这个环节中增加我们的策略,分流、直接炸掉大坝等等很容易的做出相应的应对。
其实albian不是不推荐不使用本地缓存,albian推荐的缓存使用规则如下:
1.全站都要使用的缓存就是用分布式缓存;
2.本地缓存肯定要用,但是最好用在过期的对象上,比如列表的list对象等等;
3.所有的对象都应该是可序列化和满足网络传输的;
4.如果缓存是从分布式缓存集群中获取的,可以使用会话内缓存(不是session那么简单);