开源自托管 Delta Sharing 服务器
作者:Shingo Okawa
我叫 Shingo,是 Kotosiro Sharing 的创建者。我很高兴地宣布发布 Kotosiro Sharing,这是一个极简的 Rust 实现的 Delta Sharing 服务器,旨在帮助工程师轻松托管自己的 Delta Sharing 服务。在本文中,我将提供如何使用自托管的 Kotosiro Sharing 服务器与技术背景各异的同事(从数据工程师到商业智能分析师)共享数据的说明。这些说明非常简单明了,您可以轻松地与具有不同技术水平的同事共享数据。该实现目前处于测试阶段,因此尚未提供图形用户界面。但是,此功能将在不久的将来添加。下图描绘了系统工作流程。让我们来看看当您想与同事共享宝贵数据时 Kotosiro Sharing 是如何工作的。
Delta 表结构
您的 Delta 表在 AWS S3 上存储了美国多个市场的鳄梨价格和销售量的历史数据。您的同事来到您的办公桌前,询问他们是否可以使用这些数据进行进一步的数据分析。该表的结构如下:
avocado-table
├── _delta_log
│ ├── 00000000000000000000.json
│ ├── 00000000000000000001.json
│ ├── 00000000000000000002.json
│ └── 00000000000000000003.json
├── part-00000-04d10a18-acde-4d66-bb3b-39f5d0feb689-c000.snappy.parquet
├── part-00000-c5135c42-2c15-4da5-8cd6-f0fc527dff9c-c000.snappy.parquet
├── part-00000-c6c1e092-bef3-41a0-8a05-826a33ecff6f-c000.snappy.parquet
└── part-00000-d7afaec2-4373-4865-ab48-e9f60495b41e-c000.snappy.parquet
每个 parquet 文件都按顺序附加。因此,该表有四个不同的版本。
通过 Kotosiro Sharing API 共享您的 Delta 表
登录 Kotosiro Sharing Server 并获取管理员访问令牌
现在让我们开始有趣的部分。作为数据所有者和 Kotosiro Sharing 服务器的管理员,您需要登录系统并获取管理员访问令牌。此令牌将使您能够创建共享。以下是获取令牌的方法:
$ curl -s -X POST https://:8080/admin/login \
-H "Content-Type: application/json" \
-d '{"account": "kotosiro", "password": "password"}' \
| jq '.'
{
"profile": {
"shareCredentialsVersion": 1,
"endpoint": "http://127.0.0.1:8080",
"bearerToken": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJuYW1lIjoia290b3Npcm8iLCJlbWFpbCI6ImtvdG9zaXJvQGVtYWlsLmNvbSIsIm5hbWVzcGFjZSI6ImFkbWluIiwicm9sZSI6ImFkbWluIiwiZXhwIjoxNjgxOTM3NzMyfQ.rVjA6S7EWq7CakpB0IHik0mvxl58ynZNxNM3a3RJibY",
"expirationTime": "2023-04-19 20:55:32 UTC"
}
}
注册新共享
接下来,您需要注册一个新的共享,这只是一个用于与接收者共享的逻辑分组。例如,您可以将共享命名为 share1
。请注意,此共享目前为空,这意味着您尚未向其中添加任何数据。以下是创建共享的方法:
$ curl -s -X POST "https://:8080/admin/shares" \
-H "Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJuYW1lIjoia290b3Npcm8iLCJlbWFpbCI6ImtvdG9zaXJvQGVtYWlsLmNvbSIsIm5hbWVzcGFjZSI6ImFkbWluIiwicm9sZSI6ImFkbWluIiwiZXhwIjoxNjgxOTM3NzMyfQ.rVjA6S7EWq7CakpB0IHik0mvxl58ynZNxNM3a3RJibY" \
-H "Content-Type: application/json" \
-d '{ "name": "share1" }' \
| jq '.'
{
"share": {
"id": "78f84b5e-29e7-4adf-8df5-c40487a8da43",
"name": "share1"
}
}
注册新表
到目前为止一切顺利。现在是时候通过 API 将 AWS S3 上的 Delta 表注册到您的 Kotosiro Sharing 服务了。它与其他操作一样相当简单。只需发布指定 Delta 表的 S3 存储桶对象路径以及表名称的 JSON 数据即可。例如,您可以将表命名为 table1
。以下是注册表的方法:
$ curl -s -X POST "https://:8080/admin/tables" \
-H "Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJuYW1lIjoia290b3Npcm8iLCJlbWFpbCI6ImtvdG9zaXJvQGVtYWlsLmNvbSIsIm5hbWVzcGFjZSI6ImFkbWluIiwicm9sZSI6ImFkbWluIiwiZXhwIjoxNjgxOTM3NzMyfQ.rVjA6S7EWq7CakpB0IHik0mvxl58ynZNxNM3a3RJibY" \
-H "Content-Type: application/json" \
-d '{ "name": "table1", "location": "s3://kotosiro-sharing-example/avocado" }' \
| jq '.'
{
"table": {
"id": "8a040c74-4505-44e5-aeda-9db662f338eb",
"name": "table1",
"location": "s3://kotosiro-sharing-example/avocado"
}
}
将新表注册为 share1 中 schema1 的一部分
您已经创建了一个新的共享并注册了一个新的表。现在,您需要通过创建模式将表与共享关联起来。为此,您可以将表注册为 share1
中 schema1
的一部分。将表注册到共享的 API 操作非常简单。以下是一个示例:
$ curl -s -X POST "https://:8080/admin/shares/share1/schemas/schema1/tables" \
-H "Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJuYW1lIjoia290b3Npcm8iLCJlbWFpbCI6ImtvdG9zaXJvQGVtYWlsLmNvbSIsIm5hbWVzcGFjZSI6ImFkbWluIiwicm9sZSI6ImFkbWluIiwiZXhwIjoxNjgxOTM3NzMyfQ.rVjA6S7EWq7CakpB0IHik0mvxl58ynZNxNM3a3RJibY" \
-H "Content-Type: application/json" \
-d '{ "table": "table1" }' \
| jq '.'
{
"schema": {
"id": "62bf785c-1764-4953-9986-a6708996e72c",
"name": "schema1"
}
}
发布新的接收者配置文件
这是与同事共享 Delta 表的最后一步,也是最重要的一步。您需要发布一个新的接收者配置文件,其中包含同事访问共享数据所需的凭据。生成的配置文件 JSON 是凭据,因此您必须安全地与同事共享。作为管理员,您有责任确保配置文件仅与授权的接收者共享。以下是发布配置文件的方法:
$ curl -s -X GET "https://:8080/admin/profile" \
-H "Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJuYW1lIjoia290b3Npcm8iLCJlbWFpbCI6ImtvdG9zaXJvQGVtYWlsLmNvbSIsIm5hbWVzcGFjZSI6ImFkbWluIiwicm9sZSI6ImFkbWluIiwiZXhwIjoxNjgxOTM3NzMyfQ.rVjA6S7EWq7CakpB0IHik0mvxl58ynZNxNM3a3RJibY" \
-H "Content-Type: application/json" \
| jq '.'
{
"profile": {
"shareCredentialsVersion": 1,
"endpoint": "http://127.0.0.1:8080",
"bearerToken": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJuYW1lIjoia290b3Npcm8iLCJlbWFpbCI6ImtvdG9zaXJvQGVtYWlsLmNvbSIsIm5hbWVzcGFjZSI6ImFkbWluIiwicm9sZSI6Imd1ZXN0IiwiZXhwIjoxNjgxOTM3ODA1fQ.Pwqa5ylTDnjyivNsyNTi0QNR1oKuHJhCPPxWiznomRE",
"expirationTime": "2023-04-19 20:56:45 UTC"
}
}
创建共享客户端
从现在开始,您是共享 Delta 表的接收者。要将共享 Delta 表作为 pandas 数据帧打开,作为共享 Delta 表的接收者,您需要首先安装 delta-sharing 包。安装该包后,您可以使用共享的配置文件创建 delta_sharing.SharingClient
对象。这将允许您访问共享 Delta 表。
import delta_sharing
profile = "../../creds/profile.json"
client = delta_sharing.SharingClient(profile)
列出表格
让我们验证我们是否可以正确访问共享的表。以下脚本检索由您的同事提供的共享共享的所有表的列表:
client.list_all_tables()
[Table(name='table1', share='share1', schema='schema1')]
加载表格
现在是时候访问共享数据了。操作非常简单:无需准备麻烦的云服务凭据,也无需担心同事使用什么平台。您所要做的就是指定表的路径。表路径由配置文件路径,后跟 #
和表的完全限定名称组成:<share-name>.<schema-name>.<table-name>
。
url = profile + "#share1.schema1.table1"
delta_sharing.load_as_pandas(url)
行 | 日期 | 平均价格 | 总销量 | 4046 | 4225 | 4770 | 总袋数 | 小袋 | 大袋 | 超大袋 | 类型 | 年份 | 地区 | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 0 | 2015-12-26 15:00:00 | 1.33 | 64236.62 | 1036.74 | 54454.85 | 48.16 | 8696.87 | 8603.62 | 93.25 | 0.0 | 传统 | 2015 | 奥尔巴尼 |
1 | 1 | 2015-12-19 15:00:00 | 1.35 | 54876.98 | 674.28 | 44638.81 | 58.33 | 9505.56 | 9408.07 | 97.49 | 0.0 | 传统 | 2015 | 奥尔巴尼 |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
18247 | 10 | 2018-01-13 15:00:00 | 1.93 | 16205.22 | 1527.63 | 2981.04 | 727.01 | 10969.54 | 10919.54 | 50.00 | 0.0 | 有机 | 2018 | WestTexNewMexico |
18248 | 11 | 2018-01-06 15:00:00 | 1.62 | 17489.58 | 2894.77 | 2356.13 | 224.53 | 12014.15 | 11988.14 | 26.01 | 0.0 | 有机 | 2018 | WestTexNewMexico |
18249 行 × 14 列
用于过滤的 SQL 表达式
太棒了!现在您可以从数据湖中访问所需的数据。假设您只对日期范围在 2016-01-01
和 2017-12-31
之间的数据感兴趣。在这种情况下,您可以将SQL 片段作为提示发送到共享服务器,以便它过滤掉冗余的 Parquet 文件。以下是请求所需的 Parquet 文件的方法(截至 2023 年 4 月 24 日,此过滤 API 在 Python 客户端库中尚未公开,因此此代码片段基于我的本地补丁。我计划在不久的将来创建拉取请求以将此过滤 API 添加到公开版本中):
url = profile + "#share1.schema1.table1"
delta_sharing.load_as_pandas(
url,
predicateHints=['year >= 2016', 'year <= 2017']
)
行 | 日期 | 平均价格 | 总销量 | 4046 | 4225 | 4770 | 总袋数 | 小袋 | 大袋 | 超大袋 | 类型 | 年份 | 地区 | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 0 | 2016-12-24 15:00:00 | 1.52 | 73341.73 | 3202.39 | 58280.33 | 426.92 | 11432.09 | 11017.32 | 411.83 | 2.94 | 传统 | 2016 | 奥尔巴尼 |
1 | 1 | 2016-12-17 15:00:00 | 1.53 | 68938.53 | 3345.36 | 55949.79 | 138.72 | 9504.66 | 8876.65 | 587.73 | 40.28 | 传统 | 2016 | 奥尔巴尼 |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
11336 | 49 | 2017-01-07 15:00:00 | 1.18 | 14375.39 | 1327.98 | 2617.20 | 5.75 | 10424.46 | 10283.85 | 140.61 | 0.00 | 有机 | 2017 | WestTexNewMexico |
11337 | 50 | 2016-12-31 15:00:00 | 1.28 | 15307.87 | 867.66 | 3434.02 | 37.30 | 10968.89 | 10815.88 | 153.01 | 0.00 | 有机 | 2017 | WestTexNewMexico |
11338 行 × 14 列
用于过滤的 JSON 谓词
虽然之前使用SQL 过滤的 predicateHints
很方便,但其逻辑表达能力有点受限,并且根据官方协议规范,建议改用JSON 过滤。需要注意的是,SQL 过滤方法将被弃用。以下是如何使用JSON 过滤请求所需的 Parquet 文件(截至 2023 年 4 月 24 日,此过滤 API 在 Python 客户端库中尚未公开,因此此代码片段基于我的本地补丁。我计划在不久的将来创建拉取请求以将此过滤 API 添加到公开版本中):
url = profile + "#share1.schema1.table1"
delta_sharing.load_as_pandas(
url,
jsonPredicateHints={
"op": "and",
"children": [
{
"op": "greaterThanOrEqual",
"children": [
{"op": "column", "name": "year", "valueType": "int"},
{"op": "literal", "value": "2016", "valueType": "int"}
]
},
{
"op": "lessThanOrEqual",
"children": [
{"op": "column", "name": "year", "valueType":"int"},
{"op": "literal", "value": "2017", "valueType": "int"}
]
}
]
}
)
行 | 日期 | 平均价格 | 总销量 | 4046 | 4225 | 4770 | 总袋数 | 小袋 | 大袋 | 超大袋 | 类型 | 年份 | 地区 | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 0 | 2016-12-24 15:00:00 | 1.52 | 73341.73 | 3202.39 | 58280.33 | 426.92 | 11432.09 | 11017.32 | 411.83 | 2.94 | 传统 | 2016 | 奥尔巴尼 |
1 | 1 | 2016-12-17 15:00:00 | 1.53 | 68938.53 | 3345.36 | 55949.79 | 138.72 | 9504.66 | 8876.65 | 587.73 | 40.28 | 传统 | 2016 | 奥尔巴尼 |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
11336 | 49 | 2017-01-07 15:00:00 | 1.18 | 14375.39 | 1327.98 | 2617.20 | 5.75 | 10424.46 | 10283.85 | 140.61 | 0.00 | 有机 | 2017 | WestTexNewMexico |
11337 | 50 | 2016-12-31 15:00:00 | 1.28 | 15307.87 | 867.66 | 3434.02 | 37.30 | 10968.89 | 10815.88 | 153.01 | 0.00 | 有机 | 2017 | WestTexNewMexico |
11338 行 × 14 列
结论
我很高兴宣布 Kotosiro Sharing 项目的发布,感谢您阅读到这里。我希望您喜欢这次短暂的旅程,并看到了 Delta Sharing 如何改变游戏规则。我真正喜欢这个想法的是:
- 开放且与云无关的协议。
- 易于管理隐私、安全和合规性。
- 消除滞后和不一致的数据,以及无需通过电子邮件发送过时数据。
- 接收者不需要技术专长,因为他们只需要编写几行 Python 代码。
官方开放协议规范可在此处查看。我也欢迎对我的 Kotosiro Sharing 项目做出贡献。感谢阅读!