文章目录
最近在Elastic官网blog的这篇文章引起了许多人的注意——Investigative analysis of disjointed data in Elasticsearch with the Siren Platform (利用Siren平台对Elasticsearch中的非联接(disjointed)数据进行调查分析)
这里的亮点莫过于文章里面提到的对于disjointed
数据的调查分析。
用户对于es join的热切需求
其实对于很多国内的资深的ES玩家来说,Elasticsearch是真真正正的被玩出了花样:
无论是互联网企业还是各种金融机构,都会把Elasticsearch用在BI分析、多维分析、大数据流处理等等国外ES玩家较少涉足的场景。通过结合Elasticsearch本身首屈一指的全文检索和模糊查询能力、结构化和非结构化数据的处理能力,灵活的字段组合查询能力、以及丰富的数据聚合功能、再加上大数据和高并发的支持,使得Elasticsearch在大数据多维分析,OLAP等场景应用越来越广泛。
但这里,当我们把Elasticsearch作为一个数据仓库或者一个数据湖去使用的时候,不同数据源的join关联分析,往往会是我们使用Elasticsearch时候的一大痛点。
基于Elasticsearch分布式集群的特性,其实是很难做到一个高效且可扩展的分布式join操作的,所以现在Elasticsearch只支持join type
和 nested type
两种有限的join场景,并且这两种join的效率都不是特别高(nested type
查询性能比标准查询的慢5~10倍, join type
则是慢了10 ~ 100倍,参见tune-for-search-speed),甚至对于join type
还存在限制parent和child必须在一个分片上面的限制。
因此,通常情况下,我们得到的建议都是做数据的denormalize(反规范化),做一张大宽表,把所有的字段都放置在一张’表’里面,以获得对查询和聚合的性能。但其实这种大宽表带来的问题也是明显的,当我们要更新某个字段值时,需要重新索引整个文档,其带来的痛点包括:
- 当这个文档很大时,更新字段值带来的reindex代价较高
- 当这个字段的值,是大多数文档都一样的common值时,一个值的修改可能会涉及到整个索引中大部分的数据,比如,资产名的更改,发行商名的变化等
- 当这个字段需要频繁变动的时候,整个文档reindex代价非常高
因此,很多用户还是非常希望Elasticsearch有一个更好的实现数据联合分析的能力的,包括:
- Elasticsearch内部的多索引之间的关联分析
- Elasticsearch和外部数据源的关联分析
但可惜的是,这里没有银弹,在分布式系统的前提下,我们还是需要在不同的场景中,权衡性能、存储成本、数据更新成本之间的关系,选择一个局部最优解来作为解决方案。
Siren Federate 插件带来的扩展能力
基于上面的原因,也难怪大家会对这个Siren Federate 插件比较感兴趣了。大家可以查看Siren Federate的官网简单了解。
他们是这样描述的:
Siren Federate插件通过以下主要功能扩展了Elasticsearch:
-
联合层,可对外部数据库进行虚拟化和查询。
-
反射层,用于缓存来自Elasticsearch内外部数据库的数据。
-
分布式联接层(distributed join layer),可跨索引和外部数据库大规模执行联接(join)操作。
-
基于正在申请专利的技术的联接缓存层,可以缓存最常见的联接结果,从而缩短执行时间。
这里面,我觉得大家最感兴趣的应该是两点:
- 反射层,用于缓存来自Elasticsearch内外部数据库的数据
- 分布式联接层(distributed join layer),可跨索引和外部数据库大规模执行联接(join)操作。
在这篇文章里面,我们带大家初探 Siren Federate
Siren Federate的安装
安装相对简单,和普通的插件安装是一样的。从官网下载对应版本的安装包,使用elasticsearch-plugin
进行安装
$ ./bin/elasticsearch-plugin install file:///PATH-TO-SIREN-FEDERATE-PLUGIN/siren-federate-7.9.3-21.2-proguard-plugin.zip
-> Downloading file:///PATH-TO-SIREN-FEDERATE-PLUGIN/siren-federate-7.9.3-21.2-proguard-plugin.zip
[=================================================] 100%
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ WARNING: plugin requires additional permissions @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
* java.io.FilePermission cloudera.properties read
* java.io.FilePermission simba.properties read
* java.lang.RuntimePermission accessClassInPackage.sun.misc
* java.lang.RuntimePermission accessClassInPackage.sun.misc.*
* java.lang.RuntimePermission accessClassInPackage.sun.security.provider
* java.lang.RuntimePermission accessDeclaredMembers
* java.lang.RuntimePermission createClassLoader
* java.lang.RuntimePermission getClassLoader
...
See http://docs.oracle.com/javase/8/docs/technotes/guides/security/permissions.html
for descriptions of what these permissions allow and the associated risks.
Continue with installation? [y/N]y
-> Installed siren-federate
重新启动ES,可看到如下的日志,表明Siren Federate加载成功
[2017-04-11T10:42:02,209][INFO ][o.e.p.PluginsService ] [etZuTTn] loaded plugin [siren-federate]
也可以通过调用siren/<index>/_search
相关接口,确认
外部数据源的虚拟映射
这个是比较有意思的功能,我们还是先来看官方关于该功能的描述:
Siren Federate提供了一个名为
connector
的模块,该模块透明地将数据表从外部数据库系统映射到Elasticsearch中的“虚拟索引”。该connector
的API允许你把外部数据库系统注册为数据源。目前支持两种类型的数据源:JDBC和Elasticsearch。注册数据源后,可以将外部数据库系统中的表映射到虚拟索引。使用Elasticsearch API将请求发送到虚拟索引时,例如Mapping或Search API,该请求被connector
模块拦截。该请求将转换为外部数据库方言,并针对外部数据库执行。外部数据库的结果将映射到Elasticsearch方言,并作为Elasticsearch响应返回。
这里的实际意义在于,如果能在ES里面直接将外部的数据表映射为虚拟索引,我们就可以实现跨数据源的分析。
支持的外部数据源
目前Siren Federate支持的外部数据源如下:
Name | JDBC class |
---|---|
PostgreSQL | org.postgresql.Driver |
MySQL | com.mysql.jdbc.Driver |
Oracle 12c+ | oracle.jdbc.OracleDriver |
Spark SQL 2.2+ | com.simba.spark.jdbc41.Driver |
Neo4j | org.neo4j.jdbc.http.HttpDriver |
MySQL测试
接下来,我们添加一个MySQL数据源试试。首先,我们要通过API创建一个MySQL数据源。
创建远程数据源步骤
要配置JDBC数据源,需要完成以下步骤:
- 打开
elasticsearch.yml
文件并添加以下设置:
node.attr.connector.jdbc:true
- 在节点的配置目录中创建一个名为jdbc-drivers的目录,例如,在
elasticsearch/config/
或/etc/elasticsearch/
中创建该目录。这里最好是按照每个数据库再创建一个子目录 - 将远程数据源的JDBC驱动程序及其依赖项复制到JDBC -drivers目录中。 Supported JDBC drivers
├── jdbc-drivers
│ ├── mysql
│ │ └── mysql-connector-java-8.0.21.jar
│ └── pg
│ └── postgresql-42.2.18.jar
- 重启Elasticsearch服务
创建远程数据源对象
通过Connector
相关的API进行相关数据源对象的创建,分别是Datasource API
和Virtual index API
。
首先使用Datasource API
来创建数据源对象,_siren/connector/datasource/<id>
:
PUT _siren/connector/datasource/mysql
{
"jdbc": {
"username": "root",
"password": "changeme",
"driver": "com.mysql.jdbc.Driver",
"url": "jdbc:mysql://cdb-bibxdjok.cd.tencentcdb.com:10130/dev?useLegacyDatetimeCode=false",
"properties": {
"ssl": true
}
}
}
注意这里需要填入的参数,特别是driver
和url
。我们可以通过GET _siren/connector/datasource
来查看输入规范:
{
"Dremio" : {
"driverClassName" : "com.dremio.jdbc.Driver",
"defaultURL" : "jdbc:dremio:direct={
{host}}:{
{port}}{
{databasename}}",
"defaultPort" : 31010,
"validationQuery" : "SELECT 1 AS N",
"disclaimer" : ""