PowerData

编者荐语:

来自PowerData-张文慧同学的文章

以下文章来源于DataSpeed ,作者张文慧

[

DataSpeed .

慢慢积累,稳稳前行,用数据说话,为成长助力

](#)

Datahub-元数据管理与治理利器

导读:

本文深入介绍了 Datahub 这一现代数据目录。文章开篇简要阐述了 Datahub 的功能,如简化元数据管理、助力数据发现与治理等,强调其对数据从业者的重要性。接着列举了 datahub 的主要特点,包括数据发现、管理、质量控制等。通过本文,你可全面了解 Datahub 的能力与使用。

1.Datahub 简介

DataHub 是一个现代数据目录,旨在简化元数据管理、数据发现和数据治理。它使用户能够有效地探索和理解他们的数据、跟踪数据沿袭、分析数据集并建立数据合同。这个可扩展的元数据管理平台专为开发人员构建,旨在应对快速发展的数据生态系统的复杂性,并让数据从业者利用其组织内数据的总价值。

注意这里说的不是阿里的 datahub,而是元数据工具 datahub。

datahub 的主要特点:

  • data discovery 数据发现
  • data governace 数据管理
  • data quality control 数据质量控制
  • UI-based Ingestion 基于 UI 的数据摄取
  • APIs and SDKs 丰富的 api 和 sdk

接下来我会逐步介绍 datahub 的能力和使用

2.Datahub 部署

datahub 支持使用云和本地部署。在学习的过程中推荐使用本地 docker 部署会比较快。

使用 docker 部署时要确定 python 版本 3.8+

可以直接使用我下面 0.15 版本的 docker-compose.yaml 文件,或者参考官方 github 上的 docker-compose 选择其他版本的github 地址[1] 。建议使用较新的版本。

networks:   default:     name:datahub_network services: broker:     depends_on:       zookeeper:         condition:service_healthy     environment:     -KAFKA_BROKER_ID=1     -KAFKA_ZOOKEEPER_CONNECT=zookeeper:2181     -KAFKA_LISTENER_SECURITY_PROTOCOL_MAP=PLAINTEXT:PLAINTEXT,PLAINTEXT_HOST:PLAINTEXT     -KAFKA_ADVERTISED_LISTENERS=PLAINTEXT://broker:29092,PLAINTEXT_HOST://localhost:9092     -KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR=1     -KAFKA_GROUP_INITIAL_REBALANCE_DELAY_MS=0     -KAFKA_HEAP_OPTS=-Xms256m-Xmx256m     -KAFKA_CONFLUENT_SUPPORT_METRICS_ENABLE=false     -KAFKA_MESSAGE_MAX_BYTES=5242880     -KAFKA_MAX_MESSAGE_BYTES=5242880     healthcheck:       interval:1s       retries:5       start_period:60s       test:nc-zbroker$${DATAHUB_KAFKA_BROKER_PORT:-9092}       timeout:5s     hostname:broker     image:${DATAHUB_CONFLUENT_KAFKA_IMAGE:-confluentinc/cp-kafka}:${DATAHUB_CONFLUENT_VERSION:-7.4.0}     ports:     -${DATAHUB_MAPPED_KAFKA_BROKER_PORT:-9092}:9092     volumes:     -broker:/var/lib/kafka/data/ datahub-actions:     depends_on:       datahub-gms:         condition:service_healthy     environment:     -ACTIONS_CONFIG=${ACTIONS_CONFIG:-}     -ACTIONS_EXTRA_PACKAGES=${ACTIONS_EXTRA_PACKAGES:-}     -DATAHUB_GMS_HOST=datahub-gms     -DATAHUB_GMS_PORT=8080     -DATAHUB_GMS_PROTOCOL=http     -DATAHUB_SYSTEM_CLIENT_ID=__datahub_system     -DATAHUB_SYSTEM_CLIENT_SECRET=JohnSnowKnowsNothing     -KAFKA_BOOTSTRAP_SERVER=broker:29092     -KAFKA_PROPERTIES_SECURITY_PROTOCOL=PLAINTEXT     -METADATA_AUDIT_EVENT_NAME=MetadataAuditEvent_v4     -METADATA_CHANGE_LOG_VERSIONED_TOPIC_NAME=MetadataChangeLog_Versioned_v1     -SCHEMA_REGISTRY_URL=http://schema-registry:8081     hostname:actions     image:${DATAHUB_ACTIONS_IMAGE:-acryldata/datahub-actions}:${ACTIONS_VERSION:-head} datahub-frontend-react:     depends_on:       datahub-gms:         condition:service_healthy     environment:     -DATAHUB_GMS_HOST=datahub-gms     -DATAHUB_GMS_PORT=8080     -DATAHUB_SECRET=YouKnowNothing     -DATAHUB_APP_VERSION=1.0     -DATAHUB_PLAY_MEM_BUFFER_SIZE=10MB     -JAVA_OPTS=-Xms512m-Xmx512m-Dhttp.port=9002-Dconfig.file=datahub-frontend/conf/application.conf-Djava.security.auth.login.config=datahub-frontend/conf/jaas.conf-Dlogback.configurationFile=datahub-frontend/conf/logback.xml-Dlogback.debug=false-Dpidfile.path=/dev/null     -KAFKA_BOOTSTRAP_SERVER=broker:29092     -DATAHUB_TRACKING_TOPIC=DataHubUsageEvent_v1     -ELASTIC_CLIENT_HOST=elasticsearch     -ELASTIC_CLIENT_PORT=9200     hostname:datahub-frontend-react     image:${DATAHUB_FRONTEND_IMAGE:-acryldata/datahub-frontend-react}:${DATAHUB_VERSION:-head}     ports:     -${DATAHUB_MAPPED_FRONTEND_PORT:-9002}:9002     volumes:     -${HOME}/.datahub/plugins:/etc/datahub/plugins datahub-gms:     depends_on:       datahub-upgrade:         condition:service_completed_successfully     environment:     -DATAHUB_SERVER_TYPE=${DATAHUB_SERVER_TYPE:-quickstart}     -DATAHUB_TELEMETRY_ENABLED=${DATAHUB_TELEMETRY_ENABLED:-true}     -DATAHUB_UPGRADE_HISTORY_KAFKA_CONSUMER_GROUP_ID=generic-duhe-consumer-job-client-gms     -EBEAN_DATASOURCE_DRIVER=com.mysql.jdbc.Driver     -EBEAN_DATASOURCE_HOST=mysql:3306     -EBEAN_DATASOURCE_PASSWORD=datahub     -EBEAN_DATASOURCE_URL=jdbc:mysql://mysql:3306/datahub?verifyServerCertificate=false&useSSL=true&useUnicode=yes&characterEncoding=UTF-8     -EBEAN_DATASOURCE_USERNAME=datahub     -ELASTICSEARCH_HOST=elasticsearch     -ELASTICSEARCH_INDEX_BUILDER_MAPPINGS_REINDEX=true     -ELASTICSEARCH_INDEX_BUILDER_SETTINGS_REINDEX=true     -ELASTICSEARCH_PORT=9200     -ENTITY_REGISTRY_CONFIG_PATH=/datahub/datahub-gms/resources/entity-registry.yml     -ENTITY_SERVICE_ENABLE_RETENTION=true     -ES_BULK_REFRESH_POLICY=WAIT_UNTIL     -GRAPH_SERVICE_DIFF_MODE_ENABLED=true     -GRAPH_SERVICE_IMPL=elasticsearch     -JAVA_OPTS=-Xms1g-Xmx1g     -KAFKA_BOOTSTRAP_SERVER=broker:29092     -KAFKA_CONSUMER_STOP_ON_DESERIALIZATION_ERROR=${KAFKA_CONSUMER_STOP_ON_DESERIALIZATION_ERROR:-true}     -KAFKA_SCHEMAREGISTRY_URL=http://schema-registry:8081     -MAE_CONSUMER_ENABLED=true     -MCE_CONSUMER_ENABLED=true     -METADATA_SERVICE_AUTH_ENABLED=${METADATA_SERVICE_AUTH_ENABLED:-false}     -PE_CONSUMER_ENABLED=true     -UI_INGESTION_ENABLED=true     healthcheck:       interval:1s       retries:3       start_period:90s       test:curl-sS--failhttp://datahub-gms:${DATAHUB_GMS_PORT:-8080}/health       timeout:5s     hostname:datahub-gms     image:${DATAHUB_GMS_IMAGE:-acryldata/datahub-gms}:${DATAHUB_VERSION:-head}     ports:     -${DATAHUB_MAPPED_GMS_PORT:-8080}:8080     volumes:     -${HOME}/.datahub/plugins:/etc/datahub/plugins datahub-upgrade:     command:     --u     -SystemUpdate     depends_on:       elasticsearch-setup:         condition:service_completed_successfully       kafka-setup:         condition:service_completed_successfully       mysql-setup:         condition:service_completed_successfully     environment:     -EBEAN_DATASOURCE_USERNAME=datahub     -EBEAN_DATASOURCE_PASSWORD=datahub     -EBEAN_DATASOURCE_HOST=mysql:3306     -EBEAN_DATASOURCE_URL=jdbc:mysql://mysql:3306/datahub?verifyServerCertificate=false&useSSL=true&useUnicode=yes&characterEncoding=UTF-8     -EBEAN_DATASOURCE_DRIVER=com.mysql.jdbc.Driver     -KAFKA_BOOTSTRAP_SERVER=broker:29092     -KAFKA_SCHEMAREGISTRY_URL=http://schema-registry:8081     -ELASTICSEARCH_HOST=elasticsearch     -ELASTICSEARCH_PORT=9200     -ELASTICSEARCH_INDEX_BUILDER_MAPPINGS_REINDEX=true     -ELASTICSEARCH_INDEX_BUILDER_SETTINGS_REINDEX=true     -ELASTICSEARCH_BUILD_INDICES_CLONE_INDICES=false     -GRAPH_SERVICE_IMPL=elasticsearch     -DATAHUB_GMS_HOST=datahub-gms     -DATAHUB_GMS_PORT=8080     -ENTITY_REGISTRY_CONFIG_PATH=/datahub/datahub-gms/resources/entity-registry.yml     -BACKFILL_BROWSE_PATHS_V2=true     -REPROCESS_DEFAULT_BROWSE_PATHS_V2=false     hostname:datahub-upgrade     image:${DATAHUB_UPGRADE_IMAGE:-acryldata/datahub-upgrade}:${DATAHUB_VERSION:-head}     labels:       datahub_setup_job:true elasticsearch:     deploy:       resources:         limits:           memory:1G     environment:     -discovery.type=single-node     -${XPACK_SECURITY_ENABLED:-xpack.security.enabled=false}     -ES_JAVA_OPTS=-Xms256m-Xmx512m-Dlog4j2.formatMsgNoLookups=true     -OPENSEARCH_JAVA_OPTS=-Xms512m-Xmx512m-Dlog4j2.formatMsgNoLookups=true     healthcheck:       interval:1s       retries:3       start_period:20s       test:curl-sS--failhttp://elasticsearch:$${DATAHUB_ELASTIC_PORT:-9200}/_cluster/health?wait_for_status=yellow&timeout=0s       timeout:5s     hostname:elasticsearch     image:${DATAHUB_SEARCH_IMAGE:-elasticsearch}:${DATAHUB_SEARCH_TAG:-7.10.1}     ports:     -${DATAHUB_MAPPED_ELASTIC_PORT:-9200}:9200     volumes:     -esdata:/usr/share/elasticsearch/data elasticsearch-setup:     depends_on:       elasticsearch:         condition:service_healthy     environment:     -ELASTICSEARCH_USE_SSL=${ELASTICSEARCH_USE_SSL:-false}     -USE_AWS_ELASTICSEARCH=${USE_AWS_ELASTICSEARCH:-false}     -ELASTICSEARCH_HOST=elasticsearch     -ELASTICSEARCH_PORT=9200     -ELASTICSEARCH_PROTOCOL=http     hostname:elasticsearch-setup     image:${DATAHUB_ELASTIC_SETUP_IMAGE:-acryldata/datahub-elasticsearch-setup}:${DATAHUB_VERSION:-head}     labels:       datahub_setup_job:true kafka-setup:     depends_on:       broker:         condition:service_healthy       schema-registry:         condition:service_healthy     environment:     -DATAHUB_PRECREATE_TOPICS=${DATAHUB_PRECREATE_TOPICS:-false}     -KAFKA_BOOTSTRAP_SERVER=broker:29092     -KAFKA_ZOOKEEPER_CONNECT=zookeeper:2181     -USE_CONFLUENT_SCHEMA_REGISTRY=TRUE     hostname:kafka-setup     image:${DATAHUB_KAFKA_SETUP_IMAGE:-acryldata/datahub-kafka-setup}:${DATAHUB_VERSION:-head}     labels:       datahub_setup_job:true mysql:     command:--character-set-server=utf8mb4--collation-server=utf8mb4_bin--default-authentication-plugin=mysql_native_password     environment:     -MYSQL_DATABASE=datahub     -MYSQL_USER=datahub     -MYSQL_PASSWORD=datahub     -MYSQL_ROOT_PASSWORD=datahub     healthcheck:       interval:1s       retries:5       start_period:20s       test:mysqladminping-hmysql-u$$MYSQL_USER--password=$$MYSQL_PASSWORD       timeout:5s     hostname:mysql     image:mariadb:10.5.8     ports:     -${DATAHUB_MAPPED_MYSQL_PORT:-3306}:3306     restart:on-failure     volumes:     -mysqldata:/var/lib/mysql mysql-setup:     depends_on:       mysql:         condition:service_healthy     environment:     -MYSQL_HOST=mysql     -MYSQL_PORT=3306     -MYSQL_USERNAME=datahub     -MYSQL_PASSWORD=datahub     -DATAHUB_DB_NAME=datahub     hostname:mysql-setup     image:${DATAHUB_MYSQL_SETUP_IMAGE:-acryldata/datahub-mysql-setup}:${DATAHUB_VERSION:-head}     labels:       datahub_setup_job:true schema-registry:     depends_on:       broker:         condition:service_healthy     environment:     -SCHEMA_REGISTRY_HOST_NAME=schemaregistry     -SCHEMA_REGISTRY_KAFKASTORE_SECURITY_PROTOCOL=PLAINTEXT     -SCHEMA_REGISTRY_KAFKASTORE_BOOTSTRAP_SERVERS=broker:29092     healthcheck:       interval:1s       retries:3       start_period:60s       test:nc-zschema-registry${DATAHUB_SCHEMA_REGISTRY_PORT:-8081}       timeout:5s     hostname:schema-registry     image:${DATAHUB_CONFLUENT_SCHEMA_REGISTRY_IMAGE:-confluentinc/cp-schema-registry}:${DATAHUB_CONFLUENT_VERSION:-7.4.0}     ports:     -${DATAHUB_MAPPED_SCHEMA_REGISTRY_PORT:-8081}:8081 zookeeper:     environment:     -ZOOKEEPER_CLIENT_PORT=2181     -ZOOKEEPER_TICK_TIME=2000     healthcheck:       interval:5s       retries:3       start_period:30s       test:echosrvr|nczookeeper$${DATAHUB_ZK_PORT:-2181}       timeout:5s     hostname:zookeeper     image:${DATAHUB_CONFLUENT_ZOOKEEPER_IMAGE:-confluentinc/cp-zookeeper}:${DATAHUB_CONFLUENT_VERSION:-7.4.0}     ports:     -${DATAHUB_MAPPED_ZK_PORT:-2181}:2181     volumes:     -zkdata:/var/lib/zookeeper/data     -zklogs:/var/lib/zookeeper/log volumes: broker:null esdata:null mysqldata:null zkdata:null zklogs:null

使用 docker 部署十分简单,这里不再赘述。

3.datahub 主要功能

3.1 datahub VS datahub cloud

大部分 datahub 自身的能力就已经够用了,不过企业级大规模的使用可是考虑使用 datahub cloud 的方式。

  • 搜索与发现方面
  • 两者都支持 50 + 数据源集成、表级 / 列级 / 作业级血缘、跨所有元数据搜索、表和列级血缘及影响分析、对域 / 数据产品 / 数据契约的支持、开发者友好体验。
  • 但 DataHub Cloud 还具有使用和基于图的搜索排名、业务用户友好体验、产品个性化、BI 工具浏览器扩展、无代码元数据自动化、Slack 集成、资产 / 活动订阅及通知等功能,而 DataHub 没有这些功能。
  • 数据治理方面
  • 两者都支持左移治理、数据集所有权管理、业务术语表基础功能。
  • DataHub Cloud 额外具备人工辅助资产认证工作流、计算治理标准作为持续测试、业务术语表修改审批工作流、术语与资产关联审批工作流、所有权审批工作流等功能,DataHub 不具备这些。
  • 数据可观测性方面
  • 都能展示数据质量结果、创建数据契约、提出和解决数据事件。
  • DataHub Cloud 还可监控新鲜度 SLA、表模式、表体积、表列完整性、使用自定义 SQL 监控表,以及通过邮件和 Slack 接收通知、通过 Slack 管理数据事件、查看数据健康仪表板、按需评估数据质量检查(API + UI)、在 VPC 中评估数据质量检查,DataHub 则不支持这些。
  • 企业级特性方面
  • 均为经过实战检验的开源元数据平台,都有元数据变更事件实时流。
  • DataHub Cloud 具有 99.5% 正常运行时间 SLA、数据湖和数据仓库元数据分析卸载、细粒度访问控制策略(如默认拒绝)、预定义权限角色、共享审计日志等功能,DataHub 没有。

下面的介绍以 datahub 为主,如果使用 datahub cloud 建议细读官网[2]

3.2 Business Glossary 业务术语表

在复杂的数据生态系统中工作时,使用共享词汇表组织数据资产非常有用。DataHub 中的 Business Glossary 功能通过提供一个框架来定义一组标准化的数据概念,然后将它们与数据生态系统中存在的物理资产相关联。

3.2.1 Terms & Term Groups 术语和术语组

A Business Glossary is comprised of two important primitives: Terms and Term Groups. 业务术语表由两个重要的原语组成:术语和术语组。

  • Terms: words or phrases with a specific business definition assigned to them.术语:分配了特定业务定义的单词或短语。
  • Term Groups: act like folders, containing Terms and even other Term Groups to allow for a nested structure.术语组:就像文件夹一样,包含术语甚至其他术语组,以允许嵌套结构。
3.2.2 创建、使用术语

术语的创建十分简单, Govern -> Glossary

如下图,创建业务术语

使用术语

3.2.3 git 管理术语

更厉害的是,竟然还可以用 git 这样版本控制系统管理术语,这可以通过变更管理和审查流程汇集所有变更,从而更轻松地管理跨团队的变更。具体内容可以参考这里[3]

3.3 Ingestion 摄入

0.8.25版本开始,DataHub 支持使用 DataHub 用户界面创建、配置、调度和执行批量元数据摄取。这通过最大限度地减少操作自定义集成管道所需的开销,可以更轻松地将元数据导入 DataHub。所以你可能在别的教程里看到使用 yaml 的方式导入元数据,现在可以页面化操作了。

3.3.1 connect data source

  • Airflow:开源数据编排工具,用于调度、监控和管理复杂数据管道。
  • Databricks:云数据处理和分析平台,使数据科学家和工程师能够协作并构建数据驱动的应用程序。
  • Druid:开源数据存储,专为大型数据集的实时分析而设计。
  • Elasticsearch:分布式开源搜索和分析引擎,用于处理大量数据。
  • Hive:数据仓库工具,便于查询和管理存储在 Hadoop 分布式文件系统(HDFS)中的大型数据集。
  • Apache Hudi:开源数据湖框架,为大型数据集提供 ACID 事务、高效更新、时间旅行查询和增量数据处理。
  • Iceberg:允许用户使用分布式架构管理和查询大型数据集的数据工具。
  • JSON Schemas:用于定义 JSON 数据的结构、格式和验证规则的数据工具。
  • Kafka:分布式流处理平台,用于实时处理和存储大量数据。
  • MongoDB:NoSQL 数据库,以灵活的 JSON 类似文档存储数据,便于为现代应用程序存储和检索数据。
  • MySQL:开源关系型数据库管理系统,允许用户有效地存储、组织和检索数据。
  • Oracle:关系型数据库管理系统,提供全面集成的平台用于管理和分析大量数据。
  • Postgres:开源关系型数据库管理系统,为存储、管理和分析大量数据提供强大工具。
  • Presto:开源分布式 SQL 查询引擎,专为大规模数据集的快速和交互式分析而设计。
3.3.1 创建 data source

有多种方式:UI 用户界面、CLI 命令行界面、GraphQL 图形。需要注意的是,这里有需要你有相应的权限。

以 UI 为例:

这里还是保留了原来使用 yaml 的方式。

可以根据需求定时同步元数据信息。


使用doris 的朋友要使用 9030 端口才能把原数据摄入。

3.4 domain 域

从版本 0.8.25 开始,DataHub 支持将数据资产分组到称为 Domains 的逻辑集合中。域是精选的顶级文件夹或类别,可在其中对相关资产进行显式分组。域的管理可以集中管理,也可以分发给域所有者 目前,一个资产一次只能属于一个域。

域是经过管理的顶级文件夹或类别,使您能够显式地对相关实体进行分组。这对于希望按部门 (如财务、市场等)、数据产品或其他数据网格采用中常见的逻辑分组来组织实体的组织非常有用。

3.4.1 创建和使用域

创建域

设置域

将资产分配到域

设置域之后,可以快速搜索到这个 domain

3.5 Lineage 数据血缘

数据血缘是显示数据如何在组织中流动的地图。它详细说明了数据的来源、传输方式以及最终目的地。这可能发生在单个系统内或跨各种平台,数据血缘可以手动添加,也支持使用 api 批量维护,如何和使用 api 快速便捷的导入的 datahub,请关注 dataspeed 公众号,会在之后的文章中详细讲述

3.6 Ownership 所有权

创建

创建

设置

4 datahub 功能总结

上面介绍了一写 datahub 个人比较关心的功能,当然除此以外 datahub 还有很多能力。

我做了简单的总结,如下表。

序号

功能

简介

1

Access Policies 访问策略

访问策略定义谁可以对哪些资源执行哪些操作。访问策略与角色一起确定允许用户在 DataHub 上执行哪些操作。

2

Posts 职位

DataHub 允许用户创建可在应用程序上显示的帖子。目前,帖子仅在主页上受支持,但将来可能会扩展到应用程序的其他平台。

3

About DataHub Properties 关于 DataHub 属性

DataHub 自定义属性和结构化属性是强大的工具,用于收集可能不适合 DataHub 中其他方面的资产的有意义的元数据,例如术语表术语、标签等。

4

Schema History Schema 历史记录

架构历史记录是一个有价值的工具,可用于了解 Dataset 如何随时间变化,并深入了解以下情况,并在发生这些更改时通知数据从业者。

5

Search 搜索

搜索栏是发现 DataHub 中数据资产的重要机制。在搜索栏中,可以找到 Datasets、Columns、Dashboards、Charts、Data Pipelines 等。

6

Sync Status 同步状态

在 DataHub 中查看元数据时,了解您正在查看的信息是否相关非常有用。具体来说,如果元数据过时或有一段时间未更新,则应考虑使用元数据摄取刷新该元数据,或者将其删除(如果它不再存在)。

7

Tags 标签

标签是非正式的、松散控制的标签,有助于搜索和发现。它们可以添加到数据集、数据集架构或容器中,以便轻松标记或分类实体,而无需将它们与更广泛的业务词汇表或词汇表相关联。

引用链接

[1] 

github地址: https://github.com/datahub-pr...

[2] 

datahub官网: https://datahubproject.io/doc...

[3] 

git管理术语: https://github.com/acryldata/...

[4] 

source官网: https://datahubproject.io/int...

关于作者

作者重视实战与理论的结合,文章干货满满,有较为丰富的平台、数开经验,欢迎和作者一起交流,共同进步。

DataSpeed聚焦大数据实战与大数据资讯,技术干货和行业消息一网打尽。期待与你同行,欢迎扫码添加作者微信。

关于社区

PowerData社区是由一群数据从业人员,因为热爱凝聚在一起,以开源精神为基础,组成的数据开源社区。

社区群内会定期组织模拟面试、线上分享、行业研讨(涉及金融、医疗、能源、工业、互联网等)、线下Meet UP、城市聚会、求职内推等。同时,在社区群内您可以进行技术讨论、问题请教,届时更多志同道合的数据朋友。

社区整理了一份每日一题汇总及社区分享PPT,内容涵盖大数据组件、编程语言、数据结构与算法、企业真实面试题等各个领域,帮助您自我提升,成功上岸。可以添加作者微信(zwhuihuiz),进入PowerData官方社区群。 

往期推荐

Flink实战 | PostgresCDC整库同步Kafka最佳实践

数据血缘 | 图数据库,一个绕不开的话题

数据血缘 | 探索SQLGlot的实用性与解析技巧


PowerData
1 声望2 粉丝

PowerData社区官方思否账号