以内存为中心的分布式数据库、缓存和处理平台,用于事务性、分析性和流式工作负载,提供内存速度在PB级规模。
Ignite 为应用和不同的数据源之间提供一个高性能、分布式内存中数据组织管理的框架。
Ignite作为分布式内存数据库,它支持ACID事务,支持SQL语句,Key-value,计算器,机器学习和其他数据处理的API。
Ignite持久化的内存架构允许数据和索引存储在内存和硬盘中。硬盘持久化式可选的,开启了硬盘持久化后,Ignite可以存储更多的数据,并将作为一个完整的分布式数据库。
在完整数据和索引都适用于内存时,并且持久化禁用的情况下,Ignite将作为内存数据库运行,支持sql以及所有现有的仅用于内存的API。
Ignite SQL有个明显的特征,就是支持分布式SQL连接,在并置和非并置下都可以工作。当并置时,连接可以在每个节点上可用的本地数据上执行,而不必再网络传输数据。并置模式在分布式系有优秀的扩展性和卓越的性能。
Ignite提供了丰富Key-value的相关的API,使Ignite能够作为内存网格来运行。你可以把Ignite看作一个分布式分区哈希图,每个节点拥有整个数据集的一部分。和其他的内存网格存储不同,Ignite能把数据存储在内存和硬盘,因此能够存储更多的数据在物理内存。
Ignite网格数据时现在在分布式系统中实现ACID事务或者原子数据更新最快的实现方式之一。我们知道这一点,因为我们不断地对它进行基准测试。
第三方数据库
Inite内存数据网格可以通过作为应用程序层和数据库层之间的分布式缓存来提高现有第三方数据库(如RDBMS,NoSQL或基于Hadoop的存储)的性能和可伸缩性。此方法不需要对现有数据进行翻转和替换,并且会自动直写或读取所有对基础数据库的更新或读取。Ignite将自动与基础数据库事务合并,为用户提供透明的事务行为。
但是,这种方法也有其局限性。例如,SQL或扫描查询将只包含存储在内存中的结果,而不包含在外部数据库中,因为Ignite无法索引外部数据。如果您需要通过SQL查询对磁盘上的数据建立索引并进行访问,我们建议您查看 Ignite本地持久性。
Ignite database caching在 数据网格 组件中实现。它使用户能够将最常访问的数据保存在内存中,方法是在一组计算机上对其进行分区或复制。
直写和通读
只要内存中缓存发生更新,Ignite就可以选择将其传播到底层数据库。此外,无论何时从缓存请求数据并且不在那里,Ignite都可以自动从底层数据库加载数据。这种行为被称为write-through并 read-through相应地。
后写
在简单的直写模式下,每个缓存放置和移除操作都将涉及到对持久性存储的相应请求,因此缓存更新的总体持续时间可能相对较长。为了缓解这种情况,Ignite提供了执行异步持久存储更新(也称为)的选项 write-behind。
Ignite自动控制数据如何分区,但是,用户可以插入他们自己的分发(亲和)功能并将各种数据组合在一起以提高效率。Ignite支持用于建模和访问数据的键值和SQL。另外,Ignite还提供强大的处理API,用于在分布式数据上进行计算。
Apache Ignite可以用作支持SQL,键值,计算,机器学习和其他数据处理API的一体化分布式数据库。
无论您决定使用哪种API,都始终将数据存储在支持群集的基于页面的存储中,以尝试平均分配数据,从而保证每个群集节点都拥有整个数据集的一部分。
如果Ignite Native Persistence已启用,则数据和索引可以存储在RAM中,也可以存储在磁盘上 。
Ignite本地持久性存储利用磁盘允许Ignite用户存储和处理超出内存容量的数据。它还增加了额外的弹性和崩溃恢复功能,并支持完全集群重启而不会丢失数据。而且,持续打开时,群集重启几乎是瞬间完成,因为Ignite可立即从磁盘运行,而无需预先加载内存中的所有数据。SQL
Ignite符合ANSI-99标准,支持大多数SQL和DML命令,包括SELECT,UPDATE,INSERT,MERGE,DELETE语句和分布式连接。它还提供对DDL命令子集的支持,包括表和索引的CREATE和ALTER命令。
核心价值
Ignite可用于分布式键值存储,支持所有类地图键值操作,包括并发CAS操作。它还为分布式ACID事务,连续查询,并置处理等提供了丰富的支持。Ignite键值存储完全符合 JCache(JSR 107)规范。
并置处理
大多数以磁盘为中心的数据库(如RDBMS或NoSQL)通常采用传统的客户端 - 服务器方法,数据从服务器传送到客户端,然后在该客户端处理并丢弃数据。这种方法不能很好地扩展,因为通过网络移动数据是分布式系统中最昂贵的操作。
可扩展性更强的方法是 并置处理,通过将计算带入数据实际驻留的服务器来逆转流程。这种方法可以让您执行高级逻辑或分布式SQL,而JOIN完全位于数据存储位置,避免了昂贵的序列化和网络跳闸。
分区和复制
根据配置,Ignite可以分区或复制数据。与REPLICATED其中数据在群集中的所有节点上完全复制的模式不同,在PARTITIONED模式中,Ignite将同样将数据分割到多个群集节点上,从而允许在内存和磁盘上存储数TB的数据。
冗余
Ignite还允许配置多个备份副本,以确保在发生单个节点或服务器故障时的数据弹性。
一致性
无论使用哪种复制方案,Ignite都可以保证所有集群成员的数据一致性。
虽然Ignite旨在像其他任何关系SQL数据库一样行事,但Ignite在处理约束和索引方面存在差异。Ignite支持主索引和二级索引,但唯一性只能针对主索引执行。Ignite也不支持外键约束。
Apache Ignite的SQL支持级别非常广泛,因此该平台被广泛用作成熟的SQL数据库。将Ignite的SQL功能与其分布式核心结合在一起,您可以获得水平可扩展,容错且始终可用的SQL数据库。
性能和耐久性
借助Ignite Durable Memory 体系结构,可以将数据和索引存储在内存中,也可以存储在磁盘上。这允许跨不同内存层执行分布式SQL操作,并通过磁盘的持久性实现内存中性能。如果磁盘层 被禁用,则可以将Apache Ignite用作 内存数据库。
Ignite中的本地持久性可以打开和关闭。这使Ignite可以存储大于可用内存容量的数据集。如果持久化关闭,那么Ignite就可以作为一个分布式的内存数据库或者内存数据网格,这完全取决于使用SQL和键-值API的喜好。如果持久化打开,那么Ignite就成为一个分布式的,可水平扩展的数据库,它会保证完整的数据一致性以及集群故障的可恢复能力。
由于它是以内存为中心的存储,因此Ignite被广泛用作现有第三方数据库(如RDBMS,Apache Cassandra或MongoDB)上的缓存层(又名数据网格)。此模式用于加速保留数据的底层数据库。与此同时,Ignite具有自己的持久性,这被认为是Ignite集群的备用和更好的持久层。
启用本地持久性后,Ignite始终将数据超集存储在磁盘上,并尽可能在RAM中存储。例如,如果有100个条目,并且RAM只能存储20个,那么所有100个条目都将存储在磁盘上,而只有20个条目会被缓存到RAM中以获得更好的性能。
就像其他NoSQL数据库一样,Ignite具有高可用性和水平可扩展性。但是,与其他NoSQL数据库不同,Ignite支持跨多个集群节点的SQL和ACID事务。
Ignite可以分区和复制数据。不像完全复制模式那样把数据完全的拷贝到所有的集群节点中。分区模式下,Ignite能够平均的把数据存储到各个集群节点中,从而能够再内存和硬盘中保存TB级别的数据。
与最终一致的NoSQL数据库不同,Ignite可以以高度一致的模式运行,确保所有群集节点之间的数据一致性。另外,ignte支持 可跨越多个密钥acrsoss多个集群ndoes和分区的ACID事务。
Ignite和NoSQL数据库之间的另一个区别是,首先,内存被视为功能齐全的存储,而不仅仅像大多数数据库那样是缓存层。其次,除了 键值 API之外,Ignite还支持 分布式SQL和并 置处理方法。
Ignite对于ACID 事务的支持仅限于键值API级别。Ignite还支持交叉分区事务,这意味着事务可以跨越驻留在不同服务器上不同分区中的密钥。
原子模式
Ignite支持两种缓存操作模式,事务性和原子性。在该TRANSACTIONAL模式下,您可以将多个缓存操作分组到一个事务中,而该ATOMIC模式一次支持多个原子操作。该TRANSACTIONAL模式支持完全符合ACID的交易。在此模式下,您可以将多个缓存操作(在一个或多个密钥上)分组到单个逻辑操作(称为事务)中。这些操作将在指定键上执行而没有任何其他交错操作,并且将全部成功或全部失败。没有部分执行操作。为获得更好的性能,请使用该ATOMIC模式。只有TRANSACTIONAL在需要ACID兼容操作时才启用模式。该ATOMIC模式通过避免事务锁定来提供更好的性能,同时仍然为每个操作提供数据原子性和一致性。ATOMIC模式的另一个区别是批量写入,例如PutAll(…)和RemoveAll(…)方法不会在一个事务中执行,并且可能部分失败。
请注意:无论何时使用ATOMIC模式,都会禁用事务处理,这样可以在不需要事务处理的情况下实现更高的性能和吞吐量。
IgniteTransactions
IgniteTransactions 接口包含启动和完成事务的功能,以及订阅监听器或获取指标。
跨缓存事务
可以在一个事务中组合来自不同缓存的多个操作。注意它可以在一个 事务中更新不同类型的缓存,比如复制和分区 缓存。
近缓存事务
近缓存是完全事务化的,当数据在服务端改变时,会自动地获得更新 或者失效
两阶段提交(2PC)
Ignite为其事务使用两阶段提交(2PC)协议,并尽可能优化为单阶段提交。无论何时在事务内更新数据,Ignite都会将事务状态保存在本地事务映射中,直到commit()被调用,此时如果需要,数据将传输到参与的远程节点。
并发模式和隔离级别
当原子化模式配置为事务时,Ignite对事务支持乐观和悲观的并发模型。并发模型决定了何时获得一个条目级的事务锁-在访问数据时或者在prepare阶段。锁定可以防止对一个对象的并发访问。比如,当试图用悲观锁更新一个ToDo列表项时,服务端会在该对象上置一个锁以使其他的事务或者操作无法更新同一个条目,直到提交或者回滚该事务。不管在一个事务中使用那种并发模型,在提交之前都存在事务中的所有条目被锁定的时刻。
隔离级别定义了并发事务如何"看"以及处理针对同一个键的操作。Ignite支持读提交、可重复读、可序列化隔离级别。
并发模型和隔离级别的所有组合都是可以同时使用的。下面是针对Ignite提供的每一个并发-隔离组合的行为和保证的描述。
悲观交易,乐观交易,死锁检测,无死锁事务,与Jta整合。这五种的具体问题查看原文文档。
当处理分布式事务时必须要遵守的主要规则是参与一个事务的键的锁,必须按照同样的顺序获得,违反这个规则就可能导致分布式死锁。 Ignite无法避免分布式死锁,而是有一个内建的功能——死锁检测来使调试和解决这个问题更容易。
Apache Ignite带有兼容ANSI-99的可水平扩展和容错的分布式SQL数据库。通过在集群节点之间分区数据或通过完全复制来提供分发,具体取决于用例。
与许多分布式SQL数据库不同,Ignite 持久内存 将内存和磁盘视为活动存储层。磁盘层(即 本地持久性)在缺省情况下处于禁用状态,在这种情况下,Ignite将成为纯粹 的内存数据库(IMDB)。
Ignite的一个显着特点是完全支持 分布式SQL JOIN。Ignite可以以并置和非并置方式加入数据。当并置时,JOIN会在每个节点上可用的本地数据上执行,而无需在网络上移动大型数据集。这种方法在分布式数据库中提供了最佳的可伸缩性和性能。
Apache Ignite是一个完全支持分布式ACID事务的强大一致的平台。内存层和磁盘层都符合一致性保证。
a.两阶段提交协议
Apache Ignite中的事务可以跨越多个群集节点,高速缓存(又名表)和分区。悲观和乐观锁定可用于应用程序。乐观模式还支持无死锁事务,这有助于避免用户代码中发生分布式死锁。
在分布式系统中,事务可能跨越多个集群节点。显然,当我们要确保数据在所有参与节点间保持一致时,这会带来一些挑战。例如,在发生节点故障时,事务可能没有完全落实在丢失的节点上。在这种情况下确保数据一致性的一种广泛使用的方法是两阶段提交协议(2PC)。
b.一致性和本地持久性
如果使用Ignite本地持久性,那么即使群集或单个节点在事务中停机,所有更新也会写入提前写入日志(WAL)文件,以保证数据的一致性。WAL为单个节点或整个集群发生故障时的故障情况提供恢复机制。群集总是可以恢复到最近成功提交的事务。
c.一致性和第三方持久性
在Ignite用作第三方数据库(如RDBMS)之上的缓存层的情况下,Ignite事务将跨越缓存数据和外部数据库。例如,当将RDBMS用作持久层时,Ignite会在向参与群集节点发送提交消息之前将事务性更改写入数据库。这样,如果事务在数据库级别失败,Ignite仍然可以将回滚消息发送给涉及的每个节点,从而使内存中的高速缓存与外部数据库之间的数据保持一致。
以RDBMS或NoSQL为中心的以磁盘为中心的系统通常采用传统的客户端 - 服务器方式,数据从服务器传送到客户端,然后通常被丢弃。这种方法不能很好地扩展,因为通过网络移动数据是分布式系统中最昂贵的操作。
一种更具可扩展性的方法是collocated通过将计算带入数据实际所在的服务器来逆转流程。这种方法允许您使用JOIN来执行高级逻辑或分布式SQL,并精确地存储数据的位置,避免了昂贵的序列化和网络跳闸。
a.数据搭配
要开始从并置处理中受益,我们需要确保数据正确搭配在首位。如果业务逻辑需要访问多个条目,通常最好在单个集群节点上配置相关条目。这种技术也被称为 affinity collocation数据。
b.SQL和分布式JOIN
如果针对并置数据运行查询,则Apache Ignite SQL引擎将始终执行得更加高效。在集群内执行分布式JOIN尤其重要
c.分布式并置计算
大多数传统数据库是以客户机-服务器的模式运行的,这意味着数据必须发给客户端进行处理,这个方式需要在客户端和服务端之间进行大量的数据移动,通常来说不可扩展。而Ignite使用了另外一种方式,可以将轻量级的计算发给数据,即数据的并置计算,从结果上来说,Ignite扩展性更好,并且使数据移动最小化。
Ignite是一个分布式系统,因此,有能力将数据和数据以及数据和计算进行并置就变得非常重要,这会避免分布式数据噪声。当执行分布式SQL关联时数据的并置就变得非常的重要。Ignite还支持将用户的逻辑(函数,lambda等)直接发到数据所在的节点然后在本地进行数据的运算
Apache Ignite 2.0版本引入了自己的分布式机器学习(ML)库的第一个版本,称为ML Grid。构建ML Grid的基本原理非常简单。许多用户使用Ignite作为中央高性能存储和处理系统。如果他们想要执行ML或深度学习(DL)算法(即训练集或模型推理),他们可以直接在Ignite集群上运行它们,而无需将数据ETL数据转换为Apache Mahout或Apache Spark等其他系统。
Ignite具有非常先进的集群能力,包括逻辑集群组和自动发现。
Ignite节点之间会自动发现对方,这有助于必要时扩展集群,而不需要重启整个集群。开发者可以利用Ignite的混合云支持,允许公有云(比如AWS)和私有云之间建立连接,向他们提供两者的好处。
当工作在分布式环境中时,有时需要确保有这么一个节点,不管网络是否发生变化,这个节点通常被叫做leader(领导者)。
很多系统选举领导者通常要处理数据一致性,然后通常是通过收集集群成员的选票处理的。而在Ignite中,数据一致性是通过数据网格的类似功能处理的(Rendezvous Hashing或者HRW哈希),选择领导者在传统意义上的数据一致性,在数据网格以外就不是真的需要了。
Ignite集群的发现方法有很多种:
- 基于组播的发现、
- 基于静态IP的发现、
- 基于组播和静态IP的发现、
- 在同一个机器组中隔离Ignite集群、
- 基于JDBC的发现、
- 基于共享文件系统的发现、
- 基于ZooKeeper的发现。
Ignite中,通过DiscoverySpi节点可以彼此发现对方,Ignite提供了TcpDiscoverySpi作为DiscoverySpi的默认实现,它使用TCP/IP来作为节点发现的实现,可以配置成基于组播的或者基于静态IP的。TcpDiscoveryMulticastIpFinder使用组播来发现网格内的每个节点。他也是默认的IP搜索器。除非打算覆盖默认的设置否则不需要指定他。
Ignite针对越来越火的水平扩展概念而构建,具有实时按需增加节点的能力。他可以支持线性扩展到几百个节点,通过数据位置的强语义以及数据关系路由来降低冗余数据噪声。
Ignite数据网格是一个基于内存的分布式键值存储,他可以视为一个分布式的分区化哈希,每个集群节点都持有所有数据的一部分,这意味着随着集群节点的增加,就可以缓存更多的数据。
Ignite数据网格支持本地、复制的、分区化的数据集,允许使用标准SQL语法方便地进行跨数据集查询,同时还支持在内存数据中进行分布式SQL关联。 Ignite数据网格轻量快速,是目前在集群中支持数据的事务性和原子性的最快的实现之一。
只要集群仍然处于活动状态,即使节点崩溃或者网络拓扑发生变化,Ignite都会保证不同集群节点中的数据的一致性。
Ignite提供了三种不同的缓存操作模式,分区、复制和本地。缓存模型可以为每个缓存单独配置,缓存模型是通过CacheMode枚举定义的。
分区模式:
分区模式是扩展性最好的分布式缓存模式,这种模式下,所有数据被均等地分布在分区中,所有的分区也被均等地拆分在相关的节点中,实际上就是为缓存的数据创建了一个巨大的内存内分布式存储。这个方式可以在所有节点上只要匹配总可用存储(内存和磁盘)就可以存储尽可能多的数据,因此,可以在集群的所有节点的内存中可以存储TB级的数据。也就是说,只要有足够多的节点,就可以存储足够多的数据。
分区模式相对于复制模式来说,分区模式的更新效率高,因为每个键只需要更新一个主节点,而复制模式需要更新每一个节点。然后,在读操作时,分区模式的效率就低了。
为了避免额外的数据移动,总是访问恰好缓存有要访问的数据的节点是很重要的,这个方法叫做关系并置,当工作在分区化缓存时强烈建议使用。
复制模式:
复制模式中,所有数据都被复制到集群内的每个节点,因为每个节点都有效所以这个缓存模式提供了最大的数据可用性。然而,这个模式每个数据更新都要传播到其他所有节点,因而会对性能和可扩展性产生影响。这个模式适用于读缓存比写缓存频繁的多而且数据集较小的场景,如果应用超过80%的时间用于查找缓存,那么就要考虑使用复制缓存模式了。
本地模式:
本地模式是最轻量的模式,因为没有数据被分布化到其他节点。他适用于或者数据是只读的,或者需要定期刷新的场景中。当缓存数据失效需要从持久化存储中加载数据时,他也可以工作与通读模式。除了分布化以外,本地缓存包括了分布式缓存的所有功能,比如自动数据回收,过期,磁盘交换,数据查询以及事务。
关系并置
数据和计算以及数据和数据的并置可以显著地提升应用的性能和可扩展性。
数据和数据并置:
在许多情况下,如果不同的缓存键被同时访问的话那么将他们并置在一起是很有利的。通常来说业务逻辑需要访问不止一个的缓存键,通过将他们并置在一起可以确保具有同一个affinityKey的所有键都会缓存在同一个处理节点上,从而避免从远程节点获取数据的昂贵网络开销。
例如,有一个Person和Company对象,然后希望将Person对象和其工作的Company对象并置在一起。要做到这一点,用于缓存Person对象的缓存键应该有一个属性或者方法加注了@AffinityKeyMapped注解,他会提供用于并置的Company键的值,方便起见,也可以可选地使用AffinityKey类。
数据和计算并置:
也有向缓存数据的节点发送计算,这是一个被称为数据和计算的并置的概念,他可以向特定的节点发送整个的工作单元。
要将数据和计算并置在一起,需要使用IgniteCompute.affinityRun(…)和IgniteCompute.affinityCall(…)方法。
数据再平衡
当一个新节点加入集群时,已有节点会放弃一部分缓存条目的所有权转交给新的节点,以使整个网格在任何时候都保持键的均等平衡。
如果新的节点成为一些分区的主节点或者备份节点,他会从该分区之前的主节点获取数据,或者从该分区的备份节点之一获取数据。一旦分区全部载入新的节点,旧节点就会被标记为过时然后该节点在所有当前的事务完成之后最终会被退出。因此,在一些很短的时间段,在网络发生变化之后,有一种情况是在缓存中对于一个键备份的数量可能比事先配置的多。然而,一旦再平衡完成,额外的备份会被删除。
再平衡模式:
Ignite允许在所有节点之间使用SSL Socket进行通信。要使用SSL,需要设置Factory以及配置Ignite配置文件的SSL段落,Ignite提供了一个默认的SSL上下文工厂,org.apache.ignite.ssl.SslContextFactory,他用一个配置好的keystore来初始化SSL上下文。
Ignite允许使用不同的加密类型,支持的加密算法可以参照:http://docs.oracle.com/javase/7/docs/technotes/guides/security/StandardNames.html#SSLContext,可以通过setProtocol()方法进行设置,默认值是TLS。
Ignite数据加载和流处理功能可以以可扩展以及容错的方式处理持续不断的数据流或者在集群中预加载初始数据。在一个中等规模的集群中,数据注入Ignite或者预加载数据的速度可以很高,甚至轻易地达到每秒处理百万级的事件。
数据加载
从像Ignite持久化存储或者第三方存储这样的数据源中进行数据的预加载,在下面的5.2.数据加载章节中有详细描述。
工作方式
1.客户端节点通过Ignite数据流处理器向Ignite缓存中注入有限的或者持续的数据流;
2.数据在Ignite数据节点间自动分区,每个节点持有均等的数据量;
3.数据流可以在Ignite数据节点上以并置的方式直接并行处理;
4.客户端也可以在数据流上执行并发的SQL查询。
数据流处理器
数据流处理器是通过IgniteDataStreamerAPI定义的,他可以往Ignite数据流缓存中注入大量的持续不断的数据流,数据流处理器对于所有流入Ignite的数据以可扩展和容错的方式提供了至少一次保证。
查询数据
可以和Ignite的SQL、TEXT以及基于谓词的缓存查询一起使用Ignite数据索引能力的全部功能来在数据流中进行查询。
与已有的流处理技术集成
Ignite可以与各种主要的流处理技术和kuaig进行集成,比如Kafka、Camel、Storm或者JMS,从而为基于Ignite的架构带来更强大的流处理功能。
用标准的缓存put(…)和putAll(…)操作加载大量的数据通常是比较低效的。Ignite提供了IgniteDataStreamerAPI来与主要的流技术集成,还有CacheStoreAPI,他们有助于以一个更高效的方式将大量数据注入Ignite缓存。
数据流处理器是通过IgniteDataStreamerAPI定义的,他可以将大量的连续数据注入Ignite缓存。数据流处理器以可扩展和容错的方式在数据被发送到集群节点之前通过把批量数据放在一起以获得高性能。数据流处理器可以用于任何时候将大量数据载入缓存,包括启动时的预加载。
数据流处理器不参与事务。
快速地将大量的数据流注入Ignite的主要抽象是IgniteDataStreamer,在内部他会适当地将数据整合成批次然后将这些批次与缓存这些数据的节点并置在一起。
高速加载是通过如下技术获得的:
① 映射到同一个集群节点上的数据条目会作为一个批次保存在缓冲区中;
② 多个缓冲区可以同时共处;
③ 为了避免内存溢出,数据流处理器有一个缓冲区的最大数,他们可以并行的处理;
允许覆写
默认的话,数据流处理器不会覆写已有的数据,这意味着如果遇到一个缓存内已有的条目,他会忽略这个条目。这是一个最有效的以及高性能的模式,因为数据流处理器不需要在后台考虑数据的版本。
如果预想到数据可能在数据流缓存中可能存在以及希望覆写它,设置IgniteDataStreamer.allowOverwrite(true)即可。
Ignite可以以一个分布式的方式使用java.util.concurrent框架中的大多数数据结构。
Ignite为开发者提供了采用自己熟悉的数据结构的能力,然后将其用于集群环境。比如,可以使用java.util.concurrent.BlockingQueue,在一个节点将一些信息加入其中后从另一个节点获取它,或者持有一个分布式的基本类型生成器,他会在所有节点中保证唯一性。
当前,Ignite中支持如下的分布式数据结构:
- 队列和集合
- 原子化类型
- CountDownLatch
- ID生成器
- Semaphore
分布式计算是通过以并行的方式执行来获得高性能、低延迟和线性可扩展。Ignite计算网格提供了一套简单的API,使得可以在集群内的多台计算机上执行分布式计算和数据处理。分布式并行处理是基于在任何集群节点集合上进行计算和执行然后将结果返回实现的。
IgniteCompute接口提供了在集群节点或者一个集群组中运行很多种类型计算的方法,这些方法可以以一个分布式的形式执行任务或者闭包。
只要至少有一个节点有效,所有的作业和闭包就会保证得到执行,如果一个作业的执行由于资源不足被踢出,他会提供一个故障转移的机制。如果发生故障,负载平衡器会选择下一个有效的节点来执行该作业。
Ignite计算网格可以对集群或者集群组内的任何闭包进行广播和负载平衡,包括纯Java的runnables和callables。
闭包是一个代码块,他是把代码体和任何外部变量包装起来然后以一个函数对象的形式在内部使用他们,然后可以在任何传入一个变量的地方传递这样一个函数对象,然后执行。所有的apply方法都可以在集群内执行闭包。
IgniteCompute提供了一个方便的API以在集群内执行计算。虽然也可以直接使用JDK提供的标准ExecutorService接口,但是Ignite还提供了一个ExecutorService接口的分布式实现然后可以在集群内自动以负载平衡的模式执行所有计算。该计算具有容错性以及保证只要有一个节点处于活动状态就能保证计算得到执行,可以将其视为一个分布式的集群化线程池。
计算和数据的并置可以最小化网络中的数据序列化,以及可以显著地提升应用的性能和可扩展性。不管何时,都应该尽力地将计 算和缓存待处理数据的集群节点并置在一起。
affinityCall(…)和affinityRun(…)方法使作业和缓存着数据的节点位于一处,换句话说,给定缓存名字和关系键,这些方法会试图在指定的缓存中定位键所在的节点,然后在那里执行作业。
Ignite支持作业的自动故障转移,当一个节点崩溃时,作业会被转移到其他可用节点再次执行。然而在Ignite中也可以将任何作业的结果认为是失败的。工作的节点可以仍然是存活的,但是他运行在一个很低的CPU,I/O,磁盘空间等资源上,在很多情况下会导致应用的故障然后触发一个故障的转移。此外,也有选择一个作业故障转移到那个节点的功能,因为同一个应用内部不同的程序或者不同的计算也会是不同的。
FailoverSpi负责选择一个新的节点来执行失败作业。FailoverSpi检查发生故障的作业以及该作业可以尝试执行的所有可用的网格节点的列表。他会确保该作业不会再次映射到出现故障的同一个节点。故障转移是在ComputeTask.result(…)方法返回ComputeJobResultPolicy.FAILOVER策略时触发的。Ignite内置了一些可定制的故障转移SPI实现。
负载平衡组件将作业在集群节点之间平衡分配。Ignite中负载平衡是通过LoadBalancingSpi实现的,它控制所有节点的负载以及确保集群中的每个节点负载水平均衡。对于同质化环境中的同质化任务,负载平衡采用的是随机或者轮询的策略。然而在很多其他场景中,特别是在一些不均匀的负载下,就需要更复杂的自适应负载平衡策略。
LoadBalancingSpi采用前负载技术,即在将其发送到集群之前就对作业在某个节点的执行进行了调度。
注意: 当作业还没有与数据并置或者还没有在哪个节点上执行的倾向时,负载平衡就已经触发了。如果使用了数据和计算的并置,那么数据的并置优先于负载平衡。
检查点提供了保存一个作业中间状态的能力,他有助于一个长期运行的作业保存一些中间状态以防节点故障。重启一个故障节点后,一个作业会从保存的检查点载入然后从故障处继续执行。对于作业检查点状态,唯一必要的就是实现java.io.Serializable接口。
检查点功能可以通过GridTaskSession接口的如下方法启用:
ComputeTaskSession.loadCheckpoint(String)
ComputeTaskSession.removeCheckpoint(String)
ComputeTaskSession.saveCheckpoint(String, Object)
注意: 检查点因为性能的原因默认是禁用的,要启用它需要在任务或者闭包类上加注@ComputeTaskSessionFullSupport注解。
检查点的一个重要使用场景是避免“主”节点(启动了原来的执行的节点)的故障。当主节点故障时,Ignite不知道将作业的执行结果发送给谁,这样的话结果就会被丢弃。
这种情况下要恢复,可以先将作业的最终执行结果保存为一个检查点然后在”主”节点故障时有一个逻辑来重新运行整个任务。这时任务的重新运行会非常快因为所有的作业都可以从已保存的检查点启动。
Ignite中,作业是在客户端侧的任务拆分初始化或者闭包执行阶段被映射到集群节点上的。然而,一旦作业到达被分配的节点,就需要有序地执行。默认情况下,作业被提交到一个线程池然后随机地执行,如果要对作业执行顺序进行细粒度控制的话,需要启用CollisionSpi。
- FIFO排序
FifoQueueCollisionSpi可以使一定数量的作业无中断地以先入先出的顺序执行,所有其他的作业都会被放入一个等待列表,直>到轮到他。
并行作业的数量是由parallelJobsNumber配置参数控制的,默认值为2.- 优先级排序
PriorityQueueCollisionSpi可以为每个作业设置一个优先级,因此高优先级的作业会比低优先级的作业先执行。
任务优先级是通过任务会话中的grid.task.priority属性设置的,如果任务没有被赋予优先级,那么会使用默认值0。
服务网格可以在集群上部署任意用户定义的服务,比如自定义计数器,ID生成器,分层映射等。
Ignite可以控制每个集群节点应该部署多少个服务的实例,可以自动地确保所有的服务正确地部署和容错。
无论拓扑发生变化或者节点故障都会使部署的服务持续有效
在集群中自动地部署任意数量的分布式服务实例
自动地部署单例,包括集群单例、节点单例或者关系键单例
通过在配置中指定在节点启动时自动部署分布式服务
取消任何已部署的服务
在集群中获得有关服务部署拓扑结构的信息
对于访问远程部署的分布式服务创建服务代理
注意: 默认情况下,所有的集群节点的类路径中都包含服务类是必须的,服务网格是不支持对等类加载的。
在所有的情况下,除非单例服务部署,Ignite会自动地确保集群内的每个节点部署相同数量的服务。当网络发生变化时,为了更好地进行负载平衡,Ignite会对服务的部署进行重新评估然后可能将已经部署的服务重新部署到其他的节点。
Ignite会一直保证服务的持续有效,以及不管拓扑发生变化或者节点故障都会按照指定的配置进行部署。
默认情况下,就像上面负载平衡部分描述的那样,会根据集群的负载情况,Ignite服务会被部署到一个随机的节点(多个节点)。
除了这个默认的方式,Ignite还提供了一个API以将服务部署到特定的节点集合上,下面会详细描述各个方式。
① 基于节点过滤器的部署
② 基于集群组的部署
③ 基于关系键的部署
Ignite分布式消息可以在集群内的所有节点间进行基于主题的通信,带有特定消息主题的消息可以分布到订阅了该主题的所有节点或者节点的子集。
Ignite消息基于发布-订阅范式,发布者和订阅者通过一个通用的主题连接在一起。当一个节点针对主题T发布了一个消息A,他会被分布到所有订阅了主题T的节点。
任意加入集群的新节点会自动地订阅集群内(或者集群组内)其他节点订阅的所有的主题。
Ignite分布式事件功能使得在分布式集群环境下发生各种各样事件时应用可以接收到通知。可以自动获得比如任务执行、发生在本地或者远程节点上的读写或者查询操作的通知。
listen方法可以用于接收集群内发生的指定事件的通知,这些方法在本地或者远程节点上注册了一个指定事件的监听器,当在该节点上发生该事件时,会通知该监听器。
本地事件
localListen(…)方法只在本地节点上针对指定事件注册事件监听器。
远程事件
remoteListen(…)方法会在集群或者集群组内的所有节点上针对指定事 件注册监听器。
Ignite平台是基于固化内存架构的,当开启Ignite原生持久化功能时,它可以存储和处理存储在内存和磁盘上的数据和索引,固化内存架构有助于通过利用集群的所有可用资源,使数据固化到磁盘的同时,获得内存级的性能。
Ignite固化内存的操作方式类似于操作系统的虚拟内存,比如Linux,但是这两种架构的显著不同在于,当开启固化内存功能时,它会将磁盘视为数据的超集,即使重启或者故障,数据仍然会保留,而传统的虚拟内存只是将磁盘作为一个交换空间,如果进程终止数据就会丢失。
因为这种架构是以内存为中心的,所以RAM会被视为首选的存储层,所有的处理都是在内存中进行的。下面会列出这种内存架构的特性和优势:
- 堆外内存:所有的数据和索引都位于Java堆外,这样就可以轻易地处理集群内的PB级的数据;
- 消除明显的由垃圾回收导致的暂停:因为所有的数据和索引都是存储在堆外的,所以应用是有可能导致长时间暂停的唯一来源;
- 内存使用可预测:固化内存默认会使用尽可能多的内存和磁盘空间,但是也可以配置内存使用量来满足应用的需求;
- 自动内存碎片整理:Ignite会尽可能高效地使用内存,然后在后台执行碎片整理以避免碎片化;
- 改进性能和内存使用:不管是内存还是磁盘,所有的数据和索引都以类似的页面化格式进行存储,这样可以避免不必要的数据序列化和反序列化;
Ignite的原生持久化具有如下优势:
- 可选的持久化:哪些数据只会保存在内存中,哪些只会保存在磁盘上,或者什么时候内存作为磁盘的缓存层,都是可选的;
- 数据恢复:因为Ignite的持久化层保存了完整的数据集,所以不用担心集群的重启或者故障,数据不会丢失,同时还保留了强事务一致性;
- 内存只缓存热数据:在磁盘上存储数据的超集然后在内存中存储数据的子集。如果开启了Ignite的原生持久化,就不需要在内存中保存所有的数据,固化内存会在内存中保留热数据,如果空间不足,会自动地将冷数据移出内存;
- 在整个数据集中执行SQL:多数内存系统只会在预加载到内存的数据中进行查询,因此数据的大小受到了内存大小的限制。而Ignite SQL会跨越整个分布式的持久化数据集,通过内存缓存来优化性能。实际上,Ignite已经可以作为一个全功能的分布式事务型SQL数据库;
- 集群即时重启:如果整个集群故障,它可以立即重启并且可用,随着开始访问数据,内存缓存会自动地预热。
Ignite固化内存是一个机遇也面对内存架构,它会将内存拆分成固定大小的页面。这些页面会被存储于内存的堆外受管内存区(Java堆外)中,然后在磁盘上以特定的层次结构进行组织。
数据格式
Ignite在内存和磁盘上维护了同样的二进制格式,这样就不需要花费在内存和磁盘之间移动数据时进行序列化的开销。
Ignite固化内存架构的结构图:
十一、生产准备
本章涵盖了在准备将系统迁移到生产环境时的主要考虑因素。
详情查看原文档。
官方中文文档
本人程序媛一枚,因为离港澳较近,周末兼职港澳人肉代购。
欢迎各位大佬添加本人微信,还会经常有点赞活动送价值不菲的小礼品哦。
即使现在不需要代购,等以后有了女(男)朋友、有了宝宝就肯定会需要的喽。