精华内容
下载资源
问答
  • IGNITE

    2019-10-24 11:22:59
    IGNITE
  • Ignite

    2018-02-26 17:29:05
    什么是IgniteApache Ignite内存数组组织框架是一个高性能、集成和分布式的内存计算和事务平台,用于大规模的数据集处理,比传统的基于磁盘或闪存的技术具有更高的性能,同时它还为应用和不同的数据源之间提供高性能...

    什么是Ignite

    Apache Ignite内存数组组织框架是一个高性能、集成和分布式的内存计算和事务平台,用于大规模的数据集处理,比传统的基于磁盘或闪存的技术具有更高的性能,同时它还为应用和不同的数据源之间提供高性能、分布式内存中数据组织管理的功能。

    Ignite具有以下特点:

    一个以内存为中心的数据平台

    Apache Ignite是一个高性能、分布式的内存计算平台,在用户应用层与数据层无缝插入,Apache Ignite改变了传统的磁盘存储方式,从基于磁盘的存储层把数据加载到内存.

    强一致性

    在任意时刻,所有节点中的数据是一样的。同一时间点,在节点A中获取到key1的值与在节点B中获取到key1的值应该都是一样的。

    高可用

    使用软件或硬件技术实现存储的高度可用性。其主要技术指标是存储切换功能,数据复制功能,数据快照功能等。当一台存储出现故障时,另一台备用的存储可以快速切换,达到存储不停机的目的。

    强大的SQL、键-值以及相关处理的API

    完整的SQL支持

    Ignite提供了完整的SQL、DDL和DML的支持,可以使用纯SQL而不用写代码与Ignite进行交互,这意味着只使用SQL就可以创建表和索引,以及插入、更新和查询数据。有这个完整的SQL支持,Ignite就可以作为一种分布式SQL数据库。

    键-值

    Ignite的内存数据网格组件是一个完整的事务型分布式键值存储,它可以在有几百台服务器的集群上进行水平扩展。再打开持久化时,Ignite可以存储比内存容量更大的数据,并且在整个集群重启之后仍然可用。

       

    Ignite的适用场景(部署环境)

    适用场景

    从官网的上的图可以看出ignite有数据网格,计算网格,服务网格,SQL网格,数据结构,流计算,文件系统,高级集群等模块,都是放在内存操作,主要追求的是能快速分析处理数据,实时内存应用。

    数据量越大操作起来越费劲越费时,只适合事后慢慢分析,从spark开始内存计算就是为了解决太费时问题,Apache Beam也延续了这种趋势,Ignite主要内存功能强大,更方便适用,用内存来聚合数据源,处理数据。

    因此,当数据量越来越大的时候甚至超越PB级时,就体现出Ignite的优越性。

    Ignite的安装与配置

    准备

    Apache Ignite官方在如下环境中进行的测试:

    • JDK:Oracle JDK7及以上,Open JDK7及以上,IBM JDK7及以上
    • OS:Linux(任何版本),Mac OS X(10.6及以上),Windows(XP及以上),Windows Server(2008及以上),Oracle Solaris
    • 网络:没有限制(建议10G)
    • 架构:x86,x64,SPARC,PowerPC

    安装

    下面是安装Apache Ignite的简要步骤:

    • https://ignite.apache.org/下载Apache Ignite的zip压缩包
    • 将zip压缩包解压到系统安装文件夹
    • 设置IGNITE_HOME环境变量指向安装文件夹,确保没有/结尾(这一步可选)

    从源代码构建 
    如果你下载的是源代码包,可以用如下命令构建:

    1.  # Unpack the source package

    2.  $ unzip -q apache-ignite-{version}-src.zip

    3.  $ cd apache-ignite-{version}-src

    4.   

    5.  # Build In-Memory Data Fabric release(without LGPL dependencies)

    6.  $ mvn clean package-DskipTests

    7.   

    8.  # Build In-Memory Data Fabric release (withLGPL dependencies)

    9.  $ mvn clean package-DskipTests-Prelease,lgpl

    10. 

    11.# Build In-Memory Hadoop Accelerator release

    12.# (optionally specify version of hadoop touse)

    13.$ mvn clean package-DskipTests-Dignite.edition=hadoop [-Dhadoop.version=X.X.X]

    从命令行启动

    一个Ignite节点可以从命令行通过默认的配置或者传入外部配置文件的方式启动。可以启动很多很多的节点然后他们会自动地发现对方。 
    通过默认配置 
        要启动一个基于默认配置的网格节点,打开命令行然后切换到IGNITE_HOME(安装文件夹),然后输入如下命令: 
    Linux:

    1.  $ bin/ignite.sh

    Windows:

    1.  $ bin/ignite.bat

    然后会看到输出大体是如下的样子:

    1.  [02:49:12]Ignite node started OK (id=ab5d18a6)

    2.  [02:49:12]Topology snapshot [ver=1, nodes=1,CPUs=8, heap=1.0GB]

    ignite.sh启动ignite节点会使用默认的配置文件:config/default-config.xml 
    传递配置文件 
    要从命令行显式地传递一个配置文件,只需要在安装文件夹路径下输入ignite.sh <配置文件路径>,比如: 
    Linux

    1.  $ bin/ignite.shexamples/config/example-cache.xml

    Windows

    1.  $ bin/ignite.batexamples/config/example-cache.xml

    配置文件的路径既可以是绝对路径,也可以是相对于IGNITE_HOME的相对路径,也可以是相对于类路径的META-INF文件夹。

    交互式模式 
    要在一个交互模式传递配置文件,可以加上-i参数,像这样:ignite.sh -i。

    从Maven获得

    在项目里使用Apache Ignite的另一个方式是使用Maven2依赖管理。 
    Ignite只需要一个ignite-core强依赖,通常还需要添加ignite-spring,来做基于spring的XML配置,还有ignite-indexing,来做SQL查询。 
    确保将${ignite-version}替换为实际的版本号。

    1.  <dependency>

    2.  <groupId>org.apache.ignite</groupId>

    3.  <artifactId>ignite-core</artifactId>

    4.  <version>${ignite.version}</version>

    5.  </dependency>

    6.  <dependency>

    7.  <groupId>org.apache.ignite</groupId>

    8.  <artifactId>ignite-spring</artifactId>

    9.  <version>${ignite.version}</version>

    10.</dependency>

    11.<dependency>

    12.<groupId>org.apache.ignite</groupId>

    13.<artifactId>ignite-indexing</artifactId>

    14.<version>${ignite.version}</version>

    15.</dependency>

     

    多环境部署

    同时,ApacheIgnite作为一个应用极其广泛的数据处理平台,它既可以在本地部署,也可以在云平台或混合环境中运行。比如,Ignite可以独立部署,也可以部署在Kubernetes或者Docker容器中,还有Apache Mesos以及Hadoop Yarn。它可以运行在物理主机中,也可以部署在虚拟机中。

    常用的部署环境主要有:Docker部署、AWS部署、Google计算部署、Mesos部署、Yarm部署、Kubernetes部署等。

    具体的Ignite多平台部署操作可以参考以下链接:

    https://www.zybuluo.com/liyuj/note/980548

     

    使用Ignite可获得的收益(优势)

    从设计的角度看

    Ignite对开发者非常友好,提供了丰富的、符合各种标准和规范的API,如果在已有项目或者系统中集成的话,对已有代码的侵入性或者对已有架构设计的破坏性较小,在已有架构代码中做出不是很大的修改,就可以在整个系统中加入一个数据缓存层或者内存计算层,对下可以映射各种关系库或者非关系库,对上方便的对接应用系统。

    Apache Ignite统一API支持SQLC++.NetJavaScalaGroovyPHPNode.js。统一API连接 cloud-scale 应用与多种数据存储类型,包含结构化、半结构化和非结构化数据。它提供了一个高性能的数据环境,使公司能够处理full ACID事务,通过实时、互动和batch查询产生有价值的见解。

    用户可以保留现有的RDBMS,并在RDBMS和应用层之间部署Apache IgniteApache Ignite自动集成了OracleMySQLDB2PostgresMicrosoft SQL Server以及其他的RDBMSes.该系统自动生成底层数据库的架构定义的应用程序域模型,然后加载数据。内存数据库通常只提供SQL接口,而Apache Ignite支持更广泛的访问和处理范例。Apache Ignite支持键/值存储、SQL访问、MapReduceHPC / MPP处理、streaming/ CEP处理、聚类以及Hadoop加速器。

    Ignite集群配置好之后,数据集增加只需在Ignite集群中增加节点而不需要重启整个集群。节点数目可以无限增加,所以Ignite的扩展性是无穷的。

    从数据库类型看

    Apache Ignite是一个基于内存的分布式键/值存储,包括ACID 事务,故障转移,高级负载平衡和广泛的SQL支持。与以磁盘作为主要存储机制传统的数据库管理系统不同,Apache Ignite的数据存储是基于内存的,这一设计让Apache Ignite的速度比传统数据库提升了一百万倍。

    将数据存储在缓存中能够显著地提高应用的速度,因为缓存能够降低数据在应用和数据库中的传输频率。Apache Ignite允许用户将常用的热数据储存在内存中,它支持分片和复制两种方式,让开发者可以均匀地将数据分布式到整个集群的主机上。同时,Ignite还支撑任何底层存储平台,不管是RDBMSNoSQL,又或是HDFS

    Ignite作为以内存为中心的平台,是基于固化内存架构的,当Ignite持久化存储特性开启时,它可以在内存和磁盘中存储和处理数据和索引。

    该内存架构在可以将集群中的所有可用资源持久化到磁盘的前提下,还可以获得内存级的高性能。 Ignite固化内存的构建和操作方式,类似于比如Linux这样的操作系统的虚拟内存。但是两者的显著区别是,如果开启持久化存储的话,固化内存会一直将整个数据和索引保持在磁盘上,而虚拟内存使用磁盘只是用于交换用途。

    当固化内存和Ignite持久化存储同时开启时,下面Ignite作为一个平台的优势和特点:

    内存

    堆外内存

    避免明显的GC暂停

    自动碎片整理

    可预测的内存消耗

    SQL性能

    磁盘

    可选的持久化

    支持闪存、SSD以及Intel的3D Xpoint

    存储数据的超集

    全事务化(前写日志WAL

    集群瞬时启动

    Ignite与同类技术的对比

    先期了解:Ignite和Hadoop以及Spark的关系

    Ignite和Hadoop解决的是不同的问题,即使在一定程度上可能应用了类似的底层基础技术。Ignite是一种多用途,和OLAP/ OLTP内存中数据结构相关的,而Hadoop仅仅是Ignite原生支持(和加速)的诸多数据来源之一。   

    Spark 是一个和Ignite类似的项目。但是Spark聚焦于OLAP,而Ignite凭借强大的事务处理能力在混合型的OLTP/ OLAP场景中表现更好。特别是针对Hadoop,Ignite将为现有的Map/Reduce,Pig或Hive作业提供即插即用式的加速,避免了推倒重来的做法,而Spark需要先做数据ETL,更适合新写的分析应用。

    Apache和Spark

    Apache的Spark是一种快速易用的大数据处理框架。在内存计算解决方案中,Apache Ignite和Apache Ignite是互补的,他们一起配合使用,在许多事例上展现了卓越的性能。

    Apache Spark和ApacheIgnite通常是用来解决不同的用例,因此很少会竞争同一个任务。下面的表格列出了一些它们之间的关键差异。

    序号

    对比项目

    Apache Spark

    Apache Igeite

    1

    数据保留

    从外部存储加载数据(通常是基于磁盘的),并在处理完成时丢弃数据。不存储数据。

    通过ACID事务和SQL查询功能提供分布式内存中的键值存储(分布式缓存或数据网格)。保留内存中的数据,并可写入底层数据库

    2

    OLAP/OLTP

    对于非事务性的只读数据,所以用于OLAP。弹性弹性分布式数据库(RDDs)不支持就地变异

    支持非事务性(OLAP)有效负载,以及完全符合ACID的事务

    3

    数据类型

    基于RDDs。仅适用于数据驱动的有效负载

    完全支持可以“无数据”的纯计算有效负载

    Apache Spark不提供共享存储,所以从HDFS或其他磁盘存储的数据必须加载到Apache Spark中加工。Apache Ignite可以在内存中直接共享Spark状态。

    Ignite和Spark的另一重要集成就是ApacheIgnite Shared RDD API。 Ignite RDD本质上对Ignite 缓存的展现,Ignite的所有改变都会对RDD用户立刻可见,Ignite RDD可以直接在Spark作业执行过程中部署。Ignite RDD也可以使用缓存模式,在内存中部署来自Spark的数据,这些数据仍然使用Spark RDD API来访问。

    Apache Spark支持丰富的SQL语法,但不支持数据的索引,它必须做全扫描,所以Spark即使在中小型的数据集中的查询时间也需要几分钟。而Apache Ignite支持数据索引,所以查询速度要比 Spark SQL快1000倍以上。 Ignite Shared RDD返回的结果集中也符合 Spark Dataframe API,,因此进行进一步分析时仍然可以使用Spark。Spark和Ignite都集成了Apache YARN 和Apache Mesos,所以它们之间的互通性更多。

    和类似技术的对比

    Ignite和Hazelcast

    Apache Ignite和Hazelcast都提供了富数据网格的特性,解决了可扩展的分布式集群环境下在内存中对数据进行缓存和分区的问题。

    Ignite和Hazelcast在缓存的方式上是有很多不同的,同时支持事务和数据的查询,下面的表格列出了一些主要的不同点,这些都是我们在选择内存数据网格产品时需要特别关注的。

     

    序号

    对比项目

    Apache Ignite

    Hazelcast

    1

    聚焦于开源

    Ignite是一个Apache的开源项目,还在不断的增加新特性,对C++.NET/C#Node.js的支持也会很快到来。

    Hazelcast正在持续的减少开源版本的功能,更多的功能加入了企业版中,比如堆外存储,持续查询,Web-Session集群,SSL加密支持等。

    2

    JCache(JSR107)

    Ignite完全兼容JCache (JSR 107)缓存规范

    Hazelcast完全兼容JCache (JSR 107)缓存规范

    3

    堆外存储

    Ignite根据用户配置支持将数据存储在堆内或者堆外

    Hazelcast仅在商业版中提供堆外存储的功能

    4

    堆外索引

    只要配置了堆外存储,Ignite就会在堆外存储索引(为了不影响使用堆内内存的用户应用。)

    不支持

    5

    持续查询

    Ignite支持持续查询,比如允许客户端和服务器端订阅数据变化的持续通知

    Hazelcast仅在商业版中提供持续查询的功能。

    6

    SQL查询

    Ignite支持完整的SQL(ANSI-99)语法以查询内存中的数据

    Hazelcast仅对SQL提供有限的支持(只有几个关键字)

    7

    关联查询

    Ignite支持完整的SQL关联,包括跨多个缓存的关联,比如:select * from A a, B b where a.b_id = b.id

    Hazelcast不支持任何的关联查询,不管用不用SQL,如果需要,开发者需要手工处理多个查询的结果。

    8

    查询一致性

    Ignite提供完整的查询一致性,即查询是在一个特定的快照中执行的,查询开始之后的数据更新不影响查询的结果。

    Hazelcast查询是不一致的,这是可能的,查询结果的一部分将看到一定的更新,而另一部分则不会。

    9

    查询容错

    Ignite查询是容错的,即查询结果始终是一致的不会受到集群拓扑发生变化的影响,比如节点的加入,退出或崩溃。

    Hazelcast查询是不容错的,即查询结果在集群拓扑发生变化时不一致,而数据正在后台重新平衡。

    10

    数据一致性

    Ignite支持内存中数据的原子性和事务一致性,不管数据存储在分区或者复制缓存中。

    Hazelcast仅在分区缓存中支持原子性和事务一致性,而存储在复制缓存中的数据没有任何事务一致性的保证。

    11

    SSL加密

    Ignite为所有的网络传输提供SSL加密,包括客户端和服务器端以及服务器之间。

    Hazelcast仅在商业版中提供SSL加密功能。

    12

    Web-Session集群

    Ignite为所有已知的应用服务器提供Web-Session的缓存和集群化支持。

    Hazelcast仅在商业版中提供Web-Session集群化支持。

    13

    计算网格

    Ignite提供集群上的M/RFork/Join和基本的分布式lambda处理,包括任务负载平衡,容错,检查点,计划任务等。

    Hazelcast仅支持M/R和集群内的分布式随机任务。

    14

    流式网格

    Ignite支持内存流,包括对数据流浮动窗口的查询和维护支持

    不支持

    15

    服务网格

    Ignite可以使用户方便地将其服务集群化,包括支持各种单例集群。

    Hazelcast管理的服务不提供单例集群的功能。

    16

    .Net/C#,C++支持

    Ignite将在1.5.0版中提供完整的内存组织API

    Hazelcast仅在商业版中提供有限的客户端API支持。

    17

    Node.js支持

    Ignite将在1.5.0版中提供Node.js的客户端API

    不支持

    Ignite和Coherence

    Apache Ignite和Oracle Coherence都提供了富数据网格的特性,解决了可扩展的分布式集群环境下在内存中对数据进行缓存和分区的问题。

    Ignite和Coherence在缓存的方式上是有很多不同的,同时支持事务和数据的查询,下面的表格列出了一些主要的不同点,这些都是我们在选择数据网格产品时需要特别关注的。

     

    序号

    对比项目

    Apache Ignite

    Oracle Coherence

    1

    开源和闭源

    Ignite是一个Apache的开源项目,并且还在不断的增加新特性,对C++.NET/C#Node.js的支持也会很快到来。

    Coherence是一个Oracle的专有软件,并不提供开源和免费的版本。

    2

    JCache (JSR 107)

    Ignite完全兼容JCache (JSR 107)缓存规范

    Coherence完全兼容JCache (JSR 107)缓存规范

    3

    堆外存储

    Ignite根据用户配置支持将数据存储在堆内或者堆外

    Coherence对开发者提供了有限的选项支持将数据存储在堆外

    4

    堆外索引

    只要配置了堆外存储,Ignite就会在堆外存储索引(为了不影响使用堆内内存的用户应用。)

    不支持

    5

    SQL查询

    Ignite支持完整的SQL(ANSI-99)语法以查询查询内存中的数据

    不支持

    6

    关联查询

    Ignite支持完整的SQL关联,包括跨多个缓存的关联,比如:select * from A a, B b where a.b_id = b.id

    Coherence不支持任何的关联查询,不管用不用SQL,如果需要,开发者需要手工处理多个查询的结果。

    7

    ACID事务

    Ignite提供了每台服务器每秒成千上万事务的优异性能。

    Coherence因为性能原因不建议使用事务。

    8

    分层存储

    Ignite支持分层存储模型,数据可以在堆内、堆外以及交换空间内存储和移动,上层将提供更多的存储能力,当然延迟也会增加。

    不支持

    9

    数据流

    Ignite提供内存流的支持,包括支持流数据的维护、查询和浮动窗口

    不支持

    10

    配置

    Ignite支持通过Java Bean以及原生的Spring XML集成对系统进行配置,同时也支持通过代码对系统进行方便配置的能力。

    Coherence通过专有的XML格式文件进行配置,不支持通过代码进行配置。

    Ignite和Gemfire

    Apache Ignite和Pivotal Gemfire都提供了富数据网格的特性,解决了可扩展的分布式集群环境下在内存中对数据进行缓存和分区的问题。

    Ignite和Gemfire在缓存的方式上是有很多不同的,同时支持事务和数据的查询,下面的表格列出了一些主要的不同点,这些都是我们在选择数据网格产品时需要特别关注的。

     

    序号

    对比项目

    Apache Ignite

    Pivotal Gemfire

    1

    开源和闭源

    Ignite是一个Apache的开源项目,并且还在不断的增加新特性,对C++.NET/C#Node.js的支持也会很快到来。

    GemfirePivotal的专有软件。

    2

    JCache (JSR107)

    Ignite数据网格是JCacheJSR107)规范的一个实现,该API为数据访问提供了简单易用、但是功能强大的API

    Gemfire没有实现JCache,使用专有的API

    3

    堆外存储

    Ignite根据用户配置支持将数据存储在堆内和堆外

    Gemfire不支持将数据存储在堆外

    4

    SQL查询

    Ignite支持完整的SQL(ANSI-99) 查询语法以查询内存中的数据。

    Gemfire不支持标准的SQL语法,但是他提供了他自己的叫做OQL的对象查询语言。

    5

    关联查询

    Ignite支持完整的SQL关联,包括跨多个缓存的关联,比如:select * from A a, B b where a.b_id = b.id

    Gemfire不支持任何的跨区或者跨缓存的关联查询,如果需要,开发者需要手工处理多个查询的结果。

    6

    跨分区事务

    Ignite支持跨分区事务,事务可以在整个集群中缓存的所有分区中执行。

    Gemfire不支持跨越多个缓存分区或者节点的事务。

    7

    分层存储

    Ignite支持分层存储模型,数据可以在堆内、堆外以及交换空间内存储和移动,上层将提供更多的存储能力,当然延迟也会增加。

    不支持

    8

    数据流

    Ignite提供内存流的支持,包括支持流数据的维护、查询和浮动窗口

    不支持

    9

    配置

    Ignite支持通过Java Bean以及原生的Spring XML集成对系统进行配置,同时也支持通过代码对系统进行方便配置的能力。

    Gemfire通过专有的XML格式文件进行配置,不支持通过代码进行配置。

    10

    部署

    Ignite节点是对等的,并且在启动时自动加入集群(不需要任何locator服务器)。

    Gemfire需要启动和维护一个locator服务器,以便控制节点的加入

    Ignite和Redis

    Apache Ignite和Redis都提供了分布式缓存的功能,但是每个产品提供的功能特性是非常不同的。Redis主要是一个数据结构存储,但是Ignite提供了很多内存内的分布式组件,包括数据网格、计算网格、流,当然也包括数据结构。

    Ignite是一个内存数据组织,并且提供了更多的功能,无法进行一个一个对应功能特性的比较,但是我们仍然能对一些数据网格功能进行比较。

    序号

    对比项目

    Apache Ignite

    Redis

    1

    JCache (JSR 107)

    Ignite完全兼容JCacheJSR107)缓存规范

    不支持

    2

    ACID事务

    Ignite完全支持ACID事务,包括乐观和悲观并发模型以及READ_COMMITTED, REPEATABLE_READSERIALIZABLE隔离级别。

    Redis提供了客户端乐观事务的有限支持,在并发更新情况下,客户端需要手工重试事务。

    3

    数据分区

    Ignite支持分区缓存,类似于一个分布式哈希,集群中的每个节点都存储数据的一部分,在拓扑发生变化的情况下,Ignite会自动进行数据的平衡。

    Redis不支持分区,但是他提供了副本的分片,

    4

    全复制

    Ignite支持缓存的复制,集群中的每个节点的每个键值对都支持。

    Redis不提供对全复制的直接支持。

    5

    原生对象

    Ignite允许用户使用自己的领域对象模型并且提供对任何Java/Scala, C++.NET/C#数据类型(对象)的原生支持,用户可以在Ignite缓存中轻易的存储任何程序和领域对象。

    Redis不允许用户使用自定义数据类型,仅支持预定义的基本数据结构集合,比如SetListArray以及一些其他的。

    6

    ()客户端缓存

    Ignite提供客户端缓存最近访问数据的直接支持。

    Redis不支持客户端缓存。

    7

    服务器端并行处理

    Ignite支持在服务器端,靠近数据并行地直接执行任何Java, C++.NET/C#代码。

    Redis通常没有任何并行数据处理的能力,服务器端基本只支持LUA脚本语言,服务器端不直接支持Java, .NET,或者C++代码执行。

    8

    SQL查询

    Ignite支持完整SQLANSI-99)语法以查询内存中的数据。

    Redis不支持任何查询语言,只支持客户端缓存API

    9

    持续查询

    Ignite提供对客户端和服务器端持续查询的支持,用户可以设置服务器端的过滤器来减少和降低传输到客户端的数据量。

    Redis提供客户端基于键值的事件通知的支持,然而,他不提供服务器端的过滤器,因此造成了在客户端和服务器端中更新通知网络流量的显著增加。

    10

    数据库集成

    Ignite可以自动集成外部的数据库-RDBMS, NoSQL,HDFS

    不支持

     

    Ignite的技术难点

    Ignite的一些关键特性

    固化内存

    Ignite作为以内存为中心的平台,是基于固化内存架构的,当Ignite持久化存储特性开启时,它可以在内存和磁盘中存储和处理数据和索引。

    该内存架构在可以将集群中的所有可用资源持久化到磁盘的前提下,还可以获得内存级的高性能。

    Ignite固化内存的构建和操作方式,类似于比如Linux这样的操作系统的虚拟内存。但是两者的显著区别是,如果开启持久化存储的话,固化内存会一直将整个数据和索引保持在磁盘上,而虚拟内存使用磁盘只是用于交换用途。

    当固化内存和Ignite持久化存储同时开启时,下面Ignite作为一个平台的优势和特点:

    内存

    ·        堆外内存

    ·        避免明显的GC暂停

    ·        自动碎片整理

    ·        可预测的内存消耗

    ·        高SQL性能

    磁盘

    ·        可选的持久化

    ·        支持闪存、SSD以及Intel的3D Xpoint

    ·        存储数据的超集

    ·        全事务化(前写日志WAL)

    ·        集群瞬时启动

    Ignite持久化

    Ignite持久化存储是一个分布式的、支持ACID、兼容SQL的磁盘存储,它作为一个可选的磁盘层,可以将数据和索引存储在SSD、闪存、3D XPoint以及其他的非易失性存储器中,并且可以透明地与Ignite固化内存进行集成。

    开启持久化存储后,就不再需要将所有的数据和索引保持在内存中,也不再需要在节点或者集群重启后对数据进行预热,因为Ignite的固化内存和持久化存储是紧密耦合的,并且视其为二级存储。这意味着如果数据或者索引的子集在内存中遗失,固化内存会从磁盘中获取。

    Ignite的持久化存储相比于第三方存储有很多的优势(RDBMS、NoSQL、Hadoop),它可以作为Ignite集群的一个可替代的持久化层。

    ·        可以在数据中执行SQL查询,不管数据在内存中还是在磁盘中,这意味着Ignite可以作为一个经过内存优化的分布式SQL数据库;

    ·        不再需要将所有的数据和索引保持在内存中,持久化存储可以在磁盘上存储数据的超集,然后只在内存中保存频繁访问的数据的子集;

    ·        集群的瞬时重启,如果整个集群停机,不再需要通过预加载数据而对内存进行预热,只要所有集群节点都连接在一起了,整个集群就可以正常运转了;

    ·        数据和索引在内存和磁盘中是以相似的格式进行存储的,这有助于避免昂贵的格式转换,数据集只是在内存和磁盘之间进行移动;

    ·        通过插入第三方解决方案,可以创建完整的增量集群快照。

    分布式SQL数据库

    在Ignite中,作为平台的一部分,提供了分布式SQL数据库的功能,这个数据库可以水平扩展、容错并且兼容ANSI-99标准,它支持所有的SQL以及DML命令,包括SELECT、UPDATE、INSERT、MERGE以及DELETE,它还提供了对和分布式数据库相关的DDL命令的一个子集的支持,

    有赖于固化内存架构,数据集和索引可以同时在内存和磁盘中存储,这样可以跨越不同的存储层执行分布式SQL操作,来获得可以固化到磁盘的内存级性能。

    可以在Java、C++、.NET中通过原生的API使用SQL语言来与Ignite进行交互,也可以通过Ignite的JDBC或者ODBC驱动,这从语言层面来说,比如PHP、Ruby以及其他的,具有了真正的跨平台连接性。

    内存数据网格

    Ignite内存数据网格是一个内存中的分布式键-值存储,它可以在分布式集群的内存中缓存数据,Ignite数据网格可以视为一个分布式分区化的哈希,其中每个节点都持有整个数据集的一部分,这样的话,随着不断地增加新节点,就可以缓存更多的数据。

    Ignite数据网格甚至可以线性地增长到几百个节点,它通过强语义的数据位置和关系数据路由,来降低冗余数据噪声。

    Ignite数据网格速度足够快,经过官方不断的测试,目前,他是分布式集群中支持事务性或原子性数据的最快的实现之一。

    内存计算网格

    分布式计算是通过并行处理的方式来获得更高的性能,更低的延迟以及线性可扩展性,Ignite计算网格提供了一组简单的API来允许用户在集群内的多台计算机中执行分布式计算和数据处理。

    分布式并行计算是基于在集群内的节点中进行任何的计算然后将结果返回的能力。

    机器学习

    Ignite从2.0版本开始,引入了一个叫做机器学习网格的分布式机器学习库的第一版。

    构建机器学习网格的理由很简单,很多用户将Ignite作为各种数据集的高性能存储和处理核心系统,如果用户想在这些数据集上执行机器学习或者深度学习(即训练集或者模型推理),就需要首先进行ETL,将数据转换到其他的系统中,比如Apache Mahout或者Apache Spark。

    机器学习网格的路线图是从基于分布式协同处理的核心代数实现开始的。初始版本在Ignite的2.0版本中发布。未来的版本会为Python、R以及Scala引入自定义DSL,不断优化机器学习算法集比如线性和逻辑回归、决策树/随机孙林、SVM、朴素贝叶斯以及支持经过Ignite优化的神经网络,还有就是集成TensorFlow。

    当前测试版的Ignite机器学习网格,在高度优化和可扩展的Ignite平台基础上支持一个分布式的机器学习库,实现了一个本地化以及分布式的矢量和矩阵运算,还有已经广泛使用的算法的分布式版本

    其他一些扩展特性

    可以参考https://www.zybuluo.com/liyuj/note/293596

     

     总之,该项技术目前国内文档较少,尚处于起步阶段,应用于项目中所体现的缺点和不足将在未来不断发现与改善。


    展开全文
  • ignite

    2018-08-07 21:00:00
    https://www.zybuluo.com/liyuj/not...

    https://www.zybuluo.com/liyuj/note/230739

    转载于:https://my.oschina.net/wangnz/blog/1924123

    展开全文
  • ignite-源码

    2021-03-29 06:14:24
    ignite
  • Ignite-源码

    2021-03-09 09:40:51
    Ignite
  • Ignite-初识Ignite

    万次阅读 2019-09-11 19:19:33
    ignite作为分布式缓存框架, 首先了解到本来项目是分布式,ignite是直接嵌入项目(java)中,ignite是基于JVM的,所以可以完全嵌入java项目中,随着项目启动而启动关闭而关闭 (我理解为相当于java编写了一个ma...

    简介

    最近公司需要更改一个旧项目,其中涉及到Ignite作为缓存体系,之前使用的缓存框架通常是redis集群,第一次接触Ignite,想把学习、认知过程记录下来。

    ignite作为分布式缓存框架, 首先了解到本来项目是分布式,ignite是直接嵌入项目(java)中,ignite是基于JVM的,所以可以完全嵌入java项目中,随着项目启动而启动关闭而关闭 (我理解为相当于java编写了一个map缓存数据,当然别人是可以分布式的、并且可以做分布式计算的),目前遇到的问题是有时候程序运行中 但是ignite线程挂了,失去功能,并且某个节点挂掉 不能转到其他节点(后续发现问题是集群保存数据有三种模式导致部分数据丢失现象)。目标计划把服务独立出来不再嵌入项目中,构建独立的Ignite服务端集群,项目作为一个客户端。

    了解Ignite

    Ignite是轻量级分布式内存HTAP数据库及计算平台,中文官网https://liyuj.gitee.io/

    发一张我的脑图:

    Ignite是一个大容器(相当于mysql的一个连接服务,cache就是一个数据库),里面可以创建cache,数据放在cache里面。Ignite支持完整的SQL、DDL和DML,键-值形式存储数据,其中值得类型可以基本数据类型,也可以是对象Object映射成table-column。

    Ignite可以通过key键来取数据,也支持sql语句取数据:

                    1、创建一个容器cache<String,Object>

                    2、通过key查询:调用cache.get()/cache.getAll()方法

                    3、通过sql查询:调用cache.query()

    Ignite本身有原生的持久化机制,可以选择是否开启,也可以集成到第三方数据库进行持久化。缓存策略:部门常用的数据可以放在内存中,通过重写CacheStoreAdapter这个类进行自定义持久化策略,如果在内存取不到数据会通过load/loadAll进行查询。举个例子(目前例子都是基于独立服务启动):

    server-cache.xml配置文件:

    <?xml version="1.0" encoding="UTF-8"?>
    
    <!-- Licensed to the Apache Software Foundation (ASF) under one or more contributor 
    	license agreements. See the NOTICE file distributed with this work for additional 
    	information regarding copyright ownership. The ASF licenses this file to 
    	You under the Apache License, Version 2.0 (the "License"); you may not use 
    	this file except in compliance with the License. You may obtain a copy of 
    	the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required 
    	by applicable law or agreed to in writing, software distributed under the 
    	License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS 
    	OF ANY KIND, either express or implied. See the License for the specific 
    	language governing permissions and limitations under the License. -->
    
    <!-- Ignite Spring configuration file to startup grid cache. When starting 
    	a standalone Ignite node, you need to execute the following command: {IGNITE_HOME}/bin/ignite.{bat|sh} 
    	examples/config/example-cache.xml When starting Ignite from Java IDE, pass 
    	path to this file to Ignite: Ignition.start("examples/config/example-cache.xml"); -->
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="
            http://www.springframework.org/schema/beans
            http://www.springframework.org/schema/beans/spring-beans.xsd">
    
        <!-- IgniteConfiguration -->
        <bean id="grid.cfg" class="org.apache.ignite.configuration.IgniteConfiguration">
    
            <!-- Explicitly configure TCP discovery SPI to provide list of initial nodes. -->
            <property name="discoverySpi">
                <bean class="org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi">
                    <!--集群之间的交流端口-->
    				<property name="localPort" value="48500"/>
                    <property name="localPortRange" value="3"/>
                    <property name="joinTimeout" value="1000"/>
                    <property name="ipFinder">
                        <!-- Uncomment multicast IP finder to enable multicast-based discovery
                            of initial nodes. -->
                        <!--<bean class="org.apache.ignite.spi.discovery.tcp.ipfinder.multicast.TcpDiscoveryMulticastIpFinder"> -->
                        
                        <bean class="org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder">
                            <property name="addresses">
                                <list>
                                    <!--集群IP-->
                                    <value>XXX.1.8.1:48500..48503</value>
    	                            <value>XXX.1.8.2:48500..48503</value>
                                </list>
                            </property>
                        </bean>
                        
                    </property>
                </bean>
            </property>
    		<property name="cacheConfiguration">
    			<list>
    				<bean parent="cache-template">
                        <property name="name" value="CACHE_PURE"/>
                        <!--持久化存储  -->
                        <property name="cacheStoreFactory">
                            <bean class="javax.cache.configuration.FactoryBuilder"
                                  factory-method="factoryOf">
                         <!--重写CacheStoreAdapter  -->
                                <constructor-arg value="com.xx.xx.cache.manager.store.CollAdapterStoreMgr"/>
                            </bean>
                        </property>
                        <!--建立索引 PureCache是object-table映射 -->
                        <property name="indexedTypes">
                            <list>
                                <value type="java.lang.Class">java.lang.String</value>
                                <value type="java.lang.Class">com.xx.xx.cache.model.PureCache</value>
                            </list>
                        </property>
                    </bean>
    
    			</list>
    			
    			
    			
    		</property>
    		
    		<property name="clientConnectorConfiguration">
            <bean class="org.apache.ignite.configuration.ClientConnectorConfiguration">
                <!--本机IP-->
                <property name="host" value="XXX.1.8.1"/>
                <!--对thin客户端暴露的端口-->
                <property name="port" value="10811"/>
                <property name="portRange" value="10"/>
            </bean>
    		</property>  
        </bean>
    
    			<bean id="cache-template" abstract="true"
    				  class="org.apache.ignite.configuration.CacheConfiguration">
    				<!-- 缓存初始大小[默认1500000] -->
    				<!--<property name="startSize" value="2000"/>-->
    				<!-- 缓存再平衡模式[默认ASYNC异步平衡模式,分布式缓存会马上启动,然后在后台会从其他节点加载所有必要的数据] -->
    				<property name="rebalanceMode" value="SYNC"/>
    				<!-- 配置主节点和备份部分的同步和异步更新[默认PRIMARY_SYNC客户端节点会等待主节点的写或者提交完成,但不会等待备份节点的更新完成] -->
    				<property name="writeSynchronizationMode" value="FULL_SYNC"/>
    				<!-- 缓存模式 [PARTITIONED分区模式]-->
    				<property name="cacheMode" value="PARTITIONED"/>
    				<!--有备份的分区缓存,当设置为PARTITIONED生效 -->
    				<property name="backups" value="2"/>
    				<!-- 事务-原子化模式[ATOMIC模式因为避免了事务锁,所以性能更好,但是仍然提供了单个数据的原子性和一致性] -->
    				<property name="atomicityMode" value="ATOMIC"/>
    				<!-- 如果cache中无法取到数据,自动从数据库中搜索并加载 -->
    				<property name="readThrough" value="true"/>
    				<!-- 自动写入到数据库 -->
    				<property name="writeThrough" value="true"/>
    				<!-- 热生存时间 -->
    				<property name="eagerTtl" value="true"/>
    			</bean>
    			<!-- ignite -->
    			
    </beans>
    
    

    Object-table映射PureCache类:

    package com.xx.xx.cache.model;
    
    import org.apache.ignite.cache.query.annotations.QuerySqlField;
    
    import java.io.Serializable;
    import java.util.Date;
    
    
    @SuppressWarnings("serial")
    public class PureCache implements Serializable {
    
        
        @QuerySqlField(index = true)
        private Long id;
    
       
        @QuerySqlField
        private String name;
    
        
        @QuerySqlField
        private String adapterEnglishName;
    
       
        @QuerySqlField
        private String interfaceType;
    
        @QuerySqlField
        private Integer collAdapterType;
    
       
        @QuerySqlField
        private String startupPath;
    
        
        @QuerySqlField
        private String shutdownPath;
    
        
        @QuerySqlField
        private String params;
    
       
        @QuerySqlField
        private String memo;
    
        
        @QuerySqlField
        private Integer dataType;
    
       
        @QuerySqlField
        private String developFactory;
    
        
        @QuerySqlField
        private String adapterVersion;
    
       
        @QuerySqlField
        private Integer adapterExecuteType;
    
        @QuerySqlField
        private Date createTime;
    
        @QuerySqlField
        private Date updateTime;
    
       
    
        public Long getId() {
            return id;
        }
    
        public void setId(Long id) {
            this.id = id;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public String getAdapterEnglishName() {
            return adapterEnglishName;
        }
    
        public void setAdapterEnglishName(String adapterEnglishName) {
            this.adapterEnglishName = adapterEnglishName;
        }
    
        public String getInterfaceType() {
            return interfaceType;
        }
    
        public void setInterfaceType(String interfaceType) {
            this.interfaceType = interfaceType;
        }
    
        public Integer getCollAdapterType() {
            return collAdapterType;
        }
    
        public void setCollAdapterType(Integer collAdapterType) {
            this.collAdapterType = collAdapterType;
        }
    
        public String getStartupPath() {
            return startupPath;
        }
    
        public void setStartupPath(String startupPath) {
            this.startupPath = startupPath;
        }
    
        public String getShutdownPath() {
            return shutdownPath;
        }
    
        public void setShutdownPath(String shutdownPath) {
            this.shutdownPath = shutdownPath;
        }
    
        public String getParams() {
            return params;
        }
    
        public void setParams(String params) {
            this.params = params;
        }
    
        public String getMemo() {
            return memo;
        }
    
        public void setMemo(String memo) {
            this.memo = memo;
        }
    
        public Integer getDataType() {
            return dataType;
        }
    
        public void setDataType(Integer dataType) {
            this.dataType = dataType;
        }
    
        public String getDevelopFactory() {
            return developFactory;
        }
    
        public void setDevelopFactory(String developFactory) {
            this.developFactory = developFactory;
        }
    
        public String getAdapterVersion() {
            return adapterVersion;
        }
    
        public void setAdapterVersion(String adapterVersion) {
            this.adapterVersion = adapterVersion;
        }
    
        public Integer getAdapterExecuteType() {
            return adapterExecuteType;
        }
    
        public void setAdapterExecuteType(Integer adapterExecuteType) {
            this.adapterExecuteType = adapterExecuteType;
        }
    
        public Date getCreateTime() {
            return createTime;
        }
    
        public void setCreateTime(Date createTime) {
            this.createTime = createTime;
        }
    
        public Date getUpdateTime() {
            return updateTime;
        }
    
        public void setUpdateTime(Date updateTime) {
            this.updateTime = updateTime;
        }
    
    
        //</editor-fold>
    
        @Override
        public String toString() {
            final StringBuilder sb = new StringBuilder("CollAdapterCache{");
            sb.append("id=").append(id);
            sb.append(", name='").append(name).append('\'');
            sb.append(", adapterEnglishName='").append(adapterEnglishName).append('\'');
            sb.append(", interfaceType='").append(interfaceType).append('\'');
            sb.append(", collAdapterType=").append(collAdapterType);
            sb.append(", startupPath='").append(startupPath).append('\'');
            sb.append(", shutdownPath='").append(shutdownPath).append('\'');
            sb.append(", params='").append(params).append('\'');
            sb.append(", memo='").append(memo).append('\'');
            sb.append(", dataType=").append(dataType);
            sb.append(", developFactory='").append(developFactory).append('\'');
            sb.append(", adapterVersion='").append(adapterVersion).append('\'');
            sb.append(", adapterExecuteType=").append(adapterExecuteType);
            sb.append(", createTime=").append(createTime);
            sb.append(", updateTime=").append(updateTime);
            sb.append('}');
            return sb.toString();
        }
    
    }
    

    持久化对象CollAdapterStoreMgr:

    package com.xx.xx.cache.manager.store;
    
    
    import org.apache.commons.lang3.StringUtils;
    import org.apache.ignite.cache.store.CacheStoreAdapter;
    import org.apache.ignite.lang.IgniteBiInClosure;
    import org.apache.ignite.resources.SpringResource;
    import org.apache.logging.log4j.LogManager;
    import org.apache.logging.log4j.Logger;
    
    import javax.cache.Cache;
    import javax.cache.integration.CacheLoaderException;
    import javax.cache.integration.CacheWriterException;
    import java.util.List;
    import java.util.Map;
    import java.util.concurrent.atomic.AtomicLong;
    
    
    public class PureCacheStoreMgr extends CacheStoreAdapter<String, PureCache> {
    
        private static Logger logger = LogManager.getLogger(PureCacheStoreMgr .class.getName());
    
     
    
        @Override
        public void loadCache(IgniteBiInClosure<String, ParserAdapterCache> clo, Object... args) {
           
        }
    
        @Override
        public Map<String, ParserAdapterCache> loadAll(Iterable<? extends String> keys) {
              /**
                实现多key个查询
               **/
             return super.loadAll(keys);
        }
    
        @Override
        public ParserAdapterCache load(String key) throws CacheLoaderException {
            /**
                实现单个key查询
               **/
            return result;
        }
    
        @Override
        public void write(Cache.Entry<? extends String, ? extends ParserAdapterCache> entry) throws CacheWriterException {
            /**
                持久化
               **/
        }
    
        @Override
        public void delete(Object key) throws CacheWriterException {
            /**
                删除
               **/
        }
    }
    

    对Ignite的初始化cache配置,如果服务器独立运行的时候,需要把自己额外的jar放进apache-ignite-fabric-2.5.0-bin\libs里面。

    了解运行模式

    Ignite运行有三种角色

    1、服务端(server节点)

           数据存储,参与缓存,参与分布式计算...,并且可以嵌入java代码,使项目本身是一个服务节点,也可以独立节点运行部署。集群节点挂了,其他节点会感知。

    2、客户端(client节点)

           本身不存储数据,可以通过api对服务器节点进行数据存储,参与分布式计算...集群节点挂了,其他节点会感知。

    3、瘦客户端(thin client)       

                   thin client不会加入Ignite的集群拓扑,它也不存储数据,也不参与执行计算和流处理。和Ignite原生的client节点不同,它并不感知集群的拓扑结构变化(增加/删除节点后,thin client并不知道),而且一次只能和Ignite集群中的一个节点连接通讯,当该节点失效后,它会从事先配置好节点列表中挑选一个新的节点,重新连接

    ignite集群cache数据保存三种模式:

    1、LOCAL:本地模式,数据都存储在本地,无数据再平衡,类似常见的存储服务;(查不到数据再做处理)

    2、PARTITIONED:分区模式,数据分散到集群中的各个节点,分区模式适合存储数量庞大的数据

    3、REPLICATED:复制模式,有数据再平衡过程,主节点(Primary)数据与分区模式的一致,只是复制模式默认备 份了除主节点数据外的其余数据。复制模式适合存储数据量小,增长不快的数据。

    部署Ignite集群

            安装包下载地址:百度云,提取码:sv74,也可以官网自行下载:https://ignite.apache.org/download.cgi

    服务器位置

    部署服务器

    部署根路径

    x.1.8.1

    /home/xx/xx/ignite

    x.1.8.2

    /home/xx/xx/ignite

     

    发布位置

    1. 上传发布包ignite2.5到/home/xx/xx/ignite目录下

              修改配置文件 /home/xx/xx/ignite/ignite2.5/config/server-cache.xml

              <bean class="org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder">

                            <property name="addresses">

                                <list>

                                   <!--添加集群IP地址-->

                                    <value>x.1.8.1:48500..48510</value>

                                    <value>x.1.8.2:48500..48510</value>

                                </list>

                            </property>

            </bean>

            <bean class="org.apache.ignite.configuration.ClientConnectorConfiguration">

            <!--修改为本机IP地址-->

                <property name="host" value="x.1.8.1"/>

                <property name="port" value="10800"/>

                <property name="portRange" value="10"/>

           </bean>

    程序启动

          进入目录 /home/xx/xx/ignite/ignite2.5/bin

          命令:nohup bash ignite.sh ../config/server-cache.xml &

          成功标识:输入tail -1000 nohup.out

     

    控制台监控,按步骤输入命令

    1. bash ignitevisorcmd.sh
    2. Open

     

    找到config/server-cache.xml选择,输入该选择前面的编号,比如:10

          3、top    --查看所有节点信息

          4、cache  -a  --查看所有库信息

     

     

    window安装DBeaver

    下载DBeaver5.0.2

    下载ignite-core-2.5.0.jar

    安装DBeaver5.0.2

    1. 安装ignite驱动

    数据库 > 驱动管理 > 新建

     

    URL模板:jdbc:ignite:thin://可用的服务器节点IP/

    端口:10800

    添加文夹:选择下载好的ignite-core-2.5.0.jar

    点击查找类选择:org.apache.ignite.IgniteJdbcThinDriver

    确认

    数据量 > 新建连接 > 选择ignite

    不填写账号、密码

    测试链接,显示OK

    下一步、完成。

    展开全文
  • Ignite is a high-level library to help with training and evaluating neural networks in PyTorch flexibly and transparently. Click on the image to see complete code Features Less code than pure...
  • ignite:Ignite da Rocketseat的总冠军
  • <div><p>Hi, Could you please add AI clients ...<p>Also Apache Ignite clients was added to the DATABASES list (ycsb script). <p>Thanks!</p><p>该提问来源于开源项目:brianfrankcooper/YCSB</p></div>
  • ignite文档

    2018-04-11 15:05:04
    ignite文档,初学者很有用,讲解了ignite的基本功能,附带demo
  • Ignite-Challenges:所有Ignite课程挑战
  • ignite test

    2018-06-04 13:44:52
    apache Ignite As an​ SQL database, Ignite supports all DML commands including SELECT, UPDATE, INSERT, and DELETE queries. It also implements a subset of DDL commands relevant for distributed systems.
  • ignite web

    2018-05-09 18:51:55
    ignite集群开发,功能的服务,web client。要需要的可以下载
  • ignite clientid

    2018-05-09 18:49:21
    ignite集群开发,功能的服务,web client。要需要的可以下载
  • <div><p>After the merge of #1118 here are some things to take care of in the Apache Ignite (incubating) clients, preferably before the next release. <p>Files missing a proper license header: <ul><li>...
  • 点燃 来自#IGNITE NodeJS的代码
  • Desafio-Ignite-session2:Desenvolvendo desafio Ignite
  • ignite-dtmoney:Ignite ReactJS-dtmoney应用程序
  • AngularJS的Ignite UI指令 使用igniteui-angularjs.js的指令在页面中使用控件。 或使用此预配置的应用程序快速引导您的AngularJS项目。 重要信息存储库已从igniteui-angular重命名为igniteui-angularjs 。 这是...
  • ignite-reacjs Trilha Ignite React.js火箭座
  • study_Ignite_React study_Ignite_React
  • rocketseat-ignite:Rocketseat的Ignite训练营实践练习
  • MyBatis点火扩展 MyBatis-Ignite扩展点燃对MyBatis缓存的支持。 必需品
  • Ignite2019 Ignite 2019 DevOps研讨会的示例应用程序
  • ignite-react-challenges:Rocketseat Ignite挑战-ReactJS Trail

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 5,643
精华内容 2,257
关键字:

ignite