EhCache RMI 分布式缓存/缓存集群

EhCache 系统简介

EhCache 是一个纯 Java 的进程内缓存框架,具有快速、精干等特点。 
EhCache 的主要特性有:

  1. 快速、精干
  2. 简单;
  3. 多种缓存策略;
  4. 缓存数据有两级:内存和磁盘,因此无需担心容量问题;
  5. 缓存数据会在虚拟机重启的过程中写入磁盘;
  6. 可以通过 RMI、可插入 API 等方式进行分布式缓存;
  7. 具有缓存和缓存管理器的侦听接口;
  8. 支持多缓存管理器实例,以及一个实例的多个缓存区域;
  9. 提供 Hibernate 的缓存实现;

EhCache集群解决的问题: 
  由 于 EhCache 是进程中的缓存系统,一旦将应用部署在集群环境中,每一个节点维护各自的缓存数据,当某个节点对缓存数据进行更新,这些更新的数据无法在其它节点中共享, 这不仅会降低节点运行的效率,而且会导致数据不同步的情况发生。例如某个网站采用 A、B 两个节点作为集群部署,当 A 节点的缓存更新后,而 B 节点缓存尚未更新就可能出现用户在浏览页面的时候,一会是更新后的数据,一会是尚未更新的数据。 
  所以就需要用到 EhCache 的集群解决方案。 
   
EhCache集群方案:

? Terracotta 
? RMI 
? JMS : 依赖 ehcache-jmsreplication.jar 
? JGroups : 依赖ehcache-jgroupsreplication.jar 
? EhCache Server

  其中的三种最为常用集群方式,分别是 RMI、JGroups 以及 EhCache Server 。

EhCache集群疑问

? 你如何知道集群环境中的其他缓存? 
? 分布式传送的消息是什么形式? 
? 什么情况需要进行复制?增加(Puts),更新(Updates)或是失效(Expiries)? 
? 采用什么方式进行复制?同步还是异步方式?

EhCache集群基本概念

1、正确的元素类型:只有可序列化的元素可以进行复制。一些操作,比如移除,只需要元素的键值而不用整个元素;在这样的操作中即使元素不是可序列化的但键值是可序列化的也可以被复制。 
2、成员发现(Peer Discovery):Ehcache进行集群的时候有一个cache组的概念。每个cache都是其他cache的一个peer,没有主cache的存在。成员发现(Peer Discovery)正是用来解决 “你如何知道集群环境中的其他缓存?” 这个问题的。Ehcache提供了两种机制用来进行成员发现,即:自动成员发现和手动成员发现。要使用一个内置的成员发现机制要在ehcache的配置文件中指定cacheManagerPeerProviderFactory元素的class属性为 
net.sf.ehcache.distribution.RMICacheManagerPeerProviderFactory。

  自动的发现方式用TCP广播机制来确定和维持一个广播组。它只需要一个简单的配置可以自动的在组中添加和移除成员。在集群中也不需要什么优化服务器的知识,这是默认推荐的。ehcache.xml配置示例代码如下:

<cacheManagerPeerProviderFactory
class="net.sf.ehcache.distribution.RMICacheManagerPeerProviderFactory"
properties="peerDiscovery=automatic, multicastGroupAddress=230.0.0.1,
multicastGroupPort=4446, timeToLive=32"/>
<!-- timeToLive
    0是限制在同一个服务器
    1是限制在同一个子网
    32是限制在同一个网站
    64是限制在同一个region
    128是限制在同一个大洲
    255是不限制-->

 手动的发现方式需要知道每个监听器的IP地址和端口。集群成员(也就是服务器)不能在运行时动态地添加和移除。ehcache.xml配置示例代码如下:

<!-- server1 -->
<cacheManagerPeerProviderFactory
class="net.sf.ehcache.distribution.RMICacheManagerPeerProviderFactory"
properties="peerDiscovery=manual,
rmiUrls=//server2:40001/sampleCache11|//server2:40001/sampleCache12"/>

<!-- server2 -->
<cacheManagerPeerProviderFactory
class="net.sf.ehcache.distribution.RMICacheManagerPeerProviderFactory"
properties="peerDiscovery=manual,
rmiUrls=//server1:40001/sampleCache11|//server1:40001/sampleCache12"/>

CacheManagerPeerListener 
  每个CacheManagerPeerListener监听从成员们发向当前CacheManager的消息。配置 CacheManagerPeerListener需要指定一个CacheManagerPeerListenerFactory,它以插件的机制实现, 用来创建CacheManagerPeerListener。 
  Ehcache有一个内置的基于RMI的分布系统。它的监听器是RMICacheManagerPeerListener,这个监听器可以用RMICacheManagerPeerListenerFactory来配置。 
  示例代码:

<cacheManagerPeerListenerFactory
class="net.sf.ehcache.distribution.RMICacheManagerPeerListenerFactory"
properties="hostName=localhost, port=40001,
socketTimeoutMillis=2000"/>

  属性说明:

hostname (可选) – 运行监听器的服务器名称。标明了做为集群群组的成员的地址,同时也是你想要控制的从集群中接收消息的接口。 
   在CacheManager初始化的时候会检查hostname是否可用。 
   如果hostName不可用,CacheManager将拒绝启动并抛出一个连接被拒绝的异常。 
  如果指定,hostname将用InetAddress.getLocalHost().getHostAddress()来得到。 
port – 监听器监听的端口。 
socketTimeoutMillis (可选) – Socket超时的时间。默认是2000ms。当你socket同步缓存请求地址比较远,不是本地局域网。你可能需要把这个时间配置大些,不然很可能延时导致同步缓存失败。

CacheReplicators 
  每个要进行同步的cache都需要设置一个用来向CacheManager的成员复制消息的缓存事件监听器。这个工作要通过为每个cache的配置增加一个cacheEventListenerFactory元素来完成。 
  代码:

<cache name="sampleCache2" maxElementsInMemory="10" eternal="false" timeToIdleSeconds="100" timeToLiveSeconds="100" overflowToDisk="false">
<cacheEventListenerFactory class="net.sf.ehcache.distribution.RMICacheReplicatorFactory"
properties="replicateAsynchronously=true,replicatePuts=true, replicateUpdates=true, replicateUpdatesViaCopy=false, replicateRemovals=true "/>
</cache>

  cacheEventListenerFactory 支持以下属性

replicatePuts=true | false – 当一个新元素增加到缓存中的时候是否要复制到其他的peers. 默认是true。 
replicateUpdates=true | false – 当一个已经在缓存中存在的元素被覆盖时是否要进行复制。默认是true。 
replicateRemovals= true | false – 当元素移除的时候是否进行复制。默认是true。 
replicateAsynchronously=true | false – 复制方式是异步的(指定为true时)还是同步的(指定为false时)。默认是true。 
replicatePutsViaCopy=true | false – 当一个新增元素被拷贝到其他的cache中时是否进行复制指定为true时为复制,默认是true。

Cache属性说明:

<cache
        name="userCache"
        maxElementsInMemory="10000"
        eternal="true"
        overflowToDisk="true"
        timeToIdleSeconds="0"
        timeToLiveSeconds="0"
        diskPersistent="false"
        diskExpiryThreadIntervalSeconds="120">
        <cacheEventListenerFactory
           class="net.sf.ehcache.distribution.RMICacheReplicatorFactory"
          properties="replicateAsynchronously=true,replicatePuts=true,replicateUpdates=true,replicateUpdatesViaCopy=false,replicateRemovals=true">
        </cacheEventListenerFactory>
        <bootstrapCacheLoaderFactory
          class="net.sf.ehcache.distribution.RMIBootstrapCacheLoaderFactory"
               properties="bootstrapAsynchronously=true">
        </bootstrapCacheLoaderFactory>
    </cache>

必须属性: 
  name:缓存名称。 
  maxElementsInMemory:缓存最大个数。 
  eternal:对象是否永久有效,一但设置了,timeout将不起作用。 
  overflowToDisk:当内存中对象数量达 
  maxElementsInMemory时,Ehcache将会对象写到磁盘中。 
   diskSpoolBufferSizeMB:这个参数设置DiskStore(磁盘缓存)的缓存区大小。默认是30MB。每个Cache都应该有自己的一个缓冲区。 
  maxElementsOnDisk:硬盘最大缓存个数。 
可选的属性: 
  timeToIdleSeconds:设置对象在失效前的允许闲置时间(单位:秒)。仅当eternal=false对象不是永久有效时使用,可选属性,默认值是0,也就是可闲置时间无穷大。 
  timeToLiveSeconds:设置对象在失效前允许存活时间(单位:秒)。最大时间介于创建时间和失效时间之间。仅当eternal=false对象不是永久有效时使用,默认是0.,也就是对象存活时间无穷大。 
  diskPersistent:是否disk store在虚拟机启动时持久化. The default value is false. 
  memoryStoreEvictionPolicy:当达到maxElementsInMemory限制时,Ehcache将会根据指定的策略去清理内存。默认策略是LRU(最近最少使用)。你可以设置为FIFO(先进先出)或是LFU(较少使用)。 
  diskExpiryThreadIntervalSeconds:磁盘失效线程运行时间间隔,默认是120秒。 
  clearOnFlush:内存数量最大时是否清除。 
缓存子元素: 
  cacheEventListenerFactory:注册相应的的缓存监听类,用于处理缓存事件,如put,remove,update,和expire 
  bootstrapCacheLoaderFactory:指定相应的BootstrapCacheLoader,用于在初始化缓存,以及自动设置。

EhCache RMI 手动方式配置缓存

Tomcat1: 127.0.0.1:8080, Cache Server1: 127.0.0.1:40001 
Tomcat2: 127.0.0.1:8088, Cache Server2: 127.0.0.1:40002

用到的架包: 
ehcache-core-2.6.8.jar 
log4j-1.2.17.jar 
servlet-api.jar (示例中使用了@WebServlet,请确保servler-api的架包版本大于3.0) 
slf4j-api-1.6.1.jar 
slf4j-log4j12-1.6.1.jar

创建Web工程TestEhcache, 工程目录如下: 

CacheManagerFactory.java

private CacheManager manager;
    private static CacheManagerFactory factory = new CacheManagerFactory();
    private final static String EHCACHEFILE = "/ehcache.xml";

    private CacheManagerFactory() {
    }

    public static CacheManagerFactory getInstance() {
        return factory;
    }

    public CacheManager getCacheManager() {
        if (manager == null) {
            InputStream is = this.getClass().getResourceAsStream(EHCACHEFILE);
            manager = CacheManager.create(is);
        }
        return manager;
    }

    public Cache getCache(String cache) {
        return getCacheManager().getCache(cache);
    }

    public void setCache(Cache cache) {
        getCacheManager().addCache(cache);
    }

    public void setCache(String cache) {
        getCacheManager().addCache(cache);
    }

    public Element getElement(String cacheName, String key) {
        if (getCache(cacheName) == null)
            setCache(cacheName);
        return getCache(cacheName).get(key);
    }

    public void setElement(String cache, Element element) {
        if (getCache(cache) == null)
            setCache(cache);
        getCache(cache).put(element);
    }

    public Boolean continaElementKey(String cacheName, String key) {
        if (getCache(cacheName) == null)
            setCache(cacheName);
        return getCache(cacheName).isKeyInCache(key);
    }

TesAction.java

@WebServlet("/test")
public class TesAction extends HttpServlet {

    private static final long serialVersionUID = 1L;

    CacheManagerFactory cmf = CacheManagerFactory.getInstance();

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
        doPost(request,response);
    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException {
        String res = "";
        String key = request.getParameter("key");

        Element element = cmf.getElement("userCache", "map");
        if(element == null){
            Map<String, String> map = new HashMap<String, String>();
            map.put(key, key);
            cmf.setElement("userCache", new Element("map", map));
        }else{
            Map<String, String> map = (Map<String, String>) element.getValue();
            res = map.get(key);
            if(res == null){
                map.put(key, key);
                // 多次测试发现,存在同名Element是,重复put的是无法复制的,因此当遇到两个节点同步不上的时候,先remove后put。
                cmf.getCache("userCache").remove("map");
                cmf.setElement("userCache", new Element("map", map));
                res = "0;null";
            }
        }

        response.setContentType("text/html;charset=UTF-8");
        response.setCharacterEncoding("UTF-8");
        PrintWriter out = response.getWriter();
        out.write(res);
        out.close();
    }

    @Override
    public void init() throws ServletException {
        super.init();
    }

}

ehcache.xml:

<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://ehcache.sf.net/ehcache.xsd">

    <diskStore path="java.io.tmpdir" />

    <cacheManagerPeerProviderFactory
        class="net.sf.ehcache.distribution.RMICacheManagerPeerProviderFactory"
        properties="peerDiscovery=manual,rmiUrls=//127.0.0.1:40002/userCache|//127.0.0.1:40002/resourceCache">
    </cacheManagerPeerProviderFactory>

    <cacheManagerPeerListenerFactory
        class="net.sf.ehcache.distribution.RMICacheManagerPeerListenerFactory"
        properties="hostName=127.0.0.1, port=40001, socketTimeoutMillis=2000">
    </cacheManagerPeerListenerFactory>

    <defaultCache maxElementsInMemory="10000" eternal="false" timeToIdleSeconds="30" timeToLiveSeconds="30" overflowToDisk="false"/>

    <cache
        name="userCache"
        maxElementsInMemory="10000"
        eternal="true"
        overflowToDisk="true"
        timeToIdleSeconds="0"
        timeToLiveSeconds="0"
        diskPersistent="false"
        diskExpiryThreadIntervalSeconds="120">
        <cacheEventListenerFactory
            class="net.sf.ehcache.distribution.RMICacheReplicatorFactory"
            properties="replicateAsynchronously=true,replicatePuts=true,replicateUpdates=true,replicateUpdatesViaCopy=false,replicateRemovals=true">
        </cacheEventListenerFactory>
        <bootstrapCacheLoaderFactory
            class="net.sf.ehcache.distribution.RMIBootstrapCacheLoaderFactory"
            properties="bootstrapAsynchronously=true">
        </bootstrapCacheLoaderFactory>
    </cache>

    <cache
        name="resourceCache"
        maxElementsInMemory="10000"
        eternal="true"
        overflowToDisk="true"
        timeToIdleSeconds="0"
        timeToLiveSeconds="0"
        diskPersistent="false"
        diskExpiryThreadIntervalSeconds="120">
        <cacheEventListenerFactory
            class="net.sf.ehcache.distribution.RMICacheReplicatorFactory"
            properties="replicateAsynchronously=true,replicatePuts=true,replicateUpdates=true,replicateUpdatesViaCopy=false,replicateRemovals=true">
        </cacheEventListenerFactory>
        <bootstrapCacheLoaderFactory
            class="net.sf.ehcache.distribution.RMIBootstrapCacheLoaderFactory"
            properties="bootstrapAsynchronously=true">
        </bootstrapCacheLoaderFactory>
    </cache>

</ehcache>

复制TestEhcache到 TestEhcache1, 修改TestEhcache1下的ehcache.xml ,只需要修改cacheManagerPeerProviderFactory和cacheManagerPeerListenerFactory修改为如下代码,其他不变

<cacheManagerPeerProviderFactory
        class="net.sf.ehcache.distribution.RMICacheManagerPeerProviderFactory"
        properties="peerDiscovery=manual,rmiUrls=//127.0.0.1:40001/userCache|//127.0.0.1:40001/resourceCache">
    </cacheManagerPeerProviderFactory>

    <cacheManagerPeerListenerFactory
        class="net.sf.ehcache.distribution.RMICacheManagerPeerListenerFactory"
        properties="hostName=127.0.0.1, port=40002, socketTimeoutMillis=2000">
    </cacheManagerPeerListenerFactory>

为了区别,将TestEhcache1的TesAction.doPost()方法修改为如下代码,只get的缓存不put缓存,用于观察TestEhcache1是否能同步TestEhcache的数据:

String res = "0;null";
        Element element = cmf.getElement("userCache", "map");
        if(element != null){
            Map<String, String> map = (Map<String, String>) element.getValue();
            res = map.get(request.getParameter("key"));
            if(res == null){
                res = "0;null";
            }
        }
        response.setContentType("text/html;charset=UTF-8");
        response.setCharacterEncoding("UTF-8");
        PrintWriter out = response.getWriter();
        out.write(res);
        out.close();

将TestEhcache部署到tomcat1, TestEhcache1部署到Tomcat2。依次执行如下代码: 
localhost:8080/TestEhcache/test?key=125 
localhost:8080/TestEhcache/test?key=125 
localhost:8088/TestEhcache1/test?key=125 
如果输出内容分别如下,说明集群ok, 两节点数据同步没问题, 否者请仔细检查配置文件和TestAction代码: 
0;null 
125 
125

EhCache RMI 自动方式配置缓存 
将ehcache.xml的cacheManagerPeerProviderFactory代码改为:

<cacheManagerPeerProviderFactory
 class="net.sf.ehcache.distribution.RMICacheManagerPeerProviderFactory"
    properties="peerDiscovery=automatic, multicastGroupAddress=192.168.0.1,
    multicastGroupPort=40004, timeToLive=32"
/>

EhCache Jgroups 方式配置缓存

在TestEhcache和TestEhcache1工程中添加ehcache-jgroupsreplication-1.7.jar和jgroups-3.6.9.Final.jar。 使用该方式比RMI方式配置简单。

TestEhcache 的 ehcache.xml

<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://ehcache.sf.net/ehcache.xsd">

    <diskStore path="java.io.tmpdir" />

    <cacheManagerPeerProviderFactory
        class="net.sf.ehcache.distribution.jgroups.JGroupsCacheManagerPeerProviderFactory"
        properties="connect=TCP(bind_port=4001):
            TCPPING(initial_hosts=192.168.8.150[4001],192.168.8.150[4002];port_range=10;timeout=3000;num_initial_members=3):
            MERGE2(min_interval=3000;max_interval=5000):
            FD_ALL(interval=5000;timeout=20000):
            FD(timeout=5000;max_tries=48;):
            VERIFY_SUSPECT(timeout=1500):
            pbcast.NAKACK(retransmit_timeout=100,200,300,600,1200,2400,4800;discard_delivered_msgs=true):
            pbcast.STABLE(stability_delay=1000;desired_avg_gossip=20000;max_bytes=0):
            pbcast.GMS(print_local_addr=true;join_timeout=5000)"
        propertySeparator="::">
    </cacheManagerPeerProviderFactory>

    <defaultCache
        maxElementsInMemory="10000"
        eternal="true"
        overflowToDisk="true"
        timeToIdleSeconds="0"
        timeToLiveSeconds="0"
        diskPersistent="false"
        diskExpiryThreadIntervalSeconds="120">
        <cacheEventListenerFactory
            class="net.sf.ehcache.distribution.jgroups.JGroupsCacheReplicatorFactory"
            properties="replicateAsynchronously=true,replicatePuts=true,replicateUpdates=true,replicateUpdatesViaCopy=false,replicateRemovals=true"/>
        <bootstrapCacheLoaderFactory
            class="net.sf.ehcache.distribution.jgroups.JGroupsBootstrapCacheLoaderFactory"
            properties="bootstrapAsynchronously=true">
        </bootstrapCacheLoaderFactory>
    </defaultCache>
</ehcache>

复制TestEhcache的ehcache.xml到TestEhcache1,并且修改下列代码:

connect=TCP(bind_port=4002)

推荐文章:http://raychase.iteye.com/blog/1545906 
http://blog.csdn.net/tang06211015/article/details/52281551

http://www.ehcache.org/apidocs/2.10.3/index.html

来源:http://blog.csdn.net/xlxxcc/article/details/52350264

时间: 2024-10-07 01:59:51

EhCache RMI 分布式缓存/缓存集群的相关文章

EhCache缓存在集群环境中同步问题

由于 EhCache 是进程中的缓存系统,一旦将应用部署在集群环境中,当每一个节点维护各自的缓存数据,某个节点对缓存数据进行更新,这些更新的数据无法在其它节点中共享,这不仅会降低节点运行的效率,而且会导致数据不同步的情况发生.例如某个网站采用 A.B 两个节点作为集群部署,当 A 节点的缓存更新后,而 B 节点缓存尚未更新就可能出现用户在浏览页面的时候,一会是更新后的数据,一会是尚未更新的数据,尽管我们也可以通过 Session Sticky 技术来将用户锁定在某个节点上,但对于一些交互性比较强

ZooKeeper一二事 - 搭建ZooKeeper伪分布式及正式集群 提供集群服务

集群真是好好玩,最近一段时间天天搞集群,redis缓存服务集群啦,solr搜索服务集群啦,,,巴拉巴拉 今天说说zookeeper,之前搭建了一个redis集群,用了6台机子,有些朋友电脑跑步起来,有点卡,那这里主要说说伪分布式的集群,正式版的集群需要3台机子,我就一带而过说一说,搭建起来也是非常简单的 先来说说Zookeeper 什么是Zookeeper呢,顾名思义,动物园管理员嘛,什么hadoop大象啦,hive蜜蜂啦,pig小猪啦,都是用这货来管的,就是大数据Hadoop里面的嘛~ (题外

高性能网站架构缓存——redis集群

相信你已经对redis有一定的了解,并能够安装上,进行简单的使用了,但是在咱们的实际应用中,使用redis肯定不会使用单机版,不光是redis不能使用单机版,其他的也不会使用,所以今天我们来说一下redis cluster的安装. 1.  Redis Cluster的架构图. (1)所有的redis节点彼此互联(PING-PONG机制),内部使用二进制协议优化传输速度和带宽. (2)节点的fail是通过集群中超过半数的节点检测失效时才生效. (3)客户端与redis节点直连,不需要中间proxy

分布式-微服务-集群 的概念和区别

分布式:一个业务分拆多个子业务,部署在不同的服务器上 集群:同一个业务,部署在多个服务器上 微服务的意思也就是将模块拆分成一个独立的服务单元通过接口来实现数据的交互. 分布式是指将不同的业务分布在不同的地方.而集群指的是将几台服务器集中在一起,实现同一业务. 分布式中的每一个节点,都可以做集群.而集群并不一定就是分布式的. 分布式,从窄意上理解,也跟集群差不多,但是它的组织比较松散,不像集群,有一个组织性,一台服务器垮了,其它的服务器可以顶上来. 分布式的每一个节点,都完成不同的业务,一个节点垮

分布式锁--redis(集群)

原文链接:https://blog.csdn.net/weixin_38003389/article/details/89434629 redis 集群做分布式锁,我们使用 Redisson. 框架 版本 Spring Boot 2.0.3.RELEASE Spring Cloud Finchley.RELEASE redis redis-4.0.11 JDK 1.8.x maven配置 <parent> <groupId>org.springframework.boot</

分布式文件系统FastDFS集群部署

1.源码开放下载地址:https://github.com/happyfish100 早期源码开放下载地址:https://sourceforge.net/projects/fastdfs/files/ 官网论坛:http://bbs.chinaunix.net/forum-240-1.html 2.系统架构如下 文件上传流程 1.client询问tracker上传到的storage,不需要附加参数: 2.tracker返回一台可用的storage: 3.client直接和storage通讯完成

分布式机器学习的集群方案介绍之HPC实现

机器学习的基本概念 机器学习方法是计算机利用已有的数据(经验),得出了某种模型(迟到的规律),并利用此模型预测未来(是否迟到)的一种方法.目前机器学习广泛应用于广告投放.趋势预测.图像识别.语音识别.自动驾驶和产品推荐等众多领域. 在确定了问题模型之后,根据已知数据寻找模型参数的过程就是训练,训练过程就是不断依据训练数据来调整参数的迭代,从而使依据模型作出的预测结果更加准确. HPC的基本概念 HPC就是高性能计算或高性能计算集群的简写.为了追求高性能,HPC的工作负载一般直接运行在Linux系

Akka(10): 分布式运算:集群-Cluster

Akka-Cluster可以在一部物理机或一组网络连接的服务器上搭建部署.用Akka开发同一版本的分布式程序可以在任何硬件环境中运行,这样我们就可以确定以Akka分布式程序作为标准的编程方式了. 在上面两篇讨论里我们介绍了Akka-Remoting.Akka-Remoting其实是一种ActorSystem之间Actor对Actor点对点的沟通协议.通过Akka-Remoting来实现一个ActorSystem中的一个Actor与另一个Actorsystem中的另一个Actor之间的沟通.在Re

浅谈分布式计算系统和集群系统的区别

随着项目经验的增长笔者对分布式计算的了解是越来越深入,那么接下来笔者就和大家浅谈下分布式系统的特点吧,可以这样理解,分布式系统是将多个子任务分布在不同的物理机上并行工作.是以空间换时间并行计算来提高程序的可靠性和性能.分布式系统的高性能计算属于MIMD的范畴领域.它是按不同的业务分配不同的节点(单点),组织比较松散,一个节点垮掉那么些节点负责的业务就不能正常处理,当然,技术到位肯定会有其他解决方案例如基于Remoting通信方案WCF通信方案. 而采用集群方案,同样提供10台服务器,每台服务器都