开源IMDG之GridGain,imdggridgain


作为另一款主流的开源数据网格产品,GridGainHazelcast的强有力竞争者。同样提供了社区版和商业版,近日GridGain的开源版本已经进入Apache孵化器项目Ignite(一款开源的内存计算(In-Memory Computing)IMC中间件),目前Apache正在迁移GridGain开源版本的代码到Ignite项目。鉴于经过之前Hazelcast的介绍已经对数据网格产品有了一定了解,本文着重介绍GridGainHazelcast差异化之处。

重叠功能列举

比较

Hazelcast

GridGain

使用性

安装

Maven引入Jar包即可,无需安装软件

客户端

支持各种语言的客户端

框架集成

集成HibernateWeb SessionSpring

基本功能

分布式计算工具

分布式的集合并发包消息队列调度器

性能

性能配置

内存索引Near-Cache数据亲和性

可靠性

数据备份

分区数据冗余备份

持久化

read-throughwrite-through/behind

事务

保证数据一致性

扩展性

自动分区

支持本地分区复制三种方式

动态拓扑

动态添加删除结点,自动rebalance

 

上面简单列举了一些HazelcastGridGain的重叠功能,而两者的差异之处主要在于以下几个方面:

Ø  整体功能的全面性:围绕内存计算提供的功能

Ø  使用性:对SQL支持的完整性、对Continuous Query的支持、以及与持久化存储的数据集成

Ø  性能:免费的off-heap存储实现。

Ø  可靠性方面:事务的隔离性、内存溢出到磁盘

Ø  管理:提供强大的后台管理界面

此外,企业版还提供了Portable跨平台对象、安全和审计、数据中心复制、可还原的本地cache以及split-brain网络分段问题解决等功能。本文暂不关注企业版中的附加功能,下面开始着重介绍上面列举的开源社区版与Hazelcast的功能差异。

全面的内存计算功能栈

从整体功能上来说,GridGain是个出色的多面手,不仅可以完成本职工作-内存计算/数据网格,还提供了:

1)     GGFS(GridGain In-Memory File System),类似Spark生态圈中的Tachyon,能够加速MapReduce任务的执行。

2)     完整的ACID和事务支持,可以作为内存数据库。

3)     流式数据/事件处理,可以作为CEP事件处理器。


丰富的查询功能

一般开源IMDG产品支持基本的对象过滤查询能力,但GridGain底层借助H2数据库引擎来解析和执行SQL,所以支持复杂的对象联结查询,类似于GemFire中的OQL提供的功能,以及仅在Hazelcast商业版本中才支持的Continuous Query功能。

 

首先来看一下我们的测试数据和Entity是什么样子,代码忽略了构造函数、getter/settertoString等方法。Person中包含了idnamesalary三个基本属性,并与Organization是多对一的关系,与Address是一对一的关系。


对于POJO要注意几点:1)查询中涉及的成员变量都要标上@GridCacheQuerySqlField注解;2)因为POJO会被哈希到其他结点上的分区,所以要实现序列化接口3)下面例子只测试了one-to-one(直接嵌套实体Address)many-to-one(通过orgId关联其他实体)关系的查询,而没有尝试one-to-manymany-to-many(都是在实体中嵌套另一实体id的集合)4GridCacheConfiguration要开启setQueryIndexEnabled(true)

3.1 简单的过滤查询

简单的对象过滤查询是最常见的,也是其他网格产品像Hazelcast支持的。


3.2 cache下的join查询

cache下可能会关联的数据,可以通过数据亲和性设置使相关数据分配到同一分区中,从而避免网络传输开销。当然,Hazelcast也是支持数据亲和性的,本节关注的重点是join查询。代码类似于3.3中的跨cache查询,差别只不过是:1Organization对象不是保存到org-cache,而是与Person对象一起保存到person-cache2SQL中不需要显式指明缓存名称,因为对象都在一个缓存person-cache中。

3.3 cachejoin查询

joincache(org-cache)必须是REPLICATE的,从而在各个结点上都存在,不会产生交叉join(注:Impala支持这种join,将产生N*M次数据通信)


3.4 字段查询

GridGain不仅支持查询结果为实体,同时也支持各种SQL函数对实体进行各种操作,如聚合、字符串操作等。


3.5 Continuous查询

Continuous查询不支持SQL,只支持Predicate风格组装查询。


执行效果如下,首先初始化到缓存中的Person对象中有一个salary=300,满足条件,所以本地callback收到通知。之后我们试着更新缓存中的一个Person对象的salary=250,于是再次收到通知。最后我们新建一个Personsalary=500,并保存到缓存中,于是再次收到通知。这就是Continuous Query的运行效果。


 

集成持久化存储

类似HazelcastGridGain也提供了read-throughwrite-through以及异步write-behind三种与后端持久化存储通信的方式。此外,GridGain还支持事务提交时批量write,以及缓存entry即将过期时自动重新re-cache(refresh-ahead)功能。像refresh-ahead功能在GemFire等商业产品中才会实现。


堆外内存存储

不像Hazelcast等开源产品只在商业版中提供off-heap存储功能,GridGain在开源版本中就提供了此功能,从而显著地扩充JVM管理的内存容量,并减轻GC压力和停顿时间。GridGain提供了ONHEAP_TIERED(默认堆优先,溢出到非堆内存)OFFHEAP_TIERED(不使用堆,直接将所有entry放入非堆内存)OFFHEAP_VALUES(key存储在堆,value存储在非堆内存)三种模式。当堆和非堆内存都不足时,还可以开启SWAP,将数据溢出到磁盘(详见第7部分:数据溢出到磁盘)。下图表示了堆、非堆、磁盘、外围存储的容量和延迟的关系。


完整的ACID和事务支持

内存事务与传统数据库事务有一点点不同。因为IMDG产品使用的是易逝内存,所以故障或断电时内存数据会全部丢失。一般IMDG重启时会从备份结点或其他持久化存储中恢复数据。但这不代表内存事务不重要!只要集群是存活的,GridGain就要保证不同结点间的数据一致性。为此,GridGain提供了两种TRANSACTIONALATOMIC两种配置:

Ø  TRANSACTIONAL:完整的ACID属性的事务,以及显式的锁。

Ø  ATOMIC:没有事务和锁。

GridGain使用2PC(两阶段提交)协议实现分布式事务,同时支持乐观悲观两种模式。乐观模式下所有key在提交时才会加锁,所以在Prepare阶段,prepare消息发送给各结点获取事务中将要操作的key的锁,各结点通过ACK消息应答。而悲观模式下,所有key在提交前就已加锁,所以Prepare阶段不需要做任何事。在Commit阶段,commit消息发送给各结点提交,若失败则发送回滚消息给各结点。可以设置各个结点之间是同步还是异步提交(注:Hazelcast支持一种2PC扩展协议,具体的优势还有待研究)。最后,GridGain支持READ_COMMITTEDREPEATABLE_READSERIALIZABLE三种事务隔离级别,默认是REPEATABLE_READ。而Hazelcast只支持REPEATABLE_READ一种。

数据溢出到磁盘

在第5部分堆外内存存储中提到过GridGain的层次化存储,以下面的缓存配置为例,它同时开启了off-heapswap1)首先,数据优先保存在堆内存中。2)当entry总数超过100个时,会通过LRU淘汰到非堆内存中。3)当超过非堆内存的最大容量5MB时,会将多出的数据保存在磁盘上。当然,磁盘IO操作的代价是很大,我们可以优先考虑使用超大的非堆内存,或者使用SSD闪存,以及开启操作系统的磁盘IO缓存来进行优化。

GridCacheConfiguration cacheCfg = new GridCacheConfiguration();

cacheCfg.setEvictionPolicy(new GridCacheLruEvictionPolicy(100));

cacheCfg.setOffHeapMaxMemory(5 * 1024L * 1024L);

cacheCfg.setSwapEnabled(true);

强大的管理界面

首先,以相同配置启动三个GridGain实例。然后,启动gridgain-fabric-os-6.5.5/bin/ ggvisorui.exe,在Visor GUI中选择File->Connect->External标签页下,直接localhost+默认端口连接即可进入Dashboard。在这能看到我们刚刚启动的三个结点的总体信息。


点击Data Grid标签页,可以查看各个cache的内存使用、读写以及命中情况,例如我们初始化了3Person2Organization对象,并分别保存到了person-cacheorg-cache中,于是我们可以在此标签页看到Primary EntryWrite个数都是32



 

相关内容

    暂无相关文章