事件通知与对象 Lambda

Event Notifications vs Object Lambda

企业正在努力收集、存储和管理数据湖仓、分析和 AI/ML 所需的大量数据。为了简化这个过程,我们几乎每周都在为 MinIO 添加新功能。我们经常谈论的两个功能是 MinIO 的 事件通知对象 Lambda。我们甚至在一段时间前写了一篇博客文章,介绍了如何使用 使用 Kafka 的桶事件通知 来异步自动化 ETL 管道,以及最近如何使用 用于合规性的对象 Lambda 从对象中擦除敏感数据。

在写这些博客的时候,我们意识到为什么有两个不同的功能做着几乎相同的事情?或者它们不是?希腊字母 Lambda 和闪电符号有什么区别?请阅读上面提到的两篇博客文章,以便我们稍后能快速了解它们背后的原理。

事件通知

MinIO 桶通知允许管理员将通知发送到外部服务(例如 Kafka 或 RabbitMQ),以便在发生特定对象或桶事件时进行通知。MinIO 支持与 Amazon S3 事件通知 类似的 桶级和对象级 S3 事件。

这些事件可以是以下操作:

  • 向桶添加对象
  • 访问桶中的对象
  • 删除和移除对象
  • 创建和删除桶

以及其他许多操作。您可以在 文档 中找到支持的事件类型的完整列表。

此外,MinIO 支持两种消息传递模式:异步和同步。

在异步传递中,MinIO 会将事件发送到配置的远程目标,并且不会等待响应,然后继续处理下一个事件。异步桶通知优先考虑发送事件,但存在以下风险:如果远程目标在传输或处理期间出现瞬时问题,则某些事件可能会丢失。

在同步传递中,MinIO 会将事件发送到配置的远程目标,然后等待远程目标确认成功接收,再继续处理下一个事件。同步桶通知优先考虑事件传递,但存在事件发送速度较慢和队列填充的风险。

事件通知非常适合以下场景:

  • 需要等待大型 CSV 文件开始处理的 ETL 作业。
  • 将对象分散到多个应用程序进行处理。
  • 在不同时间处理工作负载,例如 cron 作业。

还有一点需要注意的是,通常可以使用任何编程语言来处理基础设施不同部分中的数据。我们将在对象 Lambda 中看到,您只能用 Python 编写代码。

对象 Lambda

说到对象 Lambda,让我们定义一下什么是“Lambda”。忘掉所有您知道的关于 Lambda 的专业术语,回到最基本的概念。想想在 Python 中什么是 Lambda。它是一个可以重复使用的小型匿名函数,就这么简单。

例如,打开一个 Python REPL 并运行以下代码:

upper = lambda string: string.upper()
print(upper("dataone"))

这将打印 DATAONE。现在如果您有 'datatwo',那么无需重新定义 string.upper(),您只需使用 upper()

print(upper("datatwo"))

您能猜到这将打印什么吗?

没错,您猜对了,是 DATATWO。因此,您拥有一个可重复使用的函数,而无需使用 def 关键字来定义它。但请注意,不要让这些函数过于复杂或包含多行代码,因为它们通常应该是一行表达式,易于阅读和理解。如果要执行的操作超过一行代码,那么请使用带有 def 的常规函数。这种方法的优势在于,如果您想更改输出,无需在所有脚本中更改代码,只需更新原始 Lambda 定义的位置即可。

现在将相同的概念应用于对象。假设您在一个大型 CSV 文件中存储了敏感数据,例如信用卡信息。在请求该对象之前,您需要确保屏蔽完整的信用卡号,只显示最后 4 位数字。虽然您可以使用事件通知来实现这一点,但需要考虑以下几个因素:

  • 您是否有多个进程重复使用相同的代码,并且希望有一个单一的事实来源?
  • 您是否希望为消息服务器集群建立全新的基础设施,并在维护该基础设施时增加额外的技术债务?可以将此视为使用 Python 中的 def 函数。您真的需要它吗?

如果您只是修改现有的对象(在对象存储术语中称为“转换”),则只需用 Python 编写一个函数,当您的应用程序请求特定对象时,它只需引用该对象的名称和 Lambda 函数的名称,以便根据 Python 代码片段对该对象进行转换。与 Python Lambda 不同,您可以使用多行 Python 代码来定义您的 Lambda,但前提是该函数只能返回一个响应。

因此,对于信用卡数据,使用几行 Python 代码片段来修改数据,然后再返回给最终用户更有意义。

使用哪个?

现在我们已经了解了这两个功能的区别及其背后的原理,我们可以使用对象 Lambda 来调整图像大小而不是 Kafka,还是可以使用 Kafka 中的事件通知来屏蔽敏感数据?让我们大声思考一下各种用例。

首先,让我们谈谈 图像调整大小博客。如果我们要在 Lambda 中进行图像调整大小,则可以在 Lambda 的 Python 函数中使用相同的 Python 代码块。如果调整大小的目标只是检索较大图像的缩略图版本,例如,当我们想查看一个快速副本时,可能需要进行一次性的调整大小。但是,如果您正在使用 CDN,并且希望将这些缩略图分发到全球各地,以便缩略图加载速度更快,然后在用户请求完整版本时,它将额外花费一两秒。在这种情况下,如果每次请求缩略图时都使用 Lambda 函数,那么网站上的最终用户将不得不等待额外的图像调整大小时间,然后再显示出来。这完全违背了 CDN 的目的。在这种情况下,您应该定期运行 ETL 作业来调整图像大小,并使其可供 CDN 使用,以便用户体验接近实时。

现在,让我们看一下 我们屏蔽敏感数据的博客。如果我们要使用事件通知来完成这项工作,当然可以,但需要考虑以下注意事项:

  • 您真的想建立一个全新的基础设施,仅仅是为了修改现有对象中的某些数据吗?坦白地说,作为一名实际的 DevOps 工程师,这似乎有点过头了。
  • 如果像屏蔽数据这样重要的功能至关重要,那么您需要尽快在请求处理流程中屏蔽数据。
    • 例如,您可以使用 ETL 来清理数据并创建一个全新的对象,所有应用程序都可以访问该对象。但是,如果数据大小为数 TB,那么您将浪费宝贵的存储空间,仅仅是为了屏蔽一个数据项,如果要屏蔽其他信息,比如人们的姓氏,是否还需要为此创建单独的数据集?您会发现,这种情况很快就会变得难以管理。
    • 您也可以在检索数据后在应用程序级别清理这些数据,但是如何才能确保所有应用程序都能正确清理数据?每个应用程序都可以用自己的方式编写函数,这些函数略有不同,这将使调试成为一场噩梦。

在考虑所有选项后,最合乎逻辑的方法似乎是介于两者之间——小巧、轻便、灵活——能够快速删除敏感数据,无论哪个应用程序请求数据。此外,根据删除的类型,您可以应用不同的 lambda 函数,根据应用程序需求和监管要求来删除恰到好处的数量的数据。这可以一箭双雕,带来以下好处

  • 首先,您确保没有重复数据占用宝贵的空间并造成不必要的混乱。
  • 其次,您可以确保每个人都使用相同的标准方法来转换数据,无论团队、应用程序或组织。
  • 奖励:如果必须更改代码库中的逻辑,您就不必进行一个项目来“查找此代码被修改的地方”。相反,您只需要在一个地方修改代码库,所有应用程序将在下次调用 lambda 函数时获得更新版本的转换后的数据。

如您所见,虽然两者之间存在细微差别和一些重叠,但重要的是要规划针对您的特定用例和应用程序的设计。我们的 SUBNET 上的工程师每天都在帮助我们的客户做出类似的基于架构的决策!如果您想让您的存储基础设施获得超强性能,或对事件通知或对象 lambda 有任何问题,请务必在 Slack 上联系我们!