您可以捐助,支持我们的公益事业。

1元 10元 50元





认证码:  验证码,看不清楚?请点击刷新验证码 必填



  求知 文章 文库 Lib 视频 iPerson 课程 认证 咨询 工具 讲座 Model Center   Code  
会员   
   
 
     
   
 
 订阅
基于空间的架构风格
 
作者: 城里的月光_欧阳
   次浏览      
 2022-12-15
 
编辑推荐:
本文主要介绍了基于空间的架构风格相关内容。希望对你的学习有帮助。
本文来自于简书,由火龙果软件Linda编辑、推荐。

大多数基于web的业务应用遵循相同的通用请求流程:来自浏览器的请求先到达web服务器,然后是应用服务器,最后是数据库服务器。虽然这种模式对小用户量非常有效,但是随着用户负载的增加,瓶颈开始出现,首先是在web服务器层,然后是在应用服务器层,最后是在数据库服务器层。对于解决用户负载增加产生的瓶颈,通常的反应是横向扩展web服务器。这是相对容易和便宜的方案,它有时可以解决瓶颈问题。然而,在大多数高用户负载的情况下,扩展web服务器层只会将瓶颈向下移动到应用服务器。扩展应用程序服务器可能比web服务器更复杂、更昂贵,而且通常只会将瓶颈转移到数据库服务器上,而数据库服务器的扩展则更加困难和昂贵。即使你可以扩展数据库,你最终得到的是一个三角形的拓扑结构,三角形最宽的部分是web服务器(最容易扩展),最小的部分是数据库(最难扩展),如图15-1所示。

在任何具有大量并发用户负载的大容量应用中,数据库通常是你可以并发处理多少事务的最终限制因素。虽然各种缓存技术和数据库扩展产品有助于解决这些问题,但事实仍然是,为极端负载扩展普通应用程序是一个非常困难的命题。

图15-1.传统的基于web的拓扑结构中的可扩展性限制

基于空间的架构风格是专门为解决涉及高可扩展性、弹性和高并发性问题而设计的。对于具有可变和不可预测的并发用户量的应用,它也是一种有用的架构风格。从架构上解决极端和可变的可扩展性问题通常比尝试扩展数据库或将缓存技术改造为不可扩展的架构要好。

一般拓扑结构

基于空间的体系结构得名于元组空间的概念,这种技术使用多个并行处理器通过共享内存进行通信。通过消除系统中作为同步约束的中央数据库,而利用自我复制的内存中的数据网格,实现了高可扩展性、高弹性和高性能。应用数据保存在内存中,并在所有活动处理单元之间进行复制。当处理单元更新数据时,它将数据异步发送到数据库,通常是通过具有持久化队列的消息传递。处理单元随着用户负载的增加和减少而动态启动和关闭,从而解决了可变的可扩展性问题。因为在应用的标准事务处理中不涉及中央数据库,所以数据库瓶颈被消除,从而在应用中提供近乎无限的可扩展性。

几个架构组件组成了一个基于空间的架构:包含应用程序代码的处理单元、用于管理和协调处理单元的虚拟化中间件、异步地将更新数据发送到数据库的数据泵、从数据泵执行更新的数据写入器以及在启动时读取数据库数据并将其传递给处理单元的数据读取器。图15-2说明了这些主要的架构组件。

图15-2. 基于空间的架构的一般拓扑结构 

处理单元

处理单元(如图15-3所示)包含应用程序逻辑(或应用程序逻辑的一部分)。这通常包括基于web的组件以及后端业务逻辑。处理单元的内容因应用的类型而异。较小的web应用可能部署到单个处理单元中,而较大的应用可能会根据应用的功能划分为多个处理单元。处理单元还可以包含小型的、单一用途的服务(与微服务一样)。除了应用程序逻辑之外,处理单元还包含一个内存中的数据网格和复制引擎,通常通过Hazelcast、Apache Ignite和Oracle Coherence等产品实现。

图15-3.处理单元

虚拟化中间件

虚拟化中间件处理架构中控制数据同步和请求处理各个方面的基础设施问题。组成虚拟化中间件的组件包括消息传递网格、数据网格、处理网格和部署管理器。这些组件(将在下一节中详细描述)可以定制编写或通过购买第三方产品实现。

消息传递网格

消息传递网格,如图15-4所示,管理输入请求和会话状态。当一个请求进入虚拟化中间件时,消息传递网格组件确定哪些活动处理组件可用于接收请求,并将请求转发给这些处理单元之一。消息传递网格的复杂性可以从简单的循环算法到更复杂的next-available算法,该算法跟踪哪个请求由哪个处理单元处理。该组件通常使用具有负载均衡功能的传统web服务器(如HA-Proxy和Nginx)实现。

图15-4.消息传递网格

数据网格

数据网格组件可能是这种架构风格中最重要和最关键的组件。在大多数现代实现中,数据网格是作为复制缓存在处理单元中单独实现的。但是,对于那些需要外部控制器的复制缓存实现,或者在使用分布式缓存时,此功能将驻留在处理单元,以及虚拟化中间件中的数据网格组件中。由于消息传递网格可以将请求转发给任何可用的处理单元,因此每个处理单元在其内存数据网格中包含完全相同的数据是至关重要的。虽然图15-5显示了处理单元之间的同步数据复制,但实际上这是以异步和非常快速的方式完成的,通常在不到100毫秒的时间内完成数据同步。

图15-5.数据网格

数据在包含相同命名数据网格的处理单元之间同步。为了说明这一点,请考虑使用Hazelcast的以下Java代码,该代码为包含客户概要信息的处理单元创建一个内部复制的数据网格:

HazelcastInstance hz = Hazelcast.newHazelcastInstance(); 

Map<String, CustomerProfile> profileCache = 

hz.getReplicatedMap("CustomerProfile");

 

所有需要访问客户概要信息的处理单元都将包含此段代码。从任何处理单元对名为CustomerProfile的缓存所做的更改将使该更改复制到包含相同命名缓存的所有其他处理单元。处理单元可以包含完成其工作所需的任意数量的复制缓存。或者,一个处理单元可以远程调用另一个处理单元以请求数据(编排)或利用处理网格(在下一节中描述)来编制请求。

处理单元中的数据复制还允许服务实例上下移动,而不必从数据库中读取数据,前提是至少有一个实例包含命名的复制缓存。当一个处理单元实例启动时,它连接到缓存提供程序(如Hazelcast)并请求获取指定的缓存。当连接到其他处理单元后,缓存将从其中一个实例中加载。

每个处理单元通过使用成员列表了解所有其他处理单元实例。成员列表包含使用同一命名缓存的所有其他处理单元的IP地址和端口。例如,假设有一个处理实例包含客户概要文件的代码和复制的缓存数据。在这种情况下,只有一个实例,因此该实例的成员列表只包含自身,如使用Hazelcast生成的以下日志语句所示:

Instance 1:

Members {size:1, ver:1} [ 

Member [172.19.248.89]:5701 - 04a6f863-dfce-41e5-9d51-9f4e356ef268 this

]

 

当另一个处理单元使用相同的命名缓存启动时,两个服务的成员列表都会更新,以反映每个处理单元的IP地址和端口:

Instance 1:
Members {size:2, ver:2} [ 
Member [172.19.248.89]:5701 - 04a6f863-dfce-41e5-9d51-9f4e356ef268 this 
Member [172.19.248.90]:5702 - ea9e4dd5-5cb3-4b27-8fe8-db5cc62c7316

Instance 2:
Members {size:2, ver:2} [ 
Member [172.19.248.89]:5701 - 04a6f863-dfce-41e5-9d51-9f4e356ef268
Member [172.19.248.90]:5702 - ea9e4dd5-5cb3-4b27-8fe8-db5cc62c7316 this
]

 

当第三个处理单元启动时,实例1和实例2的成员列表都会更新以反映新的第三个实例:

Instance 1:

Members {size:3, ver:3} [ 

Member [172.19.248.89]:5701 - 04a6f863-dfce-41e5-9d51-9f4e356ef268 this 

Member [172.19.248.90]:5702 - ea9e4dd5-5cb3-4b27-8fe8-db5cc62c7316

Member [172.19.248.91]:5703 - 1623eadf-9cfb-4b83-9983-d80520cef753

Instance 2:

Members {size:3, ver:3} [ 

Member [172.19.248.89]:5701 - 04a6f863-dfce-41e5-9d51-9f4e356ef268

Member [172.19.248.90]:5702 - ea9e4dd5-5cb3-4b27-8fe8-db5cc62c7316 this 

Member [172.19.248.91]:5703 - 1623eadf-9cfb-4b83-9983-d80520cef753

Instance 3:

Members {size:3, ver:3} [ 

Member [172.19.248.89]:5701 - 04a6f863-dfce-41e5-9d51-9f4e356ef268

Member [172.19.248.90]:5702 - ea9e4dd5-5cb3-4b27-8fe8-db5cc62c7316

Member [172.19.248.91]:5703 - 1623eadf-9cfb-4b83-9983-d80520cef753 this

]

 

请注意,这三个实例都知道彼此(包括它们自己)。假设实例1接收到更新客户概要信息的请求。当实例1使用cache.put()或类似的缓存更新方法,数据网格(如Hazelcast)将使用相同的更新异步更新其他复制的缓存,确保所有三个客户概要文件缓存始终保持彼此同步。

当处理单元关闭时,其他处理单元自动更新以反映丢失的成员。例如,如果实例2关闭,实例1和实例3的成员列表将更新如下:

Instance 1:

Members {size:2, ver:4} [ 

Member [172.19.248.89]:5701 - 04a6f863-dfce-41e5-9d51-9f4e356ef268 this 

Member [172.19.248.91]:5703 - 1623eadf-9cfb-4b83-9983-d80520cef753

Instance 3:

Members {size:2, ver:4} [ 

Member [172.19.248.89]:5701 - 04a6f863-dfce-41e5-9d51-9f4e356ef268

Member [172.19.248.91]:5703 - 1623eadf-9cfb-4b83-9983-d80520cef753 this

]

 

处理网格

图15-6所示的处理网格是虚拟化中间件中的一个可选组件,当单个业务请求中涉及多个处理单元时,它管理编排好的请求处理。如果请求需要处理单元类型(例如,订单处理单元和付款处理单元)之间的协调,则处理网格将在这两个处理单元之间协调和编排请求。

图15-6. 处理网格

部署管理器

部署管理器组件根据负载条件管理处理单元实例的动态启动和关闭。此组件持续监控响应时间和用户负载,在负载增加时启动新的处理单元,在负载降低时关闭处理单元。这是一个在应用中实现可变可伸缩性(弹性)需求的关键组件。

数据泵

数据泵是一种将数据发送到另一个处理器的方法,然后另一个处理器更新数据库中的数据。数据泵是基于空间的架构中的一个必要组件,因为处理单元不直接读写数据库。数据泵在基于空间的架构中始终是异步的,提供与内存缓存和数据库的最终一致性。当处理单元实例接收到请求并更新其缓存时,该处理单元成为更新的所有者,因此负责通过数据泵发送更新,以便最终更新数据库。

数据泵通常使用消息传递来实现,如图15-7所示。在使用基于空间的架构时,消息传递是数据泵的一个不错的选择。消息传递不仅支持异步通信,还支持通过先进先出(FIFO)队列保证传递和保持消息顺序。此外,消息传递在处理单元和数据写入器之间提供了解耦,以便在数据写入器不可用的情况下,仍可以在处理单元内进行不间断的处理。

图15-7.用于向数据库发送数据的数据泵

在大多数情况下会有多个数据泵,每一个通常专用于特定的领域或子领域(如客户或库存)。数据泵可以专用于每种类型的缓存(例如CustomerProfile、CustomerWishlist等),也可以专用于包含更大的和通用缓存的处理单元领域(如Customer)。

数据泵通常具有关联的契约,包括与契约数据相关联的操作(添加、删除或更新)。契约可以是一个JSON模式、XML模式、一个对象,甚至是值驱动的消息(包含名称-值对的映射消息)。对于更新,数据泵消息中包含的数据通常只包含新的数据值。例如,如果客户更改了其概要文件中的电话号码,则只会发送新的电话号码以及客户ID和更新数据的操作。

数据写入器

数据写入器组件接受来自数据泵的消息,并用数据泵消息中包含的信息更新数据库(见图15-7)。数据写入器可以实现为服务、应用或数据中心(如Ab Initio)。数据写入器的粒度可以根据数据泵和处理单元的范围而变化。

基于领域的数据写入器包含处理特定领域(如Customer)中的所有的更新所需的数据库逻辑,而不管它接受的数据泵数量是多少。请注意在图15-8中,有四个代表各自客户领域(Profile、WishList、Wallet和Preferences)的不同处理单元和数据泵,但只有一个数据写入器。单个客户数据写入器监听所有四个数据泵,并包含必要的数据库逻辑(如SQL),以更新数据库中与客户相关的数据。

图15-8. 基于领域的数据写入器 

或者,每类处理单元都可以有自己的专用数据写入器组件,如图15-9所示。在这个模型中,数据写入器专用于每个相应的数据泵,并且只包含特定处理单元(如钱包)的数据库处理逻辑。虽然此模型往往会生成太多的数据写入器组件,但由于处理单元、数据泵和数据写入器的联合,它确实提供了更好的可扩展性和灵活性。

图15-9.每个数据泵的专用数据写入器

数据读取器

数据写入器负责更新数据库,而数据读取器负责从数据库中读取数据并通过反向数据泵将其发送到处理单元。在基于空间的架构中,只有在以下三种情况下才会调用数据读取器:同一命名缓存的所有处理单元实例崩溃、同一命名缓存中所有处理单元的重新部署,或检索复制缓存中未包含的存档数据。在所有实例都停止运行的情况下(由于系统大面积崩溃或所有实例的重新部署),必须从数据库中读取数据(这在基于空间的架构中通常是避免的)。

当一类处理单元的实例开始启动时,每个实例都试图在缓存上获取一个锁。第一个获得锁的成为临时缓存所有者;其他人进入等待状态,直到锁被释放为止(这可能会因使用的缓存实现类型而异,但无论如何,在这种情况下,缓存会有一个主所有者)。要加载缓存,获得临时缓存所有者状态的实例将向请求数据的队列发送消息。数据读取器组件接受读取请求,然后执行必要的数据库查询逻辑来检索处理单元所需的数据。当数据读取器从数据库中查询数据时,它将数据发送到另一个队列(称为反向数据泵)。临时缓存所有者处理单元从反向数据泵接收数据并加载缓存。一旦加载了所有数据,临时所有者将释放缓存上的锁,然后所有其他实例将被同步,这时候处理可以开始。该处理流程如图15-10所示。

图15-10. 带反向数据泵的数据读取器 

与数据写入器类似,数据读取器也可以基于领域或专用于一个特定的处理单元类(通常也是这种形式)。实现方式也与数据写入器相同,要么是服务、应用或者数据中心。

数据写入器和数据读取器本质上形成了通常所说的数据抽象层(在某些情况下是数据访问层)。两者之间的区别在于处理单元对数据库中表(或模式)结构的详细了解程度。数据访问层意味着处理单元耦合到数据库中的底层数据结构,并且只使用数据读写器间接访问数据库。另一方面,数据抽象层意味着处理单元通过单独的契约与底层数据库表结构解耦。基于空间的架构通常依赖于数据抽象层模型,因此每个处理单元中的复制缓存模式可以不同于底层数据库表结构。这允许对数据库进行增量变更,而不对处理单元造成影响。为了促进这种增量变更,数据写入器和数据读取器包含转换逻辑,以便在列类型更改、列或表被删除时,数据读取器和数据编写器可以缓冲数据库变更,直到可以对处理单元缓存进行必要的更改。

数据冲突

当在活动/活动状态下使用复制缓存时,其中包含相同命名缓存的任何服务实例都可能发生更新,而由于复制延迟,可能会发生数据冲突。当在一个缓存实例(缓存A)中更新数据,并且在复制到另一个缓存实例(缓存B)的过程中,相同的数据被该缓存(缓存B)更新时,就会发生数据冲突。在这种情况下,缓存B的本地更新将被来自缓存A的旧数据通过复制覆盖,而通过复制,缓存A中的相同数据将被来自缓存B的更新覆盖。

为了说明这个问题,假设有两个服务实例(服务A和服务B)包含产品库存的复制缓存。下面的流程演示了数据冲突问题:

- 当前蓝色小装置的库存数量是500台

- 服务A将蓝色小装置的库存缓存更新到490台(售出10台)

- 在复制期间,服务B将蓝色小装置的库存缓存更新到495个单元(售出5个)

- 由于从服务A更新进行复制,服务B缓存更新为490台

- 由于从服务B更新进行复制,服务A缓存将更新到495台

- 服务A和B中的缓存都不正确且不同步(库存应为485台)

有几个因素会影响可能发生的数据冲突数量:包含相同缓存的处理单元实例的数量、缓存的更新速率、缓存大小,最后是缓存产品的复制延迟时间。根据这些因素,用于确定可能发生多少潜在数据冲突的概率公式如下:

其中,N表示使用相同命名缓存的服务实例数,UR表示更新速率(以毫秒为单位,取平方),S表示缓存大小(根据行数来统计),RL表示缓存产品的复制延迟。

此公式对于确定可能发生的数据冲突百分比以及使用复制缓存的可行性非常有用。例如,考虑以下值作为此计算中涉及的系数:

更新速率(UR): 20次/秒
实例数量(N): 5
缓存大小(S): 50,000行
复制延迟(RL): 100毫秒
更新次数: 72,000/小时
冲突概率: 14.4次/小时
百分比: 0.02%

 

将这些因素应用到公式中,每小时可以得到72,000次更新,同一数据的14次更新很有可能发生冲突。考虑到百分比比较低(0.02%),复制将是一个可行的选择。

不同的复制延迟对数据的一致性有很大的影响。复制延迟取决于许多因素,包括网络类型和处理单元之间的物理距离。由于这个原因,复制延迟值很少在产品中注明,必须根据生产环境中的实际测量值进行计算和派生。

如果实际的复制延迟(我们经常用来确定数据冲突的数量)不可用,那么前面示例中使用的值(100毫秒)是一个很好的规划数。例如,将复制延迟从100毫秒更改为1毫秒,会产生相同数量的更新(每小时72000次),但每小时只产生0.1次冲突的可能性!该场景如下表所示:

更新速率(UR):  20次/秒

实例数量(N): 5

缓存大小(S): 50,000行

复制延迟(RL): 1毫秒(从100变成)

更新次数: 72,000/小时

冲突概率: 0.1次/小时

百分比: 0.0002%

 

包含相同命名缓存的处理单元数(通过实例数因子表示)也与可能发生的数据冲突数成正比。例如,将处理单元的数量从5个实例减少到2个实例,在每小时72000个更新中,数据冲突率仅为每小时6个:

更新速率(UR):  20次/秒

实例数量(N): 2(从5变成)

缓存大小(S): 50,000行

复制延迟(RL): 100毫秒

更新次数: 72,000/小时

冲突概率: 5.8次/小时

百分比: 0.008%

 

缓存大小是唯一与冲突率成反比的因素。当缓存大小减小时,冲突率增加。在我们的示例中,将缓存大小从50,000行减少到10,000行(并保持所有因素与第一个示例相同)的冲突率为每小时72,明显高于50,000行的情况:

更新速率(UR): 20次/秒

实例数量(N): 5

缓存大小(S): 10,000行(从50,000变成)

复制延迟(RL): 100毫秒

更新次数: 72,000/小时

冲突概率: 72次/小时

百分比: 0.1%

 

在正常情况下,大多数系统在一段长的时间内没有相同的更新速率(UR)。因此,当使用此计算公式时,了解峰值使用期间的最大更新速率并计算最小、正常和峰值冲突率是很有帮助的。

云端与内部实现的对比

当涉及到部署的环境时,基于空间的架构提供了一些独特的选择。整个拓扑,包括处理单元、虚拟化中间件、数据泵、数据读取器和写入器以及数据库,都可以部署在基于云的环境和本地内部环境。然而,这种架构风格也可以部署在这些环境之间,提供了一个其他架构风格所没有的独特功能。

这种架构风格的一个强大功能(如图15-11所示)是通过处理单元和虚拟化中间件在托管云环境中部署应用程序,同时保留物理数据库和相应的数据在本地环境。由于异步数据泵和这种架构风格的最终一致性模型,这种拓扑支持非常有效的基于云的数据同步。事务处理可以在基于云的动态和弹性环境中进行,同时在安全和本地内部环境中保留物理数据管理、报告和数据分析。

图15-11.云端和内部环境的混合拓扑

复制缓存与分布式缓存对比

基于空间的架构依赖于缓存来进行应用程序的事务处理。消除对数据库的直接读写需求是基于空间的架构能够支持高扩展性、高弹性和高性能的原因。基于空间的架构主要依赖于复制缓存,但也可以使用分布式缓存。

使用复制缓存,如图15-12所示,每个处理单元都包含自己的内存中数据网格,该网格在使用相同名称缓存的所有处理单元之间同步。当任何一个处理单元中的缓存发生更新时,其他处理单元将自动使用新的信息进行更新。

图15-12. 处理单元之间的复制缓存 

复制缓存不仅速度极快,而且还支持高级别的容错性。由于没有中央服务器持有缓存,所以复制缓存没有单点故障的问题。但是,根据所使用的缓存产品的实现,此规则可能会有例外。有些缓存产品需要有一个外部控制器来监视和控制处理单元之间的数据复制,但是大多数产品公司都在放弃这种模式。

虽然复制缓存是基于空间的架构的标准缓存模型,但在某些情况下不可能使用复制缓存。这些情况包括大数据量(缓存大小)和缓存数据的高更新速率。由于每个处理单元使用的内存过大,超过100MB的内部内存缓存可能会开始导致弹性和高可扩展性方面的问题。处理单元通常部署在虚拟机中(或者在某些情况下代表虚拟机)。每个虚拟机只有一定数量的内存可供内部缓存使用,从而限制了可启动以处理高吞吐量情况的处理单元实例的数量。此外,如“数据冲突”一节所示,如果缓存数据的更新速率太高,数据网格可能无法跟上高更新速率,以确保所有处理单元实例的数据一致性。当出现这些情况时,可以使用分布式缓存。

分布式缓存,如图15-13所示,需要一个外部服务器或服务来持有一个集中的缓存。在这个模型中,处理单元不在内存中存储数据,而是使用专有协议从中央缓存服务器访问数据。分布式缓存支持高级别的数据一致性,因为数据都在一个位置,不需要复制。但是,此模型的性能低于复制缓存,因为缓存数据必须远程访问,这增加了系统的总体延迟。容错性也是分布式缓存的一个问题。如果包含数据的缓存服务器出现故障,则无法从任何处理单元访问或更新任何数据,使它们无法运行。可以通过镜像分布式缓存来减轻容错性问题,但如果主缓存服务器意外停机,并且数据无法到达镜像缓存服务器,则可能会出现一致性问题。

图15-13.处理单元之间的分布式缓存

当缓存的大小相对较小(小于100 MB)并且缓存的更新率足够低,以至于缓存产品的复制引擎能够跟上缓存更新时,使用复制缓存和分布式缓存之间的决策将变成数据一致性对比性能和容错性的取舍。分布式缓存总是比复制缓存提供更好的数据一致性,因为数据缓存在一个位置(而不是分散在多个处理单元上)。但是,使用复制缓存时,性能和容错性总是更好。很多时候,这个决定归结为在处理单元中缓存的数据类型。对高度一致的数据的(如可用产品的库存计数)需要通常有必要使用分布式缓存,而不经常更改的数据(如名称/值对、产品代码和产品描述等参考数据)通常有必要使用一个复制缓存以进行快速查找。表15-1列出了一些选择标准,可作为选择何时使用分布式缓存还是使用复制缓存的指引。

表15-1.分布式缓存与复制缓存对比

在选择与基于空间的架构一起使用的缓存模型类型时,请记住,在大多数情况下,这两种模型都适用于任何给定的应用上下文。换句话说,复制缓存和分布式缓存都不能解决所有问题。与其试图通过一个横跨整个应用的单一的缓存模型寻找妥协方案,不如利用每一个模型的优点。例如,对于维护当前库存的处理单元,选择分布式缓存模型以实现数据一致性;对于维护客户概要信息的处理单元,选择复制缓存以提高性能和容错性。

“近缓存”考虑事项

近缓存是一种缓存混合模型,它将内存中的数据网格与分布式缓存连接起来。在这个模型中(如图15-14所示),分布式缓存被称为全备份缓存(full backing cache),每个处理单元中包含的每个内存中的数据网格被称为前端缓存(front cache)。前端缓存始终包含完整备份缓存的较小子集,它利用逐出策略删除旧项目,以便添加新的项目。前端缓存可以是包含最近使用项目的最近使用缓存(MRU),也可以是包含最常用项目的最常用缓存(MFU)。或者,可以在前端缓存中使用随机替换逐出策略,以便在需要空间添加新项目时以随机方式删除旧项目。当没有明确的数据分析时,无论是最新使用的还是最频繁使用的,随机替换(RR)是一个很好的逐出策略。

图15-14.近缓存拓扑结构

虽然前端缓存始终与全备份缓存保持同步,但每个处理单元中包含的前端缓存在共享相同数据的其他处理单元之间不同步。这意味着共享同一数据上下文(如客户概要信息)的多个处理单元在其前端缓存中可能有不同的数据。这会导致处理单元之间的性能和响应能力不一致,因为每个处理单元在前端缓存中包含不同的数据。因此,我们不建议在基于空间的架构中使用近缓存模型。

实施示例

基于空间的架构非常适合于用户或请求量剧增的应用,以及吞吐量超过10,000个并发用户的应用。基于空间的架构的例子包括在线音乐会票务系统和在线拍卖系统等应用。这两个例子都需要高性能、高扩展性和高弹性。

音乐会票务系统

音乐会票务系统有一个独特的问题:在一场流行音乐会宣布之前,并发用户量相对较低。一旦音乐会门票开始销售,用户量通常会从几百个并发用户激增到几千个(可能是上万个,具体取决于哪一场演唱会),所有人都试图获得音乐会的门票(并希望是好的座位!)。门票通常在几分钟内就会卖完,这需要基于空间的架构所支持的架构特性来支持。

与这种系统相关的挑战很多。首先,不管座位偏好如何,门票的数量是一定的。考虑到大量并发请求,座位是否可以预定的信息必须不断更新并且尽可能快地提供。另外,假设指定座位是一个选项,座位可用性也必须尽快更新。对于这种类型的系统,连续地同步访问一个中央数据库可能行不通。对于一个典型的数据库来说,在这种规模和更新频率的水平上,通过标准数据库事务来处理数以万计的并发请求是非常困难的。

基于空间的体系结构非常适合音乐会售票系统,因为这种应用需要高弹性。想要购买音乐会门票的并发用户数量的瞬时增加会立即被部署管理器发现,而部署管理器又会启动大量的处理单元来处理大量的请求。最佳情况下,部署管理器将被配置为在门票发售之前不久启动所需数量的处理单元,因此在用户负载显著增加之前让这些实例处于待命状态。

在线拍卖系统

在线拍卖系统(对拍卖中的物品进行竞价)与前面描述的在线音乐会票务系统具有相同的特性,这两个系统都需要高水平的性能和弹性,并且在用户和请求负载方面都有不可预测的峰值。当一场拍卖开始时,没有办法确定有多少人将参加拍卖,以及这些人中,每一个要价将有多少人同时出价。

基于空间的架构非常适合这种类型的问题域,因为随着负载的增加,可以启动多个处理单元;随着拍卖的结束,闲置的处理单元可能会被销毁。每个拍卖都可以使用单独的处理单元,以确保与投标数据的一致性。此外,由于数据泵的异步性质,投标数据可以在没有太多延迟的情况下发送到其他单元处理(如投标历史记录、投标分析和审计),从而提高投标过程的总体性能。

架构特性评级

特性评级表中的一星级评级(如图15-15所示)意味着特定的架构特性在某种架构中没有得到很好的支持,而五星评级意味着架构特性是某种架构风格中最强大的特性之一。记分卡中确定的每个特性的定义见第4章。

图15-15.基于空间的架构特性评级

请注意,基于空间的架构最大限度地提高了弹性、可扩展性和性能(均为五星级)。这些是这种架构风格的驱动属性和主要优势。所有这三个架构特性的高评级都是通过利用内存中的数据缓存和删除数据库约束来实现的。因此,使用这种架构风格可以处理数百万并发用户。

虽然高层次的弹性、可扩展性和性能是这种架构风格的优势,但这种优势特别是在总体的简单性和可测试性方面需要作出权衡。基于空间的架构是一种非常复杂的架构风格,因为使用了缓存和主数据存储的最终一致性。必须注意需要确保在这种架构风格的众多移动部件中的任何一个发生崩溃时不会丢失数据(请参阅第14章中的“防止数据丢失”)。

由于模拟这种架构风格所支持的高级别的可扩展性和弹性所涉及的复杂性,可测试性得到了一星级的评级。在峰值负载下测试成百上千的并发用户是一项非常复杂和昂贵的任务,因此,大多数高容量测试都是在实际极端负载的生产环境中进行的。这会对生产环境中的正常操作产生极大的风险。

在选择这种架构风格时,成本是另一个考虑因素。基于空间的架构的实现相对比较昂贵,主要是由于缓存产品的许可费,以及由于高可扩展性和弹性所需要的云端和本地内部系统的高资源使用率。

很难确定基于空间的架构的分区类型,因此我们将其标识为既是领域分区,也是技术分区。基于空间的架构是按领域划分的,这不仅是因为它与特定类型的领域(高弹性和可扩展的系统)保持一致,而且还因为处理单元的灵活性。处理单元可以扮演领域服务,与基于服务的架构和微服务架构中所定义的服务一样的方式。同时,基于空间的架构是按技术划分的,它通过数据泵将使用缓存的事务处理与数据库中数据的实际存储分离开来。在如何处理请求方面,处理单元、数据泵、数据读取器和写入器以及数据库都形成了一个技术层,与如何构造单体n层(分层)架构方面非常相似。

基于空间的架构中的量子数可以根据用户界面的设计方式以及处理单元之间的通信方式而变化。因为处理单元不与数据库同步通信,所以数据库本身不是量子方程的一部分。因此,基于空间的架构中的量子通常是通过各种用户接口和处理单元之间的关联来描绘的。彼此同步通信的处理单元(或通过编排的处理网格同步通信)都将是同一个架构量子的一部分。

   
次浏览       
相关文章

中央计算的软件定义汽车架构设计
汽车电子控制系统中的软件开发过程
一文读懂汽车芯片-有线通信芯片
OTA在汽车上有哪些难点痛点?
相关文档

汽车设计-汽车的整体结构及动力系统
自动驾驶汽车软件计算框架
SysML在汽车领域的应用实践
电子电气架构-大陆汽车系统架构平台
相关课程

AutoSAR原理与实践
功能安全管理体系(基于ISO26262)
MBSE(基于模型的系统工程)
基于SOA的汽车电子架构设计与开发

最新活动计划
QT应用开发 11-21[线上]
C++高级编程 11-27[北京]
LLM大模型应用与项目构建 12-26[特惠]
UML和EA进行系统分析设计 12-20[线上]
数据建模方法与工具 12-3[北京]
SysML建模专家 1-16[北京]
 
 
最新文章
在EA中内嵌文档- Artifact
EA中模型视图
EA中的实体关系图
使用EA进行风险建模
EA中的项目词汇表
EA的模型导出或导入csv文件
自定义表格(Custom Table)在EA中的使用
Gap Analysis Matrix(差距分析矩阵)
更多...   
MBSE工具
MBSE平台
建模工具 EA
模型库-Model Center
需求管理-ReqManager
自动建模-Modeler
多级仿真-Sys Simulator
代码工程-Code Engineer
文档生成器-DocGenerator
更多...   
成功案例
广汽研究院 SysML+EA+软件分析设计
高合汽车研发部门 建模工具EA、WebEA、学习视频
国汽智联 建模工具EA、模型库、WebEA和iSpace
亿咖通 MBSE工程体系与工具链咨询
中航无人机 MBSE工具链
吉利汽车 购买EA工具
华科汽车零部件 购买EA工具
东风岚图汽车 购买EA工具 以及EA定制开发
更多...