【问题标题】:Using Aerospike to process data where uniqueness is defined by combination of keys使用 Aerospike 处理由键组合定义唯一性的数据
【发布时间】:2020-02-07 00:21:47
【问题描述】:

我正在尝试了解如何最好地构建我的 Aerospike 架构。当我在玩它时,我意识到问题的一部分是我没有完全理解 Aerospike 如何处理数据,这似乎与 RDBMS 和 Cassandra 不同。

我的数据集是一组记录,因此唯一的“主键”由多个字段的组合定义(如果我在 Aerospike 意义上误用了 primary key 一词,我深表歉意 - 最初我打算简单地连接这些带分隔符的字段)。我需要能够通过指定所有这些字段来检索单个记录并检索指定子集的批次。例如,假设我正在存储人口统计数据,其中我的“主键”是我从中获取数据的列 yearlocationsource 的组合。通过指定所有 3,我将获得准确的记录,如果我指定 2 或仅指定 1,我将获得一组记录。

在 RDBMS 中,我会使用索引来实现这一点。在 Cassandra 中,最好的方法是将所有 3 个添加到主键中,如果在执行搜索时不能保证分区键可用,则在物化视图中重新排列它们的顺序。

随着我越来越多地使用 Aerospike,我意识到这里的 PK 不会像上述两种情况中的任何一种那样对待。此外,我开始认为 Aerospike PK 可能根本不应该成为用户数据的一部分,因为默认情况下它们不会返回(除非在写入之前设置了 sendKeys,在这种情况下它们只是复制到垃圾箱中)。

从阅读文档中听起来,我真正想要的可能是secondary indexes(因为它们允许更灵活地查询数据)?索引在这里是正确的方法还是不鼓励使用,就像在 Cassandra 中一样?尝试将 Aerospike 概念与其他 DB 进行比较时,我可能会感到困惑。

【问题讨论】:

    标签: aerospike


    【解决方案1】:

    很好的问题 - 需要一个详细的答案,但让我以牺牲整体准确性为代价保持概念简短。

    1 - 无论您选择什么,Aersopike 中的主键都是字符串/整数/字节 -> 由您的应用程序绑定到的客户端库散列为 20 个字节。这个 20 字节的散列是发送到服务器并被服务器用来处理您的记录数据的“密钥”。因此,您可以创建一个字符串键:“2020:san_jose:web”,与该键关联的任何数据都将作为记录存储在 Aerospike 中。您可以执行 sendKey 甚至将您的密钥作为另一个字符串 bin 存储在记录中。但是 Aerospike 用来跟踪您的记录的是“2020:san_jose:web”的 20 字节哈希。这种复合键不会隐式绑定到数据箱 - 而是您在应用程序中显式创建。如果您可以为您感兴趣的一组记录“生成”此字符串(在您的应用程序中),则此技术可用于读取一批记录,然后使用批量读取 API。但是您不能使用 bin 中的数据并告诉 Aerospike 为您“生成”此密钥,找到匹配的记录并返回它们。

    2 - 你可以使用二级索引吗?在 Aerospike 中,您最多可以构建 256 个 SI,但在给定的查询调用中只能使用一个。 (我不建议为 RAM 和其他操作考虑构建多个。)bin 数据的基数越高,您需要的 RAM 就越多。索引内置在进程 RAM 中 - 它有其自身的操作含义 - 并将查询与散列键以及候选记录联系起来。因此,假设您在 city=="san_jose" 上使用 SI - 这将产生记录的子集。 (选择一个将数据剔除到总数的 15% 的 SI,理想情况下 - 建议。)现在,这将检索 city bin 与 san_jose 匹配的所有记录。这一切都在 RAM 中 - 所以速度很快。之后它将从磁盘读取所有这些记录并开始发送回客户端。

    3 - 在这个时刻,您有额外的机会来编写非常复杂的谓词过滤器。所以你可以说,在这个检索到的集合中,给我发送 year=2020 和 source=web 的记录......你需要的任何逻辑 AND OR NOT 条件、正则表达式等(我牺牲了准确性来驱动更大的点。你也可以在从磁盘获取记录之前,对在 RAM 级别发生的记录元数据运行 predex 过滤器。)

    4 - 最后,为什么不鼓励在分布式数据库中使用 SI?如果集群稳定,它们会很好地工作。如果节点进入或退出,数据将被迁移以创建副本副本 - SI 查询与迁移数据并行运行 - 您可能会错过或得到重复。将 SI 查询视为一个相对“长时间”运行的操作。在 Aerospike 中,如果您在启动 SI 查询之前确保数据没有迁移,则可以设置一个可选标志 - failOnClusterChange - 因此如果节点在活动期间退出或加入,您的查询将失败(通知客户端) SI 查询。根据您的数据模型,您可能关心也可能不关心 SI 查询的 100% 准确度。

    【讨论】:

    • 因此,如果我理解正确,那么 3 个字段中每个字段的复合主键 + 单独索引可能是可行的方法(并且自己编写 bin 而不是依赖 sendKeys)?这对 RAM 有多大影响?它是存储每个索引字段的副本(字符串)还是仅存储一个数字哈希来引用它?这是一个依赖 AWS 的副项目,所以我有点担心使用限制会导致成本飙升。
    • 如果你走 SI 模型路线,你应该计划只索引一个 bin。您不需要将其余部分作为 SI,因为您一次只能在查询中使用一个 SI。您不需要 sendKey 或将密钥存储在单独的 bin 中。这与你正在做的事情无关。如果您的数据模型需要批量读取,复合键很有用,并且您可以根据应用程序中的组合模式组合所需的键数组,发送此键数组以进行批量读取。这是最可靠的选择。所以 SI 与复合键 - 取决于您在应用程序中尝试执行的操作。
    • 谓词表达式可以在有或没有 SI 的情况下使用。由于服务器在向客户端发送数据之前从磁盘获取记录以应用 PredEx,因此减少服务器必须首先使用 SI 获取的候选记录集有助于提高效率。
    • 那么您的意思是,只要我从索引字段驱动查询,Aerospike 仍然可以按未索引字段过滤?此外,谓词表达式与查询的“where”子句相同还是其他?
    【解决方案2】:

    此代码示例可能有助于理解。即使我没有在“国家”上使用二级索引,这也会起作用,但效率会降低 - 即它会提取该命名空间/集合中的每条记录并应用 PredEx。

    public void read () {
                    Record record = null;
                    Statement stmt = new Statement();
                    stmt.setSetName("testset");
                    stmt.setNamespace("test");
                    stmt.setIndexName("country_idx");
                    stmt.setFilter(Filter.equal("country","USA")); 
                    stmt.setPredExp(
                            PredExp.stringBin("city"),
                            PredExp.stringValue(".*Diego"),  //prefix-suffix match: prefix.*suffix, ignore case or newline
                            PredExp.stringRegex(RegexFlag.ICASE | RegexFlag.NEWLINE)
                    );
    
                    RecordSet recordSet = this.client.query(queryPolicy, stmt);
                while (recordSet.next()) {
                    record = recordSet.getRecord();
                    System.out.println(record.toString());
                }
    
             }
    

    顺便说一句,客户端库是开源的,并且包含所有 API 的示例。对于java,见:https://github.com/aerospike/aerospike-client-java/tree/master/examples

    【讨论】:

    • 当然,如果您仍然希望国家是美国而不使用 SI,则必须在 setPredExp() 中添加该条件。您将为国家创建一个条件,为城市创建第二个条件,然后然后是其中 (2) 个的 AND 条件。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-03-12
    • 1970-01-01
    • 1970-01-01
    • 2022-01-25
    • 2020-02-02
    • 2012-08-20
    相关资源
    最近更新 更多