1 はじめに
Apache Atlas は、Apache がホストするメタデータ管理およびガバナンス製品です。現在、ビッグ データの分野で広く使用されています。企業がデータ資産を管理し、これらの資産を分類および管理し、データ分析の基盤を提供するのに役立ちます。、データ ガバナンス高品質のメタデータ情報を提供します。
企業の業務量が徐々に拡大するにつれて、データは日々増加します。さまざまな事業分野からのデータが複数の種類のデータベースに保存され、最終的には統合分析のために企業のデータ ウェアハウスに収集されることがあります。データの出所を追跡するのは当然ですが、データ間の関係性を明らかにするのは非常に面倒で、あるリンクに問題があれば追跡コストが膨大になるため、このような背景でAtlasが誕生しました。これにより、メタデータの管理が非常に便利になり、テーブル レベルと列レベルの間の関係 (血縁関係) を追跡することができ、企業のデータ資産に強力なサポートと保証を提供します。 Atlas は、HBase、Hive、Sqoop、Storm、Kafka からのメタデータの抽出と管理をサポートしています。同時に、独自のメタデータ モデルを定義し、Rest API を通じてメタデータを生成することもできます。
この記事では、誰もが Atlas をよりよく理解できるように、Atlas の関連概念を紹介することに重点を置き、同時に、独自のパーソナライズされたニーズを開発するために、Rest API を通じてデータ モデルをカスタマイズし、血縁関係を生成する方法について詳しく説明します。
2. アトラスの原則と関連概念
メタデータ
メタデータは、実際には、テーブル、フィールド、ビューなどのデータを説明するデータです。各ビジネス システムは、独自のテーブル、フィールド、ビュー、データの送信元と送信先、データ間に相関関係があるかどうか、などを定義できます。システム データに重複フィールドや矛盾するフィールドがあるかどうか、これらはメタデータ管理が解決する必要がある問題であり、Atlas が解決する必要がある問題でもあります。
動作原理
Atlas の原理を理解するのはそれほど難しくありません。主に、内部で提供されるスクリプトを通じてデータ ウェアハウス内のデータベース構造を読み取り、データ モデルを生成し、Atlas の Hbase に保存します。同時に、データ内のデータの変更を監視します。実行された SQL ステートメントは、テーブル間および列間の依存関係を生成し、フロント デスクのユーザーに表示されます。
データウェアハウスのサポート
Atlas は Hive に対して最高のサポートを備えています。Hive が Hadoop に依存しており、データが HDFS に保存されていることは誰もが知っています。Atlas には、Hive のテーブル構造などのメタデータ情報を直接実行して読み取り、Atlas リポジトリに同期できる特別なシェル スクリプトがあります。 . はメタデータモデルを自動生成し、Atlas が提供する HiveHook は Hive データの変化を監視したり、Hive が実行する SQL に基づいてデータ間の関係を推測したり、血縁関係図を生成したりすることができます。ストレージ メディア データと親族関係、Atlas のサポートは理想的ではありません。ただし、通常、MySQL や Oracle などのビジネス ライブラリからデータ ウェアハウスにデータを定期的に同期して統合や分析を行います。データ ウェアハウスでは通常、Hadoop エコシステムを使用するため、これは問題になりません。
アーキテクチャ図
以下は Atlas のアーキテクチャ図です。Atlas が依存するエコシステムは非常に大規模であることがわかり、そのことが直接その展開を非常に面倒にしています。この記事では Atlas の展開については説明しません。インターネット上には関連するチュートリアルが多数あります。興味があれば、友達が自分で検索して試してみることもできます。
コアコンポーネントの概念
Atlas には主に次のコア コンポーネントがあり、これらに注目する必要があります。次に、Rest Api によるカスタム モデリングは、実際には次のコンポーネントの追加、削除、確認、変更の操作です。
1. タイプ
データベース、テーブル、列などのメタデータ タイプ定義は、mysql テーブル (mysql_table)、oracle テーブル (oracle_table) などに再分割することもできます。Atlas には、DataSet、Process など、多くのタイプが付属しています。通常の場合、データ関連型は型定義時に DataSet を継承し、プロセス関連型は Process を継承するため、血縁関係の生成が容易になります。 API を呼び出してタイプをカスタマイズすることもできます。これがすべての出発点です。タイプが定義された後、さまざまなタイプのメタデータ エンティティを生成して血縁関係を生成できます。私は個人的にメタデータ タイプ モデリングと呼ぶことを好みます。
2. 分類
平たく言えば、分類とは、メタデータにラベルを付けることを意味します。分類は転送可能です。たとえば、ビュー A はテーブル A に基づいて生成されるため、テーブル A に a のタグが付けられている場合、ビュー A にも自動的に a のタグが付けられます。これの利点は次のとおりです。データ追跡を容易にします。
3. エンティティ
エンティティは特定のメタデータを表し、Atlas によって管理されるオブジェクトはさまざまなタイプのエンティティです。
4. 血統
データリネージはデータ間の伝達関係を表すもので、データがどこから来てどこに流れ、途中でどのような操作が行われたのかを明確に知ることができるため、データに問題が発生した場合には、すぐに遡って、問題が発生したリンクを見つけることができます。
3. Altasのインストール
(参照リンク。実際の状況に応じて使用してください)
1. https://blog.csdn.net/hshudoudou/article/details/123899947
2. https://blog.csdn.net/javaThanksgiving/article/details/130505251
4. アルタスの利用
Altas が正常に展開された後は、使い方は非常に簡単です。これがログイン インターフェースです。デフォルトのユーザー名とパスワードは admin、admin です:
ホームページに入り、[切り替え] をクリックします。右上隅にある [new] をクリックして使用します。 新しいインターフェイスはより直感的です:
ページの左側には、Atlas タイプ ツリーがあります。ツリー ノードのタイプをクリックすると、次のエンティティが表示されます。ここで、mysql_table をクリックします:
以下に多数のテーブルがあることがわかります。これらのテーブルは、以前に Rest Api を使用してアップロードして定義しました。
Rest Api を介してタイプをカスタマイズし、エンティティを生成し、血縁関係を作成する方法を説明しましょう。
5. Atlas Rest APIの詳しい説明と例
ホームページの上部にある [ヘルプ] > [API ドキュメント] をクリックして、Atlas のオープン インターフェイスをすべて表示します。
注意する必要があるのは、Atlas のインターフェイスです。使用するときは認証が必要です。そうです、http リクエストを構築するときにユーザー名とパスワードの認証情報を取得する必要があります。この例では、atlas-client-v2 オープン ソース コンポーネントを使用して Atlas API 呼び出しを行います。
この例では、my_db タイプ、my_table タイプを定義し、my_db を 1 対多の my_table にします。次に、my_db の下に test_db エンティティを作成し、my_table の下に test_table_source および test_table_target エンティティを作成し、test_table_source から取得されるように test_table_target のデータを定義します。 、 2 つのエンティティを生成する 血縁関係の依存。
my_db および my_table タイプをカスタマイズする
my_db タイプと my_table タイプを定義します。Atlas の Rest API では、1 つのリクエストで複数のタイプを定義できます。ここでは、まず json リクエスト本体を構築し、コーディングを通じて実装します。この 2 つを比較すると、json リクエストの方が理解しやすいです。本文は次のとおりです (重要な場所にメモが記載されています)。
{
"enumDefs": [],
"structDefs": [],
"classificationDefs": [],
//类型定义
"entityDefs": [
{
"name": "my_db",
//数据类型的定义,约定俗成,继承Atlas自带的DataSet
"superTypes": [
"DataSet"
],
//服务类型(便于在界面分组显示类型)
"serviceType": "my_type",
"typeVersion": "1.1",
"attributeDefs": []
},
{
"name": "my_table",
"superTypes": [
"DataSet"
],
"serviceType": "my_type",
"typeVersion": "1.1",
"attributeDefs": []
}
],
//定义类型之间的关系
"relationshipDefs": [
{
"name": "my_table_db",
"serviceType": "my_type",
"typeVersion": "1.1",
//关系类型:ASSOCIATION:关联关系,没有容器存在,1对1
//AGGREGATION:容器关系,1对多,而且彼此可以相互独立存在
//COMPOSITION:容器关系,1对多,但是容器中的实例不能脱离容器存在
"relationshipCategory": "AGGREGATION",
//节点一
"endDef1": {
"type": "my_table",
//表中关联的属性名称,对应下面的 my_db
"name": "db",
//代表这头是不是容器
"isContainer": false,
//cardinality: 三种类型SINGLE, LIST, SET
"cardinality": "SINGLE"
},
// 节点2
"endDef2": {
"type": "my_db",
"name": "tables",
"isContainer": true,
// db 包含 table,table不能重复,所以类型设置为 SET
"cardinality": "SET"
},
// 推导tag NONE 不推导
"propagateTags": "NONE"
}
]
}
コーディング実装:
pom 依存関係を導入します。独自のビジネス システムに統合する場合、ビジネス システムが他のログ フレームワークを使用している場合は、slf4j-log4j12 依存関係を削除する必要があることに注意してください。そうしないと、ログ フレームワークが競合し、起動エラーが発生します。さらに、atlas-client- Common は commons-configuration 1.10 に依存しています。ビジネス システムに下位バージョンの依存関係がある場合は、忘れずにそれらを除外してください。そうしないと、2 つが競合し、クライアントの初期化が失敗します。
<dependencies>
<!-- Apache Atlas -->
<dependency>
<groupId>org.apache.atlas</groupId>
<artifactId>atlas-client-common</artifactId>
<version>2.1.0</version>
<exclusions>
<exclusion>
<artifactId>slf4j-log4j12</artifactId>
<groupId>org.slf4j</groupId>
</exclusion>
</exclusions>
</dependency>
<!-- Apache Atlas Client Version2 -->
<dependency>
<groupId>org.apache.atlas</groupId>
<artifactId>atlas-client-v2</artifactId>
<version>2.1.0</version>
<exclusions>
<exclusion>
<artifactId>slf4j-log4j12</artifactId>
<groupId>org.slf4j</groupId>
</exclusion>
<exclusion>
<artifactId>log4j</artifactId>
<groupId>log4j</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>${fastjson.version}</version>
</dependency>
</dependencies>
atlas-application.properties を導入します (存在する必要があります。存在しないと初期化が失敗します)。
atlas.rest.address=http://127.0.0.1:21000
コードは次のように実装されます (json に比べて非常に理解しやすい)。
AtlasClientV2 atlasClientV2 = new AtlasClientV2(new String[]{
"http://127.0.0.1:21000"}, new String[]{
"admin", "admin"});
//父类集合
Set<String> superTypes = new HashSet<>();
superTypes.add(AtlasBaseTypeDef.ATLAS_TYPE_DATASET);
//定义myType
AtlasTypesDef myType = new AtlasTypesDef();
//定义myDb
AtlasEntityDef myDb = new AtlasEntityDef();
myDb.setName("my_db");
myDb.setServiceType("my_type");
myDb.setSuperTypes(superTypes);
myDb.setTypeVersion("1.1");
//定义mytable
AtlasEntityDef myTable = new AtlasEntityDef();
myTable.setName("my_table");
myTable.setServiceType("my_type");
myTable.setSuperTypes(superTypes);
myTable.setTypeVersion("1.1");
//定义relationshipDef
AtlasRelationshipDef relationshipDef = new AtlasRelationshipDef();
relationshipDef.setName("my_table_db");
relationshipDef.setServiceType("my_type");
relationshipDef.setTypeVersion("1.1");
relationshipDef.setRelationshipCategory(AtlasRelationshipDef.RelationshipCategory.AGGREGATION);
relationshipDef.setPropagateTags(AtlasRelationshipDef.PropagateTags.NONE);
//定义endDef1
AtlasRelationshipEndDef endDef1 = new AtlasRelationshipEndDef();
endDef1.setType("my_table");
endDef1.setName("db");
endDef1.setIsContainer(false);
endDef1.setCardinality(AtlasStructDef.AtlasAttributeDef.Cardinality.SINGLE);
relationshipDef.setEndDef1(endDef1);
//定义endDef2
AtlasRelationshipEndDef endDef2 = new AtlasRelationshipEndDef();
endDef2.setType("my_db");
endDef2.setName("tables");
endDef2.setIsContainer(true);
endDef2.setCardinality(AtlasStructDef.AtlasAttributeDef.Cardinality.SET);
relationshipDef.setEndDef2(endDef2);
//entityDefs
List<AtlasEntityDef> entityDefs = new ArrayList<>(2);
entityDefs.add(myDb);
entityDefs.add(myTable);
myType.setEntityDefs(entityDefs);
//relationshipDefs
List<AtlasRelationshipDef> relationshipDefs = new ArrayList<>(1);
relationshipDefs.add(relationshipDef);
myType.setRelationshipDefs(relationshipDefs);
//查询是否已有my_db类型,没有则创建
SearchFilter filter = new SearchFilter();
filter.setParam("name", "my_db");
AtlasTypesDef allTypeDefs = atlasClientV2.getAllTypeDefs(filter);
if (allTypeDefs.getEntityDefs().isEmpty()) {
//请求 rest api
atlasClientV2.createAtlasTypeDefs(myType);
}
上記のコードを実行します。実行後、Atlas ホームページに移動して、型が正常に作成されたことを確認します。
型モデル図を表示します。
タイプが作成されたので、次にエンティティを作成します。
エンティティ test_db、test_table_source、test_table_target を作成する
json は次のとおりです。
//my_db 实体
{
"typeName": "my_db",
"attributes": {
"qualifiedName": "test_db",
"name": "test_db",
"description": "测试创建db"
}
}
//test_table_source 实体
{
"typeName": "my_table",
"attributes": {
"qualifiedName": "test_table_source",
"name": "test_table_source",
"description": "测试创建test_table_source"
},
"relationshipAttributes": {
"db": {
"typeName": "my_db",
//my_db的guid(创建完my_db后会返回)
"guid": "xxxx"
}
}
}
//test_table_target 实体
{
"typeName": "my_table",
"attributes": {
"qualifiedName": "test_table_target",
"name": "test_table_target",
"description": "测试创建test_table_target"
},
"relationshipAttributes": {
"db": {
"typeName": "my_db",
"guid": "xxx"
}
}
}
コードは次のように実装されます。
//创建实体 test_db
AtlasEntity testDb = new AtlasEntity();
testDb.setTypeName("my_db");
Map<String, Object> attributes = new HashMap<>();
attributes.put("qualifiedName", "test_db");
attributes.put("name", "test_db");
attributes.put("description", "测试创建db");
testDb.setAttributes(attributes);
Map<String, String> queryAttributes = new HashMap<>();
queryAttributes.put("qualifiedName", "test_db");
String myDbGuid = null;
try {
//查询不到会报错
AtlasEntity.AtlasEntityWithExtInfo extInfo = atlasClientV2.getEntityByAttribute("my_db", queryAttributes);
myDbGuid = extInfo.getEntity().getGuid();
} catch (AtlasServiceException e) {
if (ClientResponse.Status.NOT_FOUND.equals(e.getStatus())) {
AtlasEntity.AtlasEntityWithExtInfo extInfo = new AtlasEntity.AtlasEntityWithExtInfo(testDb);
//请求
EntityMutationResponse response = atlasClientV2.createEntity(extInfo);
myDbGuid = response.getGuidAssignments().values().toArray(new String[]{
})[0];
}
}
//创建与db的关系
Map<String, Object> relationShipAttr = new HashMap<>();
Map<String, String> dbMap = new HashMap<>();
dbMap.put("guid", myDbGuid);
dbMap.put("typeName", "my_db");
relationShipAttr.put("db", dbMap);
//创建实体 test_table_source
AtlasEntity testTableSource = new AtlasEntity();
testTableSource.setTypeName("my_table");
attributes.put("qualifiedName", "test_table_source");
attributes.put("name", "test_table_source");
attributes.put("description", "测试创建test_table_source");
testTableSource.setAttributes(attributes);
testTableSource.setRelationshipAttributes(relationShipAttr);
queryAttributes.put("qualifiedName", "test_table_source");
try {
//atlasClientV2.updateEntity(new AtlasEntity.AtlasEntityWithExtInfo(testTableSource));
AtlasEntity.AtlasEntityWithExtInfo extInfo = atlasClientV2.getEntityByAttribute("my_table", queryAttributes);
testTableSource = extInfo.getEntity();
} catch (AtlasServiceException e) {
if (ClientResponse.Status.NOT_FOUND.equals(e.getStatus())) {
AtlasEntity.AtlasEntityWithExtInfo extInfo = new AtlasEntity.AtlasEntityWithExtInfo(testTableSource);
//请求
EntityMutationResponse response = atlasClientV2.createEntity(extInfo);
testTableSource.setGuid(response.getGuidAssignments().values().toArray(new String[]{
})[0]);
}
}
//创建实体 test_table_target
AtlasEntity testTableTarget = new AtlasEntity();
testTableTarget.setTypeName("my_table");
attributes.put("qualifiedName", "test_table_target");
attributes.put("name", "test_table_target");
attributes.put("description", "测试创建test_table_target");
testTableTarget.setAttributes(attributes);
testTableTarget.setRelationshipAttributes(relationShipAttr);
queryAttributes.put("qualifiedName", "test_table_target");
try {
//atlasClientV2.updateEntity(new AtlasEntity.AtlasEntityWithExtInfo(testTableTarget));
AtlasEntity.AtlasEntityWithExtInfo extInfo = atlasClientV2.getEntityByAttribute("my_table", queryAttributes);
testTableTarget = extInfo.getEntity();
} catch (AtlasServiceException e) {
if (ClientResponse.Status.NOT_FOUND.equals(e.getStatus())) {
AtlasEntity.AtlasEntityWithExtInfo extInfo = new AtlasEntity.AtlasEntityWithExtInfo(testTableTarget);
//请求
EntityMutationResponse response = atlasClientV2.createEntity(extInfo);
testTableTarget.setGuid(response.getGuidAssignments().values().toArray(new String[]{
})[0]);
}
}
コードを実行した後、クラスのツリー図を確認して、エンティティが生成されていることを確認します。
右側の test_db エンティティをクリックすると、その基本情報と、test_table_source と test_table_target の 2 つのエンティティを含む関係情報が表示されます。
次のような関係情報を表示します。 test_table_source と test_table_target:
test_table_source と test_table_target の血縁関係の依存関係を作成する
前に述べたように、test_table_target を定義するデータは test_table_source から取得されます。血液関係の依存関係は実際には Atlas のエンティティとして存在しますが、継承された親クラスは Process です。このようにして、入力属性と出力属性を定義して血液を構築できます。 json は次のとおりです。
{
"typeName": "Process",
"attributes": {
"name": "test_process",
"qualifiedName": "test_process",
"description": "test_table_target 的数据来自 test_table_source",
"inputs": [{
"typeName": "my_table",
//test_table_source的guid,创建实体从返回的信息中获取
"guid": "xxx"
}],
"outputs": [{
"typeName": "my_table",
test_table_target的guid,创建实体从返回的信息中获取
"guid": "xxx"
}]
}
}
コードは次のように実装されます。
AtlasEntity lineage = new AtlasEntity();
//设置为process类型构建血缘
lineage.setTypeName(AtlasBaseTypeDef.ATLAS_TYPE_PROCESS);
attributes.put("qualifiedName", "test_process");
attributes.put("name", "test_process");
attributes.put("description", "test_table_target 的数据来自 test_table_source");
attributes.put("inputs", getLineAgeInfo(testTableSource));
attributes.put("outputs", getLineAgeInfo(testTableTarget));
lineage.setAttributes(attributes);
queryAttributes.put("qualifiedName", "test_process");
System.out.println(SingletonObject.OBJECT_MAPPER.writeValueAsString(lineage));
try {
//查询是否存在
atlasClientV2.getEntityByAttribute(AtlasBaseTypeDef.ATLAS_TYPE_PROCESS, queryAttributes);
} catch (AtlasServiceException e) {
if (ClientResponse.Status.NOT_FOUND.equals(e.getStatus())) {
//创建
AtlasEntity.AtlasEntityWithExtInfo extInfo = new AtlasEntity.AtlasEntityWithExtInfo(lineage);
atlasClientV2.createEntity(extInfo);
}
}
//构建inputs和outputs
private static List<Map<String, String>> getLineAgeInfo(AtlasEntity entity) {
List<Map<String, String>> list = new ArrayList<>();
Map<String, String> map = new HashMap<>();
map.put("guid", entity.getGuid());
map.put("typeName", entity.getTypeName());
list.add(map);
return list;
}
上記のコードを実行し、ホームページを開き、my_table の test_table_source をクリックして、血統タグを確認します。血統関係は正常に構築されました。
この時点で、次のモデルが完成しました。 Atlas Rest Api. を通じて私たち自身がエンティティを作成し、血縁関係の構築が完了します。
メタデータ管理とデータ ガバナンスは、今日でも注目のトピックですが、同時に、企業データ資産のサポート、データ分析の改善、企業開発の意思決定に対する効果的な支援の提供にも役立ちます。
引用链接:
1、https://blog.csdn.net/hshudoudou/article/details/123899947
2、https:/ /blog.csdn.net/javaThanksgiving/article/details/130505251
3、原文 https://blog.csdn.net/m0_37719874/article/details/124245209