我正在寻找有关我的要求的一些建议。以下是我的要求说明。如有任何疑问,请随时与我联系。甚至一些关于如何更清楚地描述我的问题的建议也非常感激:)
需求说明
我有一些数据,格式如下:
router, interface,timestamp, src_ip, dst_ip, src_port, dst_port, protocol, bits
r1, 1, 1453016443, 10.0.0.1, 10.0.0.2, 100, 200, tcp, 108
r2, 1, 1453016448, 10.0.0.3, 10.0.0.8, 200, 200, udp, 100
如您所见,它是一些网络原始数据。我省略了一些列只是为了让它看起来更清晰。数据量非常大。它产生的速度非常快,每5分钟产生10亿行...
我想要的是对这些数据进行实时分析。 例如:
使用时间戳
绘制一条线选择sum(bits),来自raw_data group by router的时间戳,interface = interface = 1,router = r1。
找出哪个3 src_ip为一个界面发送最多数据
从raw_data中选择sum(bits),其中router = r1,interface = 2 group by src_ip order by sum(bits)desc limit 3
我已经尝试了一些解决方案,但每个解决方案都不适合它。例如:
- 数据太大
- 我的专栏比我在这里描述的要多得多。为了提高我的查询速度,我必须对大多数列进行索引。但我认为在大表上创建索引并且包含太多列的索引不是很好,对吧?
醇>
OpenTSDB是一个很好的时间序列数据库。但也不适合我的要求。
openTSDB有解决TOP N问题的问题。在我的要求“获得发送大多数数据的前3个src_ip”中,openTSDB无法解决这个问题。
我知道apache spark可以像RDBMS一样使用。它具有名为spark SQL的功能。我没试过,但我猜性能不应该满足实时分析/查询要求,对吧?毕竟,spark更适合离线计算,对吗?
当我知道这个项目时,我真的非常希望ES。但它也不合适。因为聚合多个列时,必须在elasticsearch中使用所谓的嵌套桶聚合。并且无法对此聚合的结果进行排序。您必须检索所有结果并按自己排序。就我而言,结果太多了。对结果进行排序将非常困难
所以....我被困在这里。请问有人可以提出一些建议吗?
答案 0 :(得分:1)
我不明白为什么ES无法满足您的要求。我想你误解了这一部分
但它也不合适。因为聚合多个列时,必须在elasticsearch中使用所谓的嵌套桶聚合。并且无法对此聚合的结果进行排序。
您的第一个要求使用时间戳绘制一条线可以通过这样的查询/聚合轻松实现:
{
"query": {
"bool": {
"must": [
{
"term": {
"interface": 1
}
},
{
"term": {
"router": "r1"
}
}
]
}
},
"aggs": {
"by_minute": {
"date_histogram": {
"field": "timestamp",
"interval": "1m"
},
"aggs": {
"sum_bits": {
"sum": {
"field": "bits"
}
}
}
}
}
}
至于你的第二个要求找出哪个3 src_ip为一个接口发送最多的数据,它也可以通过像这样的查询/聚合轻松实现:
{
"query": {
"bool": {
"must": [
{
"term": {
"interface": 2
}
},
{
"term": {
"router": "r1"
}
}
]
}
},
"aggs": {
"by_src_ip": {
"terms": {
"field": "src_ip",
"size": 3,
"order": {
"sum_bits": "desc"
}
},
"aggs": {
"sum_bits": {
"sum": {
"field": "bits"
}
}
}
}
}
}
更新
根据您的评论,您上面的第二个要求可能会更改为找到src_ip / dst_ip的前3个组合。使用terms
代替script
聚合,而不是构建src / dest组合并为每对夫妇提供位总和的术语,这是可行的,如下所示:
{
"query": {
"bool": {
"must": [
{
"term": {
"interface": 2
}
},
{
"term": {
"router": "r1"
}
}
]
}
},
"aggs": {
"by_src_ip": {
"terms": {
"script": "[doc.src_ip.value, doc.dst_ip.value].join('-')",
"size": 3,
"order": {
"sum_bits": "desc"
}
},
"aggs": {
"sum_bits": {
"sum": {
"field": "bits"
}
}
}
}
}
}
请注意,要运行此最后一个查询,您需要enable dynamic scripting。此外,由于您将拥有数十亿份文档,脚本编写可能不是最佳解决方案,但在进一步深入探讨之前值得尝试一下。另一种可能的解决方案是在索引时添加combination
字段(src_ip-dst_ip
),以便您可以将其用作术语聚合中的字段,而无需使用脚本。
答案 1 :(得分:1)
您可以尝试Axibase Time Series Database这是非关系型的,但除了类似rest的API之外还支持SQL查询。这是一个前N个查询示例:
SELECT entity, avg(value) FROM cpu_busy
WHERE time between now - 1 * hour and now
GROUP BY entity
ORDER BY avg(value) DESC
LIMIT 3
https://axibase.com/docs/atsd/sql/#grouping
ATSD社区版是免费的。
披露:我为Axibase工作