Aerospike - 存储*少量*大值

Aerospike - Store *small quantity* of large values

场景
假设我要为每个用户存储最多 5 个字节数组,每个 50kB。

可能的实现:

1) 每条记录一个字节数组,由辅助键索引。
优点:快速 read/write.
缺点:高基数查询(每个查询最多 5 个结果)。如果频繁访问字节数组,则不利于水平缩放。

2) 单独 bin 中单个记录中的所有字节数组
优点:快速阅读
中性:块大小必须大于 250kB
缺点:写入速度慢(一次更改意味着重写所有字节数组)。

3) 将字节数组存储在 LLIST LDT
优点:避免解决方案 (1) 和 (2)
的缺点 缺点:LDT 通常很慢

4) 将每个字节数组存储在单独的记录中,键入一个 UUID。将 UUID 列表存储在另一条记录中。
优点:写入每个字节数组不需要重写所有数组。二级索引没有低基数问题。避免使用 LDT。
缺点:客户端读取是两阶段的:从元记录中获取 UUID 列表,然后对每个 UUID 进行多次获取(很慢?)

5) 将每个字节数组存储为单独的记录,使用预先确定的主键方案(例如userid_index,例如123_0,123_1, 123_2、123_3、123_4) 优点:避免两阶段读取 缺点:理论上 与另一个用户的冲突可能性(例如 user1_index1 和 user2_index2 产品相同的哈希值)。我知道这是(非常非常)低的概率,但仍然首选避免(想象一个用户由于冲突能够读取另一个用户的字节数组)。

我的评价
对于平衡 read/write 或高 read/low 写入情况,请使用 #2(一个记录,多个 bin)。重写成本更高,但避免了其他缺点(LDT 惩罚、2 阶段读取)。

对于高 (re)write/low 读取情况,请使用 #3 (LDT)。这避免了在更新其中一个字节数组时必须重写所有字节数组,因为记录是写时复制的。

问题
考虑到当前的数据模式(少量,大对象),哪种实现更可取?你同意我的评价(以上)吗?

这是一些输入。 (我想透露一下,我确实在 Aerospike 工作)。

请避免#3。不要使用 LDT,因为该功能肯定不如平台的其余部分成熟,尤其是在节点 leave/join 一个集群的集群重新平衡(迁移)情况下的性能/可靠性方面。

我会尽量坚持基本的 Key/Value 交易。这应该始终是最快和最具可扩展性的。正如您所指出的,选项 #1 不会扩展。二级索引也有内存开销,目前不允许快速启动(无论如何仅限企业版)。

对于高写入负载,您在#2 上也是正确的,尤其是如果您要始终更新 1 个 bin...

因此,剩下选项 #4 和 #5。对于选项#5,碰撞实际上不会发生。你可以复习一下数学,它根本不会发生。如果是这样,您将成名并可以发表论文 :)(甚至可能会因为发现碰撞而付出代价)。另外,请注意,您可以选择将密钥存储在记录中,这将为您提供 'key check' 的写入,这应该非常便宜(因为记录在写入之前无论如何都会被读取)。选项 #4 也可以,它只会进行额外的读取(应该非常快)。

这完全取决于你想要额外复杂的地方。因此,如果您在决定之前有足够的条件,可以在这两个选项之间做一些简单的基准测试。