一、Aerospike概念
-
Aerospike
是一个分布式、可扩展的Nosql
数据库。以KV
键值进行存储,当然也支持文档存储模型,在国内的并没有广泛使用,而在国外却大多数用在广告行业,以存储大数据量及强一致性而被广泛使用。
Aerospike
的三层架构:
- 客户端层
Client Layer
:
- 这个集群感知层包括开源客户端库,它实现
Aerospike API
、跟踪节点并知道数据在集群中的位置。包括C
、C#
、Java
、Go
、Python
、Rest
、Node.js
、Ruby
、Php
、Rust
等客户端。 - 实现
Aerospike API
、客户端-服务器协议,并直接与集群对话。 - 跟踪节点并了解数据的存储位置,即时了解集群配置的更改或节点何时启动或关闭。
- 实现自己的
TCP/IP
连接池以提高效率。还检测未上升到集群中节点故障级别的事务故障,并将这些事务重新路由到具有数据副本的节点。 - 透明地将请求与数据直接发送到节点,并根据需要重试或重新路由请求(例如,在集群重新配置期间)。
- 分布层
Clustering and Data Distribution Layer
-
Aerospike
“无共享”架构旨在通过自动故障转移、复制和跨数据中心复制 (XDR) 可靠地存储 TB 级数据。该层线性缩放。分布层旨在通过所有集群管理功能的系统自动化来消除手动操作。它包括三个模块: - 集群管理模块:跟踪集群中的节点。关键算法是基于
Paxos
的gossip-voting
过程,该过程确定哪些节点被视为集群的一部分。Aerospike
实现了一个特殊的心跳(主动和被动)来监控节点间的连接。 - 数据迁移模块:当您添加或删除节点时,
Aerospike
数据库集群成员资格被确定。每个节点使用分布式哈希算法将主索引空间划分为数据切片并分配所有者。Aerospike
数据迁移模块智能地平衡集群中所有节点的数据分布,确保每一位数据在所有集群节点和数据中心之间复制。此操作在系统复制因子配置中指定。 - 事务处理模块:根据请求读写数据,并提供一致性和隔离性保证。该模块负责
- 同步/异步复制: 对于具有即时一致性的写入,它会在提交数据并将结果返回给客户端之前将更改传播到所有副本。
- 代理: 在集群重新配置期间,客户端层可能暂时过时的极少数情况下,事务处理模块透明地将请求代理到另一个节点。
- 重复数据的解决:对于从分区中恢复的集群(包括重新启动节点时),该模块解决了不同数据副本之间的任何冲突。分辨率可以基于生成计数(版本)或上次更新时间。
一旦第一个集群启动,您可以在其他数据中心安装额外的集群并设置跨数据中心复制,以确保如果数据中心出现故障,远程集群接管工作负载而对用户的干扰最小或没有。
- 存储层
Data Storage Layer
-
Aerospike
是具有无模式数据模型的键值对存储。数据流入策略容器、命名空间,它们在语义上类似于RDBMS 系统中的数据库。在命名空间内,数据被细分为集合(RDBMS表)和记录(RDBMS行)。每条记录都有一个在集合中唯一的索引键,以及一个或多个保存与记录关联的值的命名箱(RDBMS列)。 - 您不需要定义集和箱。为了获得最大的灵活性,可以在运行时添加它们。
-
bin
中的值是强类型的,可以包含任何支持的数据类型。bin
没有类型,因此不同的记录可以具有相同的bin
,但具有不同类型的值。
- 索引,包括主索引和可选的二级索引,默认存储在 DRAM 中,以实现超快速访问。主索引也可以配置为存储在持久内存或 NVMe 闪存设备上。值可以存储在 DRAM 中,也可以更经济高效地存储在 SSD 中。您可以单独配置每个命名空间,因此小型命名空间可以利用 DRAM,而较大的命名空间可以获得 SSD 的成本优势。
- 数据层旨在提高速度并显着降低硬件成本。它可以在内存中运行,从而无需缓存层,也可以利用闪存存储的独特优化。无论哪种方式,数据都不会丢失。
- 在
Aerospike
中:
- 1亿个key只占用6.4GB。尽管密钥没有大小限制,但每个密钥都有效地存储在 64 个字节中。
- 本机、多线程、多核闪存 I/O 和Aerospike 日志结构化文件系统利用了低级 SSD 读写模式。为了最小化延迟,写入磁盘是在大块中执行的。这种机制绕过标准文件系统,历史上调整为旋转磁盘。
Smart Defragmenter
和Evictor
协同工作以确保 DRAM 中有空间,并且数据永远不会丢失并且始终安全地写入磁盘。
- 智能碎片整理程序:跟踪每个块中的活动记录数并回收低于最低使用水平的块。
-
Evictor
:如果系统超出设置的高水位线,则删除过期记录并回收内存。过期时间是按命名空间配置的。记录年龄从最后一次修改开始计算。应用程序可以覆盖默认生命周期并指定永远不应驱逐记录。
二、Aerospike存储模型
Aerospike
采用混合存储模型,混合内存系统包含存储在每个节点中的索引和数据,处理与物理存储的交互,包含用于自动从数据库中删除旧数据的模块,以及对物理存储进行碎片整理以优化磁盘使用。
- 动态随机存取存储器
(DRAM)
。 - 非易失性内存扩展
(NVMe)
闪存或固态驱动器(SSD)
。 - 持久内存
(PMEM)
。 - 传统的旋转媒体。
- 各存储之间的优缺点:
主索引存储 | NCMe闪存 | 动态随机存取存储器 | PMEM |
NVMe 闪存 | 所有 NVMe 闪存:超大型记录集 | 不建议 | 不建议 |
动态随机存取存储器 | 混合:最佳性价比 | 高性能。没有坚持 | 不常见 |
PMEM | 混合:重启后快速重启。非常大的数据集 | 不建议 | All PMEM:重启后快速重启,高性能 |
SSD(固态硬盘)
和闪存
- 当从客户端接收到写入(更新或插入)时,会对该行进行闩锁,以避免对该集群的同一记录进行两次冲突写入(在网络分区的情况下,可能会采取冲突写入以提供可用性,稍后解决)。在某些集群状态下,可能还需要从其他节点读取数据并解决冲突。在写入验证之后,记录的内存表示会在主节点上更新。将要写入设备的数据放置在缓冲区中进行写入。当写入缓冲区已满时,它会排队到磁盘。写入缓冲区大小(与最大行大小相同)和写入吞吐量决定了未提交数据的风险,并且配置参数允许刷新这些缓冲区以限制潜在的数据丢失。副本及其内存索引随后会更新。
Aerospike Defragmenter 跟踪磁盘上每个块上的活动记录数,并回收低于最低使用水平的块。
- 在
Aerospike
中
- 记录数据存储在一起。
- 一行的默认存储大小为 1 MB。
- 存储是写时复制。
- 在碎片整理期间回收可用空间。
- 每个命名空间都有固定的存储量,每个节点在每台服务器上必须有相同的命名空间,这需要每个命名空间的存储量相同。
- 名称解释:
namespace
,名称空间,同一集群中的不同命名空间可以使用不同类型的存储类型,包括NVME闪存
、DRAM动态随机存取存储器
、PMEM持久内存
。命名空间包含记录、索引和策略。策略规定命名空间行为,包括:
- 数据的物理存储方式。
- 一条记录存在多少个副本。
- 记录到期时。
set
,相当于传统数据库的表。在命名空间中,记录可以属于一个称为set的可选逻辑容器。集合允许应用程序对集合中的记录进行逻辑分组。集继承由其命名空间定义的策略。您可以定义特定于该集合的其他策略或操作。例如,可以为特定集合指定二级索引,或者可以对特定集合执行扫描操作。
命名空间中的记录不必在一个集合中,而只是属于命名空间。record
,相当于传统数据库的行,并且每一行中都会有一个唯一的key。数据库中存储的基本单位。记录可以属于命名空间或命名空间内的集合。单个记录由键唯一标识。记录由以下部分组成:
-
key
唯一标识,存储和获取数据都需要指定 -
metadata
元数据,包括版本信息,存活时间,上次更新的时间
bin
,相当于传统数据库的字段,并且可以在这上面声明二级索引。记录数据存储在 bin 中。Bins 由名称和值组成。bins 不指定数据类型,而是由 bin 中包含的值定义数据类型。这种动态数据类型在数据模型中提供了灵活性。例如,一条记录可以包含带有字符串值bob的 bin id。bin 的值始终可以更改为不同的字符串值,但也可以更改为不同数据类型的值,例如整数。
Aerospike支持的数据类型
- 标量数据类型:
Integer
- 支持整数值和二级索引
Double
- 始于版本3.6.0
String
- 大小限制在128kb,同时还支持二级索引
Boolean
- 在服务器上存储为单个字节。
- 对 Aerospike 5.6.0 版中添加的布尔 bin 值的支持。
- 在 5.6.0 版之前,只有 List 和 Map 数据类型可以包含布尔值。
Blob/bytes
-
Blob
是特定大小的字节数组,可以存储任何类型的任何二进制数据。请注意,字节不是以 NULL 结尾的。 - 从 4.6.0 版开始,可将广泛的 按位运算API应用于字节值。
blob
类型在java、C# 、node.js、Python、C、PHP中不受支持,会自动反序列化。
- 地理空间类型
GeoJSON
- 集合数据类型:
-
List
可以嵌套标量数据类型,具体包括有序列表和无序列表。其大小可以通过[write-block-size
]进行配置,值得注意的是通过lua UDF
定义的函数不接受List
类型 -
Map
可以嵌套标量数据类型
- 概率数据类型:
HyperLogLog
三、Aerospike策略
- Aerospike 允许以极大的灵活性进行读写。使用 Aerospike 客户端
policy
,您可以创建乐观并发的读-修改-写模式,控制生存时间,并仅在以前不存在记录时才写入记录(反之亦然)。
这种类型的操作非常快,因为像生成和生存时间这样的信息都存储在主键索引中。检索数据对象不需要额外的工作。 - 设置默认客户端策略
// 设置默认的策略
ClientPolicy clientPolicy = new ClientPolicy();
clientPolicy.readPolicyDefault.replica = Replica.MASTER_PROLES; // 指定单条记录客户端将访问那个副本的数据,这里是指以循环方式在包含密钥的主分区和复制分区的节点之间分配读取。写入始终使用包含密钥主分区的节点。
clientPolicy.readPolicyDefault.consistencyLevel = ConsistencyLevel.CONSISTENCY_ALL;
clientPolicy.readPolicyDefault.socketTimeout = 100;
clientPolicy.readPolicyDefault.totalTimeout = 100;
clientPolicy.writePolicyDefault.commitLevel = CommitLevel.COMMIT_ALL; // 写策略提交级别
clientPolicy.writePolicyDefault.socketTimeout = 500;
clientPolicy.writePolicyDefault.totalTimeout = 500;
AerospikeClient client = new AerospikeClient(clientPolicy, new Host("seed1", 3000));
- 按事物设置客户端策略
- 要基于每个事务设置策略,请将所需的策略设置传递给单个 API 调用。例如,要使用
master
提交级别执行写入,如果存在默认策略则会覆盖。
// Make a copy of the client's default write policy.
WritePolicy policy = new WritePolicy(client.writePolicyDefault);
// Change commit level.
policy.commitLevel = ConsistencyLevel.COMMIT_MASTER; // 设置只能由master提交
// Write record with modified write policy.
client.put(policy, key, bins);
- 当然你也可以在服务器上配置参数覆盖客户端所设置的事物数据一致性策略
read-consistency-level-override
write-commit-level-override
- Replica (
Policy.replica
) 指定在单条记录操作期间客户端将访问哪个副本:
-
SEQUENCE
(默认)——首先尝试包含密钥主分区的节点。如果连接失败,所有命令都会尝试包含复制分区的节点。如果达到 socketTimeout,读取也会尝试包含复制分区的节点,但写入仍保留在主节点上。 -
MASTER
—使用包含密钥主分区的节点。 -
MASTER_PROLES
—以循环方式在包含密钥的主分区和复制分区的节点之间分配读取。写入始终使用包含密钥主分区的节点。 -
RANDOM
—以循环方式在集群中的所有节点上分发读取。写入始终使用包含密钥主分区的节点。
- 一致性级别 (
Policy.consistencyLevel
) :
CONSISTENCY_ONE
(默认)—在返回之前读取单个副本。CONSISTENCY_ALL
从拥有记录父分区的唯一版本的所有节点读取。
1.在集群重新配置期间,读取单个副本可能不会返回最近写入的版本。如果您希望服务器提供“重复解析”,即联系副本并找到最新版本,包括更新主副本,请将一致性级别策略设置为
ConsistencyLevel.CONSISTENCY_ALL
2.一致性级别配置不适用于
strong-consistency
设置为true
。
- 线性化读取(
Policy.linearizeRead
)
- 如果启用,线性化读取策略 (
Policy.linearizeRead
) 会强制对支持强一致性模式的服务器命名空间的读取进行线性化。
- 发送密钥 (
Policy.sendKey
)
- 如果启用,发送密钥 (
Policy.sendKey
) 会在读取和写入时发送用户定义的密钥以及哈希摘要。如果在写入时发送密钥,则密钥将与记录一起存储在服务器上,并在扫描和查询时返回给客户端。
- 最大重试次数
Max retries
- 指定中止当前事务之前的最大重试次数。初始尝试不计为重试。如果超过 maxRetries,事务将中止并出现超时异常。
- 不应该重试非幂等的数据库写入(例如 add()),因为如果客户端超时之前的事务尝试,可能会多次执行写入操作。对非幂等写入使用不同的 WritePolicy 非常重要,它将 maxRetries 设置为零。
- 总超时(
Policy.totalTimeout
)
- totalTimeout 在客户端上进行跟踪,并与有线协议中的事务一起发送到服务器。客户端很可能首先超时,但服务器也有能力使事务超时。
如果 totalTimeout 不为零并且在事务完成之前达到 totalTimeout,则事务将中止并出现超时异常。
- 响应超时(
Policy.socketTimeout
)
- 如果设置了响应超时时间,并且快要达到设置的值时,则会检查最大重试策略和总超时策略,如果都没有超过则重试事务。
- 如果
socketTimeout
和totalTimeout
都非零并且socketTimeout > totalTimeout
,那么socketTimeout
将被设置为totalTimeout
。
- 重试时睡眠(
Policy.sleepBetweenRetries
)
- 重试之间的睡眠 (
Policy.sleepBetweenRetries
) 是重试之间睡眠的毫秒数。输入零跳过睡眠。当 maxRetries 为零时忽略此字段。该字段在异步模式下也会被忽略。 - 睡眠仅在连接错误和服务器超时时发生,这表明节点已关闭并且集群正在重组。当客户端的
socketTimeout
过期时,不会发生睡眠。 - 当节点关闭时,读取不必休眠,因为集群在集群重组期间不会关闭读取。读取的默认值为零。
- 写入的默认值也为零,因为默认情况下不会重试写入。当节点关闭时,写入需要等待集群进行重组。节点故障的立即写入重试已被证明会始终导致错误。如果写入时
maxRetries
大于零,则sleepBetweenRetries
应设置得足够高以允许集群重新调整 (>= 500ms)。
- 写入策略模式(
WritePolicy.recordExistsAction
)
-
UPDATE
(默认)—创建或更新记录。将写入命令箱与现有箱合并。 -
UPDATE_ONLY
—仅更新记录。如果记录不存在则失败。将写入命令箱与现有箱合并。 -
REPLACE
—创建或替换记录。删除写入命令 bin 未引用的现有 bin。 -
REPLACE_ONLY
—仅替换记录。如果记录不存在则失败。删除写入命令 bin 未引用的现有 bin。 -
CREATE_ONLY
—仅创建。如果记录存在则失败。
- 写入提交策略(``WritePolicy.commitLevel
)
)指定服务器在成功返回客户端之前必须成功写入多少副本:
-
COMMIT_ALL
(默认)——在返回之前提交所有副本。强一致性模式所必需的。 -
COMMIT_MASTER
—仅提交主副本并prole
异步复制副本后返回。在强一致性模式下,COMMIT_MASTER
会导致错误。 - 修改记录(包括
write
、remove
、operate
和 UDF 函数)时的默认客户端行为是在从写入相关 API 返回成功之前确认所有副本都已成功写入。此默认策略 (CommitLevel.COMMIT_ALL
) 提供最高级别的写入一致性。 - 如果需要较低的写入延迟并且应用程序可以容忍较低的写入一致性级别(可能会出现“脏读”,即如果之前从非主副本读取相同记录,则会返回较旧的值)副本已提交),将提交级别策略设置为
CommitLevel.COMMIT_MASTER
. 从 Aerospike 5.7 开始,如果客户端推送的COMMIT_MASTER
事务速率高于服务器的复制系统可以处理的速率,那么服务器将通过将这些事务转换为COMMIT_ALL
.
commitLevel 配置不适用于
strong-consistency
设置为true
。
- 写入生成策略(
WritePolicy.generationPolicy
)指定如何根据记录生成处理记录写入
- 记录生成是一个使用整数值的内部计数器,每次更新记录时 Aerospike 都会递增。(在这个上下文中,“生成”不是指“生成的行为”,而是“版本”。)当插入记录时,计数器从 1 开始。因此,计数器当前为 5 的记录, 已更新四次。客户端应用程序不能直接更改计数器的值。读取记录不会导致 Aerospike 增加其计数器。
- 当 Aerospike 处于可用和分区容错 (AP) 模式时,Aerospike 在更新 64K 次后将记录的计数器重置为 1。当 Aerospike 处于强一致性模式时,它会在记录更新 1K 次后将记录的计数器重置为 1。
- 客户端应用程序可以使用此计数器与其他客户端应用程序协调读取-修改-写入操作序列。
- 例如,假设客户端应用程序需要从记录中读取数据,修改数据,然后将修改后的数据写回记录中。读取记录需要锁定它,写入记录也是如此。但是,在客户端应用程序修改数据期间,它不会锁定记录。另一个客户端应用程序可以在第一个客户端应用程序能够获得写锁并写入修改后的数据之前更新相同的记录。
- 如果生成策略设置为
GEN_EQUAL
orGEN_GT
:
- 在读取操作期间,客户端应用程序还会读取记录的生成计数器的值。
- 客户端应用程序修改数据并获得记录上的写锁后,它会读取计数器的当前值。
- 出现以下情况之一:
- 如果生成策略设置为
GEN_EQUAL
:
- 如果当前值等于它之前读取的值,则客户端应用程序会将修改后的数据写入记录。
- 如果值不相等,则客户端应用程序不会执行写入操作。客户端应用程序可以重试读取-修改-写入操作的序列。
- 如果生成策略设置为
GEN_GT
:
- 如果当前值大于它之前读取的值,客户端应用程序会将修改后的数据写入记录。
- 如果当前值不大于,客户端应用程序不会执行写入操作。客户端应用程序可以重试读取-修改-写入操作的序列。
- 如果生成策略设置为
NONE
,则客户端应用在从记录中读取数据时不会读取计数器的值。在修改它读取的数据后,它将修改后的数据写入记录。 -
NONE
(默认)-客户端应用程序不使用记录生成计数器来限制写入。 -
EXPECT_GEN_EQUAL
—客户端应用程序更新或删除计数器的先前读取值等于当前值的记录。否则,写入操作会失败,客户端应用程序需要重试它们。 -
EXPECT_GEN_GT
—客户端应用程序更新或删除先前读取的计数器值小于当前值的记录。否则,写入操作会失败,客户端应用程序需要重试它们。当您想要从备份中恢复记录并且想要只写入您拥有旧版本的记录时,此值很有用。
- 数据的有效期(
WritePolicy.expiration
)或称为生存时间(ttl
):
- -2 —更新记录时不更改 ttl。
- -1 —永不过期。
- 0 -默认为服务器上的命名空间配置变量
default-ttl
。 - > 0 -以秒为单位的实际 ttl。
- 数据的持久删除(
WritePolicy.durableDelete
)
- 如果启用则在删除过后会留下标识,这可以防止节点故障后的问题。
四、安装Aerospike
- 在
Linux
上:
- 下载企业版
# https://download.aerospike.com
# /artifacts/aerospike-server-enterprise/<aerospike_version>/aerospike-server-enterprise-<aerospike_version>-<rhel_version>.tgz
wget -O aerospike.tgz https://download.aerospike.com/artifacts/aerospike-server-enterprise/5.7.0.17/aerospike-server-enterprise-5.7.0.17-el7.tgz
- 对于 Aerospike EE 4.5.x 或更早版本,请使用以下命令以及您的用户名和密码:
wget -O aerospike.tgz https://download.aerospike.com/artifacts/aerospike-server-enterprise/4.5.3.22/aerospike-server-enterprise-4.5.3.22-el7.tgz --user='userName' --password='passWord'
- 下载社区版
# https://download.aerospike.com
# /artifacts/aerospike-server-community/<aerospike_version>/aerospike-server-community-<aerospike_version>-<rhel_version>.tgz
wget -O aerospike.tgz https://download.aerospike.com/artifacts/aerospike-server-community/5.7.0.17/aerospike-server-community-5.7.0.17-el7.tgz
- 解压:
tar -xvf aerospike.tgz
- 安装:
cd aerospike-server-<community_or_enterprise-<aerospike_version>-<rhel_version>
sudo ./asinstall
- 配置:
- 安装会建立服务器的默认配置。默认情况下配置了内存中的测试命名空间。请参阅配置 Aerospike 数据库以修改和调整配置。
- 添加SSD
- 要添加SSD,请务必阅读有关 设置和 初始化的信息。
- 企业版需配置密钥:
- Aerospike EE 需要一个功能密钥文件 来启动并可选择启用门控功能,例如压缩。请参阅配置功能密钥文件。如果没有密钥在4.6.0以上版本无法启动,当然单节点的EE版本是可以的,Aerospike EE 评估 功能密钥
- 配置日志记录:
- 要为 Aerospike 数据库配置日志记录,请参阅配置 - 日志。
- 启动:
- Aerospike 包含的初始化脚本
/etc/init.d/aerospike
管理 Aerospike 数据库守护进程/usr/bin/asd
。 - 此外,Aerospike 数据库可以通过标准
systemctl
命令进行控制。有关详细信息,请参阅Aerospike systemd 守护进程管理。
systemctl start aerospike
systemctl stop aerospike
systemctl status aerospike
systemctl restart aerospike
- 如果在启动过程中出现错误,请参阅启动问题。知识库也是故障排除技巧的良好来源。
- 在
Docker
上:
- 企业版需要获得密钥文件
evaluation-features.conf
- 访问aerospike.com并单击主页右上角的立即尝试按钮。
- 填写表格的前四个字段。
- 在Select Trial字段中,选择Aerospike Enterprise Edition。
- 阅读许可协议和隐私政策后,单击开始我的免费试用。
- 检查您的收件箱中是否有来自“Aerospike 团队”的电子邮件。
- 在电子邮件中,单击“下载您的评估功能密钥文件”中的链接。
- 单击页面右上角的下载图标将文件保存
evaluation-features.conf
到您的系统。
- 创建一个目录,并把密钥文件放在里面
/opt/aerospike/etc
- 拉取镜像:
docker pull aerospike/aerospike-server-enterprise
- 创建容器:
docker run --rm -tid --name aerospike -p 3000:3000 -p 3001:3001 -p 3002:3002 \
-v <刚刚放密钥的文件路劲>:/aerospike/etc/ \
-e "FEATURE_KEY_FILE=/aerospike/etc/evaluation-features.conf" \
-e "NAMESPACE=<名称空间不写会默认创建一个>" aerospike/aerospike-server-enterprise
- 查看
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
c8456f7dd252 aerospike/aerospike-server-enterprise "/usr/bin/dumb-init …" 21 seconds ago Up 15 seconds 0.0.0.0:3000-3002->3000-3002/tcp aerospike
- 拉取
aerospike
工具
docker pull aerospike/aerospike-server-enterprise
- 创建容器:
docker run -it aerospike/aerospike-tools aql -h $(docker inspect -f '\{\{.NetworkSettings.IPAddress\}\}' aerospike)
- 尝试插入一条数据:
<name-of-namespace>
是您在docker run
启动数据库的命令中为命名空间指定的名称。<name-of-set>
是用于在命名空间内创建集合的名称。
insert into <name-of-namespace>.<name-of-set> (PK, test) values (123, 'test-value')
- 查看刚刚插入的数据:
select * from <name-of-namespace>.<name-of-set>
客户端地址:https://developer.aerospike.com/client/java/usage/kvs/write