将主存储器用作存储区域而不是使用磁盘是并不是一种全新的尝试。你可以在日常生活中发现许多使用主内存DBMS(数据库管理系统)(MMDB)执行比磁盘快得多的情况。一个例子是你使用手机的时候。当你发短信或给你的朋友打电话时,大多数移动服务提供商会使用MMDB来让你尽快获取朋友的信息。
内存数据网格(IMDG)与MMDB相同,它也将数据存储在主内存中,但它具有完全不同的架构。IMDG的特性可以总结如下:
换句话说,IMDG旨在将数据存储在主内存中,确保可扩展性并存储对象本身。IMDG产品,无论是开源还是商业产品,包括:
本文目的不是比较这些产品的功能和性能。相反,我们将研究IMDG的架构并讨论NHN如何利用它。
截至2012年6月,使用SATA接口的固态硬盘(SSD)性能大约是500 MB / 秒,而使用昂贵的PCI Express的SSD记录大约是3000 MB / 秒。由于10,000 转/分钟的 SATA 机械硬盘(HDD)性能大约为150 MB / 秒,因此SSD比HDD快4-20倍。但是,DDR3-2500的性能达到了20,000 MB / 秒。主存储器的处理性能比HDD快800倍,比SSD快40倍,比最快的SDD快7倍。而且,最新的x86服务器支持每台服务器扩展至数百GB的主内存。
Michael Stonebraker表示,典型的联机事务处理(OLTP)数据容量大约为1 TB,并且OLTP处理数据容量不会增加。如果使用1TB或更大容量的主存储器的服务器变得更为常用,则至少在OLTP领域,你将能够对放置在主存储器中的全部数据进行操作。
在计算史上,“加快速度”一直是每个人都应该追求的最佳美德。随着主内存容量的增加,平台有必要主动使用主内存作为存储区域,而不是永久存储。
要将主内存用作存储区域,你应该克服两个弱点:有限的容量和可靠性。你需要处理超过服务器主存储器最大容量的数据,并且在发生故障时不会发生数据丢失。IMDG通过使用分布式架构确保水平可伸缩性来克服容量限制,并通过复制系统解决可靠性问题。
尽管每个产品的细节存在一些差异,但你可以概括IMDG体系结构如图一。
图一: IMDG架构
应用程序服务器具有由IMDG提供的客户端库,并使用该库访问IMDG。许多IMDG产品提供将数据同步到RDBMS(Rational Database Management System,关系型数据库管理系统)的功能。但是,你不需要建立单独的永久存储系统(例如,RDBMS)。一般来说,IMDB可以通过序列化来存储对象。一些产品提供了存储实现可串行化接口的对象的功能,而一些IMDG提供独立的序列化方法。当然,由于无模式结构,使用它们非常方便。它可以理解为内存键值数据库存储和检索对象的概念。
IMDG中使用的数据模型是Key-Value(键值对)。因此,可以通过使用此密钥来分发和存储数据。有许多方法,比如在Arcus(NHN的Memcached Cloud)中使用一致性散列模型,或者像Hazelcast中使用简单的模数方法。以这种方式存储数据时,至少有一个节点用作复制系统来响应任何故障。
产品有各种接口。一些产品提供了一种类似于SQL的语法,用于通过JDBC(Java 数据库连接)进行访问,一些产品提供了实现Java集合的API,你可以在其中为多个节点使用HashMap或HashSet。
与Arcus等缓存系统相比,IMDG具有不同的用途和目的。图二展示了Arcus架构的简单结构
图二, 缓存系统架构如Arcus
诸如Arcus之类的缓存系统也使用主存储器作为存储区域并保证水平可伸缩性。从这个意义上讲,它们与IMDG相同。有必要在Arcus等缓存系统中使用永久存储区域,但在IMDG中是可选的。
表1:IMDG和缓存系统之间的读/写性能比较。
缓存系统 | 内存数据网格(IMDG) | |
---|---|---|
读 | 如果数据在缓存中,则不会从数据库中读取数据。如果数据不在缓存中,则会从数据库中读取数据。 | 由于经常从IMDG主内存读取, 因此速度快 |
写 | 由于数据是在永久存储器中写入的,因此应用缓存系统与提高写入性能无关。 | 即使配置为将数据同步到永久存储,某些产品也支持非同步写入。在这种情况下,你可以看到非常高的写入性能。 |
高速缓存系统和IMDG在数据迁移是否可用,是否确保可靠性以及是否提供复制功能方面也有所不同。
IMDG产品之一HazelCast的功能列表如下。由于HazelCast持有双重许可证政策,你必须购买商业许可证才能使用某些功能,例如ElasticMemory(弹性内存)。你可以轻松找到使用参考信息,因为该产品的许多功能可以作为开源免费使用。
尽管很难说HazelCast的功能是所有其他IMDG产品提供的功能,但我决定在这里介绍它,因为我认为HazelCast是了解IMDG功能的一个很好的例子。
它是一个实现Map<?,?
的类。映射(Map)数据被分配并分配给多个IMDG节点。由于RDBMS表可以表示为Map<?, ?>Map<Object key, List<Object>>
,因此可以获得类似于使用分片RDBMS时的数据分配效果。
HazelCast也支持类似SQL中DistributedMap
的功能。在检查映射中的值时,可以使用类似SQL的子句,如子句WHERE
,LIKE
, IN
和BETWEEN
。
HazelCast不仅提供了将所有数据存储在内存中的功能,还提供了将其存储在永久存储中的功能。将数据存储在永久性存储中时,可以将其配置为用作缓存系统。你也可以仅将必要的数据存储在内存中,并通过选择LRU(Least Recently Used, 最近最少使用)或LFU(Least Frequently Used,最不经常使用)算法将剩余的不常用数据存储在永久存储器中。
另外,你可以在分布式环境中使用MultiMap
。如果你检索某个关键字,则可以以MultiMapCollection<Object>
的形式获取值列表。
你可以使用DistributedSet
(分布式集合),DistributedList
(分布式列表)或DistributedQueue
(分布式队列)。这种分布式收集对象中的数据不是存储在单个IMDG节点中,而是分布并存储在多个节点中。出于这个原因,可以维护存储在多个节点中的单个列表对象或设置对象。
HazelCast提供了主题阅读的功能,以保证发布消息的顺序。这意味着你可以将其用作分布式消息队列系统。
这实际上是一个分布式锁。你可以使用单个锁在多个分布式系统中执行同步。
你可以使用DistributedMap和DistributedQueue的事务。通过提交/回滚功能,即使在应该更谨慎地执行操作的环境中,也可以使用IMDG。
上面介绍的大多数产品都使用Java作为实现语言。由于应该使用数十GB的堆(heap),可能需要相当长的时间来完成完整的GC。出于这个原因,IMDG提供了一种方法来克服这个限制。该方法是使用堆外存储器(直接缓冲区)。当JVM接收到直接缓冲区创建请求时,它将内存分配到堆外的空间并使用它。对象存储在这个分配的空间中。由于直接缓冲区不再是GC的空间,因此不会发生完整的GC问题。通常,访问直接缓冲区比访问堆缓冲区花费的时间更长。不过,如果你使用直接缓冲区,则可以分配较大的空间并减少完整GC的负担。因此,使用大容量内存空间时,可以通过减少完整GC的时间来获得一定的处理时间。
图三: 堆,直接缓冲区和硬盘(资源)的比较
但是,它需要专业知识才能通过使用直接缓冲区来存储和检索对象。你需要具备制作内存分配器所需的专业知识。出于这个原因,只有在商业IMDG产品中才提供使用堆外存储器存储对象的这一特性。
目前IMDG主要用作缓存系统。但是,IMDG是一个可能发展成为主要存储区域的平台。在很多情况下,分布式映射可以可靠地替换RDBMS表。某些产品提供分布式锁定,如果可以基于这种分布式锁定提供完整性约束功能,则可以使用IMDG替换RDBMS。在这种情况下,你将能够通过使用RDBMS作为后端系统来响应统计处理。这意味着RDBMS在互联网服务中的角色可以成为辅助。如果提供完整性约束功能,则基于急速以及过去难以提供的其他功能特性可以提供令人愉快的用户体验。
我认为,考虑到这种可能性,有必要认真研究将IMDG作为NHN互联网服务的主要存储空间的价值。