系统性能和吞吐量的需求决定了单纯在数据库中操作整个仓库拓扑数据是不现实的。这种大量的服务器端对象,会消耗大量的服务器内存和活动对象表的空间,如果这些对象使用得比较少,就很容易造成数据库服务端资源的浪费。
把仓库拓扑数据存放在本地内存中,形成内存数据对象(数据缓存),以便能高效地完成相应的操作,是一个解决办法。
但是,我们也要注意到在内存中保留仓库拓扑数据的完整副本也是不现实的,对于大的仓库来说,要维护整个拓扑数据所需要的内存会远远超过可用内存的大小,即使仓库拓扑分布在多台主机上也是一样的。
怎样才能确保无论仓库拓扑操作访问哪个存储单元,它都可以从内存中得到相应的数据呢?
对策:采用虚拟代理(Virtual Proxy)解决方案,解决从一个巨大数据库中把所有的对象全部加载进来消耗大量资源的问题。
虚拟代理(Virtual Proxy)解决方案是一种节省内存的技术,它建议在创建那些占用大量内存或处理复杂的对象时,把创建这类对象推迟到使用它的时候。在特定的应用启动的时候,不会立即使用所有的对象,而是推迟对象的创建直到应用程序需要它为止。对象在被应用第一次引用的时候创建它,并且以后同一个实例可以被重用。虚拟代理在处理数据对象的时候,可以合理安排数据库数据何时在内存中建立数据对象。
我们应该怎样来安排数据库资源的使用呢?对于不会用到,或者不会长期使用的资源,我们不应当引入过多的开销。因此,为当前内存中尚不存在的对象引入一个代理(Proxy)对象。这个代理对象可以处理一些简单的请求,比如查询目标对象的键值,但在需要完整的数据对象行为的时候就会创建并初始化目标对象,如下图所示。
代理对象与目标对象提供同样的接口,基本结构与执行过程的活动关系如下图所示。
我们可以这样来应用虚拟代理解决方案:
首先:设计一个与真实对象具有相同接口的单独对象(指虚拟代理)。不同的客户对象可以在创建和使用真实对象地方用相应的虚拟对象来代替。虚拟对象把真实对象的引用作为它的实例变量维护。
其次:代理对象不要自动创建真实对象,当客户需要真实对象的服务时,调用虚拟代理对象上的方法。
最后:在调用的时候,首先检测真实对象是否被创建。如果真实对象已经创建,代理把调用转发给真实对象。如果真实对象没有被创建,则代理对象创建真实对象,把这个对象分配给引用变量,把调用转发给真实对象。按照这种安排,验证对象存在和转发方法调用这些细节对于客户是不可见的。客户对象就像和真实对象一样与代理对象进行交互。
因此客户从检测真实对象是否为null 中解脱出来,另外,由于创建代理对象在时间和处理复杂度上要少于创建真实对象。因此,在应用程序启动的时候,用代理对象代替真实对象初始化,可以加快启动时间。
虚拟代理的缺点是:在访问这个对象的任何地方,都需要检测确认它不是空(null)。这会引入检测的时间消耗。虚拟代理可以将资源获取的开销分散得更为均匀,尤其对于庞大而消耗资源很多的数据对象来说,虚拟代理所带来的好处可能就非常明显。
设计方案需要为仓库拓扑中所有原子存储单元提供虚拟代理(Virtual Proxy),不管什么时候需要通过Virtual Proxy 访问原子存储单元,都会在相应操作执行之前将数据从数据库载入到内存中。一旦存储单元已经在内存中,则会将其保持在内存中以便后续访问能高效执行。根据仓库存储性质不同,分别采用两种方案。
第一种方案:聚合存储单元直接调入内存:
为聚合存储单元提供直接在内存中存储在技术上是可行的,因为对聚合存储单元(比如过道、侧面、机架等)的访问比较频繁且变化不大,因此将数据一直保留在内存中会比在需要时载入效率更高。此外,和原子存储单元的数量相比,在具体的仓库配置中聚合存储单元的数量要少得多,因此不会浪费过多的内存。
第二种方案:原子存储采用虚拟代理:
在原子存储单元(箱子、门、自卸、车灯)中支持Virtual Proxy,它的工作方法非常简单:首先从Storage 类派生出StorageProxy(存储代理)类,然后建立到具体AtomicStorage(原子存储)的关联,可以通过主键实现。当需要访问代理的时候,通过主键载入相应的存储单元数据并执行相关的操作,如下图所示。
把仓库拓扑数据存放在本地内存中,形成内存数据对象(数据缓存),以便能高效地完成相应的操作,是一个解决办法。
但是,我们也要注意到在内存中保留仓库拓扑数据的完整副本也是不现实的,对于大的仓库来说,要维护整个拓扑数据所需要的内存会远远超过可用内存的大小,即使仓库拓扑分布在多台主机上也是一样的。
怎样才能确保无论仓库拓扑操作访问哪个存储单元,它都可以从内存中得到相应的数据呢?
对策:采用虚拟代理(Virtual Proxy)解决方案,解决从一个巨大数据库中把所有的对象全部加载进来消耗大量资源的问题。
虚拟代理(Virtual Proxy)解决方案是一种节省内存的技术,它建议在创建那些占用大量内存或处理复杂的对象时,把创建这类对象推迟到使用它的时候。在特定的应用启动的时候,不会立即使用所有的对象,而是推迟对象的创建直到应用程序需要它为止。对象在被应用第一次引用的时候创建它,并且以后同一个实例可以被重用。虚拟代理在处理数据对象的时候,可以合理安排数据库数据何时在内存中建立数据对象。
我们应该怎样来安排数据库资源的使用呢?对于不会用到,或者不会长期使用的资源,我们不应当引入过多的开销。因此,为当前内存中尚不存在的对象引入一个代理(Proxy)对象。这个代理对象可以处理一些简单的请求,比如查询目标对象的键值,但在需要完整的数据对象行为的时候就会创建并初始化目标对象,如下图所示。
代理对象与目标对象提供同样的接口,基本结构与执行过程的活动关系如下图所示。
我们可以这样来应用虚拟代理解决方案:
首先:设计一个与真实对象具有相同接口的单独对象(指虚拟代理)。不同的客户对象可以在创建和使用真实对象地方用相应的虚拟对象来代替。虚拟对象把真实对象的引用作为它的实例变量维护。
其次:代理对象不要自动创建真实对象,当客户需要真实对象的服务时,调用虚拟代理对象上的方法。
最后:在调用的时候,首先检测真实对象是否被创建。如果真实对象已经创建,代理把调用转发给真实对象。如果真实对象没有被创建,则代理对象创建真实对象,把这个对象分配给引用变量,把调用转发给真实对象。按照这种安排,验证对象存在和转发方法调用这些细节对于客户是不可见的。客户对象就像和真实对象一样与代理对象进行交互。
因此客户从检测真实对象是否为null 中解脱出来,另外,由于创建代理对象在时间和处理复杂度上要少于创建真实对象。因此,在应用程序启动的时候,用代理对象代替真实对象初始化,可以加快启动时间。
虚拟代理的缺点是:在访问这个对象的任何地方,都需要检测确认它不是空(null)。这会引入检测的时间消耗。虚拟代理可以将资源获取的开销分散得更为均匀,尤其对于庞大而消耗资源很多的数据对象来说,虚拟代理所带来的好处可能就非常明显。
设计方案需要为仓库拓扑中所有原子存储单元提供虚拟代理(Virtual Proxy),不管什么时候需要通过Virtual Proxy 访问原子存储单元,都会在相应操作执行之前将数据从数据库载入到内存中。一旦存储单元已经在内存中,则会将其保持在内存中以便后续访问能高效执行。根据仓库存储性质不同,分别采用两种方案。
第一种方案:聚合存储单元直接调入内存:
为聚合存储单元提供直接在内存中存储在技术上是可行的,因为对聚合存储单元(比如过道、侧面、机架等)的访问比较频繁且变化不大,因此将数据一直保留在内存中会比在需要时载入效率更高。此外,和原子存储单元的数量相比,在具体的仓库配置中聚合存储单元的数量要少得多,因此不会浪费过多的内存。
第二种方案:原子存储采用虚拟代理:
在原子存储单元(箱子、门、自卸、车灯)中支持Virtual Proxy,它的工作方法非常简单:首先从Storage 类派生出StorageProxy(存储代理)类,然后建立到具体AtomicStorage(原子存储)的关联,可以通过主键实现。当需要访问代理的时候,通过主键载入相应的存储单元数据并执行相关的操作,如下图所示。
提供基于代理的方案来访问原子存储单元增加了仓库拓扑领域对象的结构复杂性,然而, 一旦数据被载入到内存中,系统性能的提升远远大于设计上的付出。从性能优化的角度来说,如果原子存储单元的数据己经在内存中了,还可以绕过代理直接访问。