Hybrid Storage(混合存储)
混合内存系统包含每个节点上的索引和数据,操纵与物理存储的互动。它还包括用于自动移除就数据的模块以及碎片整理等模块。
Aerospike可以将数据存储在DRAM,传统磁盘及SSD硬盘,每个namespace可以分别进行配置。这种配置弹性允许应用程序开发者在内存中配置一个小但频繁访问的namespace,在相对廉价的SSD硬盘中配置一个大的namespace。
在SSD上优化数据存储的重要工作已完成,包括穿透文件系统利用底层SSD读写模式。
Philosophy(理念)
不同于 Large Data
Types,一条记录的所有数据存储在一起。每行的存储限制默认为 1 MB。
存储写时复制(copy-on-write),由碎片整理进程回收空间。
每个namespace配置固定大小的存储。每个节点必须有一样的namespace,并且每个namespace大小一致。
存储可以配置为纯内存无持久化,内存并持久化,或者闪存(SSD)
持久化存储(磁盘)必须是闪存或高性能块存储设备(云),或者是任何存储设备上的文件。
Data in DRAM(内存中的数据)
内存中的数据-无持久化-好处是高吞吐量。即使是高性能的现代闪存存储性能依旧不及内存,内存的价格也在快速下降。
数据通过 JEMalloc
分配器进行分配。JEMalloc允许分配到不同的池。长期分配-比如那些为存储层所做的-可以单独分配。我们发现JEMalloc分配器在低碎片的情况下具有超常性能。
通过DRAM的多副本可以获得高级别的可靠性。由于Aerospike在集群节点损坏或节点加入时重新进行数据分配和数据复制,可以获得高级别的"k-safety" 。自动从数据副本中恢复节点数据。
由于Aerospike的随机数据分布( data distribution),当几个节点失败时数据不可用风险相当小。例如,在一个有两个数据拷贝的10节点集群中,如果两个节点失效。失效数据的数量大约2%,1/50的数据。
当持久层被配置,读发生在内存副本。通过数据路径进行写入。
Data on SSD / Flash(SSD上的数据)
当数据被写入,为避免相同记录写入冲突会在行上加写入闩。在某些集群状态下,数据需要从其他节点读入并解决冲突问题。
当写入被确认,内存中的记录在主节点被更新。被写入的数据添加到写缓冲区。如果写缓冲区满了,排队写入磁盘。类似最大行数,依赖于写缓冲区大小和写吞吐量,这里存在一些未提交数据的风险。
如果有副本,当更新时他们的索引同时更新。当多有内存中的副本都被更新,结果将返回客户端。
系统可以被配置为在所有写完成之前返回结果-延迟一致性。
Storing data(存储数据)
Aerospike数据包括整型、字符串、二进制对象、原生序列化类型、列表、映射及LDTs。
除了更高效的"single bin mode",bin-Aerospike的列-每个bin有一个bin名称,它用一个字符串表进行存储。每个列的名称被存储移除,一个namespace中可以存储32K个唯一bin名称。
如果需要更多的bin名称,可以考虑使用map。利用map,你可以存储任意数量的键值对,通过UDF访问高效访问数据。
如果通过类似java class这样的复杂语言类型访问数据。Aerospike客户端将使用语言原生的序列化系统。数据将被存储为语言指定的 "blob type"。这允许相同语言的客户端使用清晰的代码读取数据,但是大多数语言的默认序列化很简陋。
整型以8字节存储,这限制了当前版本整型的值。Aerospike网络协议允许变长整型。
String以 UTF-8字符集存储。对大多数字符串UTF-8比unicode更紧凑。为了允许夸语言兼容,客户端函数库将原始的unicode字符转换成UTF-8.
最有效率的方式是使用二进制对象 (blobs)。其大小限制于记录大小限制相当。许多部署使用自己的序列化,可能对对象压缩后直接存储。这样做意味着数据不能容易的通过UDF访问
复杂类型呈现为msgpack本地存储。复杂对象在客户端被序列化,利用写协议发送。当应用到简单的get/put操作,网络格式无需序列化或转换,直接写入存储。
Flash optimizations(闪存优化)
碎片整理器追踪磁盘上每个块上的活动记录数量,回收低于最低使用的块。碎片整理器不断扫描活动快,查找那些有一定数量空闲空间的块。
Eviction based on storage(基于存储的回收)
碎片整理器追踪磁盘上每个块上的活动记录数量,回收低于最低使用的块。清除器负责移除过期记录,当系统到达预设的高水位线时回收内存。当配置namespace时,管理员指定namespace使用内存的最大值。通常操作下,清理器查找过期数据,释放内存和磁盘空间。清理器也通过namespace追踪内存使用情况,如果内存达到预设的高水位线,即使记录不是必须过期,清理器也会释放比较旧的记录。当系统内存达到使用上限时,通过允许清理器移除老的数据,Aerospike可以被作为一个高效的LRU(最近最少使用算法)
cache使用。注意,记录的年龄通过其最后一次修改时间来度量,应用程序可以在任何时间修改记录的存活期。应用程序也可以指定记录永远不被自动回收。
Large records (Sub-Record Storage Mechanism)
大记录(子记录存储算法)
为了支持大对象的存储能力,Aerospike支持新的底层存储模型,这就是所说的“子记录”(sub-records)。子记录(sub-records)与常规记录很相似,主要的不同点事不能直接访问。子记录链接在父记录上并通过父记录进行访问。子记录与父记录共享分区ID和内部记录锁,所以在迁移时与父记录一起移动,与父记录一起通过一样的隔离机制保护。
Aerospike LDT 使用这种存储算法构建。LDT bins/records(具有LDT类型bin的记录)不是连续存储的相关记录,而是划分为多个子记录(大小在2k至1M)。一个子记录至于一个bin有关,可以包含多个项目(例如,8k的子记录可以持有100个80bytes的字符串数据)。子记录之间是互连的,链接在父记录上来提供有效的更新和查找。
因此,LDT对象利用Aerospike健壮的复制,再平衡及迁移算法来确保即时一致性和高可用。LDT对象通过客户端API在数据库服务器端处理。
子记录机制有如下好处
- 利用SSD能力执行随机读不需要任何其他开销,也不需要想传统数据库实施时所担心的数据在存储上的排列问题。
- 当执行指定的LDT操作(例如插入100bytes)成本只相当于与更新LDT条目,客户端与服务器直接也没有LDT的交互成本。
大记录用不同的方式存储,但是允许数据超过单记录的限制,请阅读Large Data Type Architecture.
原文链接: <http://www.aerospike.com/docs/architecture/storage.html>
译 者:北京IT爷们儿