我试图找出在分布式(更准确地说是faas)环境中处理文档的有效算法。
蛮力法是o(dfr),其中:
d是要处理的文档数量
f是过滤器的数量
r是单个过滤器中的最大规则数
我可以假设:
单个筛选器的规则不超过10个
一些过滤器可能共享规则(因此是n对n关系)
规则是布尔函数( predicate ),所以我可以尝试利用早期切割,这意味着如果我有f()&&g()&&h(),f()的求值为false,那么我根本不需要处理g()和h(),可以立即返回false。
在单个文档中,字段的数量总是相同的(大约5-10个)
筛选器、规则和文档已在数据库中
每个筛选器至少有一个规则
使用共享(第二个假设)我有一个想法,首先根据每个规则处理文档,然后(完成后)使用已经计算的规则计算每个过滤器的结果。这样,如果规则是共享的,那么我只计算一次。但是,它没有利用早期切割(第三种假设)。
第二个想法是使用早期切割作为稍微优化的bruteforce,但不会使用规则共享。
规则共享看起来像子问题共享,所以记忆化和动态规划可能会有所帮助。
我注意到,过滤规则关系是二部图。不太确定它是否能帮到我。我还注意到,我可以使用反向集,并在每个规则存储相应的集。但是,这将创建循环依赖,并可能导致数据库中的不同步问题。
默认的想法是文档是流式的,每个文档都是创建faas示例来处理它的事件。然而,这可能会迫使每个faas示例查询所有过滤器,这使得我只能进行o(f*d)查询,因为没有共享架构。
样品过滤器:
{
'normalForm': 'CONJUNCTIVE',
'rules':
[
{
'isNegated': true,
'field': 'X',
'relation': 'STARTS_WITH',
'value': 'G',
},
{
'isNegated': false,
'field': 'Y',
'relation': 'CONTAINS',
'value': 'KEY',
},
}
或者以更浓缩的形式:
document -> !document.x.startsWith("G") && document.y.contains("KEY")
对于文档:
{
'x': 'CAR',
'y': 'KEYBOARD',
'z': 'PAPER',
}
计算结果为true。
我可以稍微更改数据模型,流化其他内容而不是文档(例如过滤器),并使用任何nosql数据库和工具来帮助它。apache flink(事件处理)和mongodb(使用规则检索过滤器的单个查询)或者neo4j(模型看起来像二部图)看起来可以帮助我,但不确定。
它能被有效地处理吗(关于-可能-数据库查询)?什么工具是合适的?
我也一直在想,也许我是想解决一些更一般(数学)问题的特殊情况,可能有有用的定理和算法。
编辑:我的最新想法:像redis一样在缓存中收集所有文档。然后,单个事件启动并发布n个函数(就像在function as a service中一样),每个函数选择f/n(过滤器数量除以示例数量-所以在示例之间均匀分布过滤器),这样每个过滤器只从数据库中提取一次。
现在,每个示例都从缓存中流式传输所有文档(一个文档应该小于1mb,同时我应该有1-10k个文档,所以应该适合缓存)。这样,每个文档只从数据库中选择一次(缓存)。
我已经减少了数据库读取操作(仍然有一些规则被多次选择),但是我仍然没有利用过滤器之间的规则共享。我可以通过使用文档数据库故意忽略它。这样通过选择过滤器我也会得到它的规则。但我还是要重新计算它的价值。
我想这就是我使用shared-nothing可伸缩架构得到的?
1条答案
按热度按时间siv3szwd1#
我意识到虽然我的图确实(理论上)是二部的,但是(实际上)它将是一组不相交的二部图(因为不是所有的规则都是共享的)。这意味着,我可以在不同的faas示例上独立地处理那些不相交的部分,而无需重新计算相同的规则。
这将我的问题简化为处理单二部连通图。现在,我可以使用动态规划的优点,并且只有在共享内存的情况下才能共享规则计算的结果,所以我不能在不牺牲这个优点的情况下进一步划分(和分配)这个问题。所以我这样想:如果我已经决定,我将不得不重新计算一些规则,然后让它比我将得到的不相交部分低。
这实际上是最小割问题(幸运的是)多项式复杂度已知的算法。
然而,在我的例子中,这可能并不理想,因为我不想切割图的任何部分-我希望将图理想地切割成两半(分而治之策略,可以递归地重新应用,直到图非常小,在faas示例中可以在几秒钟内处理,这是有时间限制的)。
这意味着,我正在寻找切割,这将创建两个不相交的二部图,每个图可能有相同数量的顶点(或至少相似)。
这是一个最稀疏的割问题,即np难问题,但有o(sqrt(logn))近似算法,也有利于较少的割边。
目前,这看起来像是解决我的问题,但我很乐意听到任何建议,改进和其他答案。
也许用其他数据模型或算法可以做得更好?也许我可以用一些定理进一步简化它?也许我可以把它转换成另一个(更简单的)问题,或者至少这更容易在节点间划分和分布?
这种想法和分析强烈建议使用图形数据库。