关键要点
- 数据是当今许多基于 SaaS 的服务的支柱。
- 由于数据和云服务的动态性质,由于工程要求不断变化,数据转换是一种常见的需求。
- 数据转换仍然是工程领域的持续挑战,并且建立在手动工作之上。
- 目前缺乏以编程方式、自动化方式安全地执行数据转换的工具。
- 开源实用程序 Dynamo Data Transform 旨在简化基于 DynamoDB 的系统的安全和护栏,并将其构建为数据转换 - 构建在一个强大的手动框架之上,然后实现自动化和开源。
在将产品设计为自助式开发人员工具时,通常会存在限制 - 但最常见的限制之一可能是规模。确保我们的产品 Jit(一个安全即代码 SaaS 平台)是为扩展而构建的,这不是我们可以事后才想到的,它需要从第一行代码开始设计和处理。
我们希望专注于开发我们的应用程序及其用户体验,而不会遇到问题和规模方面的挑战,这对我们的工程师来说是一个持续的斗争。在研究了可以为我们的团队实现此功能的基础设施之后,我们决定将 AWS 与基于无服务器的架构结合使用。
AWS Lambda正在成为快速增长的SaaS系统的热门选择,因为它通过其工具套件(即支持这些系统的数据库AWS的DynamoDB)为开箱即用的扩展和性能提供了许多好处。
它的主要优势之一是它已经是 AWS 生态系统的一部分,因此这抽象了许多管理和维护的操作任务,例如维护与数据库的连接,并且只需最少的设置即可在 AWS 环境中开始使用。
作为一个快速增长的 SaaS 运营,我们需要根据用户和客户的反馈快速发展,并将其嵌入到我们的产品中。应用程序设计中的许多更改对数据结构和架构有直接影响。
随着应用程序设计和架构的快速且经常发生重大变化,我们发现自己经常需要在 DynamoDB 中进行数据转换,当然,对于现有用户,在零停机时间的情况下实现这一点是当务之急。(在本文的上下文中,数据转换将指将数据从状态 A 修改为状态 B)。
数据转型的挑战
本着UFC的Brendon Moreno的精神:
也许不是今天,也许不是明天,也许不是下个月,但只有一件事是正确的,我保证有一天你需要进行数据转换。
然而,虽然数据转换是工程和数据工程中众所周知的常数,但无缝转换仍然是一个痛点和挑战。目前,在 DynamoDB 中,没有简单的方法以托管方式以编程方式执行此操作,这令人惊讶。
虽然有许多形式的数据转换,从替换现有项的主键到添加/删除属性,更新现有索引 - 列表还在继续(这些类型只是几个示例),但仍然没有简单的方法以托管和可重现的方式执行其中任何一个,而不使用可破解或一次性脚本。
用户表数据转换示例
下面,我们将深入探讨一个包含生产数据的数据转换过程的真实示例。
让我们以将“全名”字段拆分为其组件“名字”和“姓氏”为例。如下面的示例所示,数据聚合当前使用“全名”属性在表中写入名称。但是,假设我们要从全名转换,并将此字段拆分为名字和姓氏字段。
以前
Id | FullName |
---|---|
123 | Guy Br |
后
Id | FirstName | LastName |
---|---|---|
123 | Guy | Br |
看起来很容易,对吧?事实并非如此,要实现这个简单的更改,这些是需要在业务逻辑端执行的步骤,以便成功转换此数据。
- 扫描用户记录
- 从每条记录中提取“全名”属性
- 将“全名”属性拆分为新的名字和姓氏属性
- 保存新记录
- 清理“全名”属性
但是,让我们讨论一下在开始之前需要考虑的一些问题,例如 - 如何在不同的应用程序环境中运行和管理这些转换?特别是当访问每个环境并不真正被视为安全最佳实践时。此外,还需要考虑服务依赖关系。例如,当您有另一个服务依赖于此特定数据格式时,您应该怎么做?您的服务需要向后兼容,并且仍为依赖它的外部服务提供相同的接口。
当您有生产客户端时,在修改一行代码之前,您需要问自己的最关键问题之一可能是如何确保保持零停机时间?
为了避免任何停机时间,您需要计划的一些事情是围绕测试和验证。如何测试数据转换脚本?在生产数据上运行可靠的数据转换试运行有哪些良好做法?
在转换数据之前,需要考虑很多事项。
现在认为这通常是手动完成的。多么容易出错、乏味的过程!看起来我们需要一个细粒度的流程来防止错误并帮助我们管理所有这些步骤。
为了避免这种情况,我们明白我们需要定义一个流程来帮助我们应对上述挑战。
重写过程
图1:重写工艺流程图
首先,我们首先调整后端代码以将新的数据格式写入数据库,同时仍保留旧格式,首先编写 FullName、FirstName 和 LastName,为我们提供一些向后兼容性的保证。这将使我们能够在出现问题时恢复到以前的格式。
代码语言:javascript复制async function createUser(item) {
// FullName = 'Guy Br'
// 'Guy Br'.split(' ') === ['Guy', 'Br']
// Just for the example assume that the FullName has one space between first and last name
const [FirstName, LastName] = item.FullName.split(' ');
const newItemFormat = { ...item, FirstName, LastName };
return dynamodbClient.put({
TableName: 'Users',
Item: newItemFormat,
}).promise();
};