首页  >  文章  >  后端开发  >  维护开源备份工具:见解等

维护开源备份工具:见解等

WBOY
WBOY原创
2024-07-18 09:37:10990浏览

备份策略似乎是一个已解决的问题,但系统管理员经常遇到如何正确备份数据、将数据存储在何处以及如何跨不同软件环境标准化备份过程的问题。 2011 年,我们开发了自定义备份脚本,可以有效地处理客户 Web 项目的备份。这些脚本多年来为我们提供了良好的服务,根据需要将备份存储在我们的存储和外部存储库中。然而,随着我们的软件生态系统的发展和多样化,我们的脚本出现了不足,缺乏对 Redis 和 MySQL/PostgreSQL 等新技术的支持。脚本也变得很麻烦,除了电子邮件警报之外没有任何监控系统。

我们曾经紧凑的脚本演变成一个复杂且难以管理的系统。为不同的客户更新这些脚本变得具有挑战性,特别是当他们使用自定义版本时。到去年初,我们意识到我们需要一个更现代的解决方案。

在这篇文章中,我们将解释我们在开发nxs-backup时遇到的所有困难,并分享我们的经验和挑战。您还可以在您的项目中测试该工具并分享您的经验,我们非常有兴趣听取您的意见。现在,让我们开始吧!

我们列出了新系统的要求:

  • 最常用软件的备份数据:(文件:离散和增量;MySQL;PostgreSQL;MongoDB;Redis);
  • 将备份存储在流行的存储库中:(FTP;SSH;SMB;NFS;WebDAV;S3);
  • 在备份过程中出现问题时接收警报;
  • 拥有统一的配置文件,集中管理备份;
  • 通过连接外部模块添加对新软件的支持;
  • 指定收集转储的额外选项;
  • 能够使用标准工具恢复备份;
  • 易于初始配置。 所有这些要求都是根据我们大约 5 年前的需求列出的。不幸的是,并非所有人都被释放。

我们研究了在创建第一个版本的 nxs-backup 之前就已经存在的开源解决方案。但他们都有自己的缺陷。例如,Bacula 对我们来说过载了不必要的功能,由于大量的手动工作(例如,用于编写/搜索数据库备份的脚本),初始配置是相当费力的工作,并且恢复副本需要使用特殊的实用程序等等

毫不奇怪,我们在考虑重写我们的工具时遇到了同样的问题。四年内发生一些变化并且在线出现新工具的可能性并不高,但仍然如此。

我们研究了一些以前没有考虑过的新工具。但是,正如前面所讨论的,这些也不适合我们。因为他们没有完全满足我们的要求。

我们最终得出两个重要结论:

  1. 现有的解决方案都不完全适合我们;
  2. 看来我们已经有足够的经验和疯狂来第一次编写我们的解决方案了。我们基本上可以再次这样做。 这就是我们所做的。

在探索新版本之前,让我们先看看我们之前有什么以及为什么它对我们来说还不够。

旧版本支持MySQL、PostgreSQL、Redis、MongoDB等数据库,文件离散增量复制,多种远程存储(S3;SMB;NFS;FTP;SSH;WebDAV),并具有备份轮换、日志记录等功能、电子邮件通知和外部模块。

现在,更多关于我们关心的事情。

在任何 Linux 上运行二进制文件而无需重新启动源文件

随着时间的推移,我们使用的系统列表已经大大增加。现在我们服务的项目使用非标准 deb 和 rpm 兼容发行版,例如 Arch、Suse、Alt 等。

最近的系统在运行 nxs-backup 时遇到困难,因为我们只收集了 deb 和 rpm 软件包,并且支持的系统版本列表有限。我们在某个地方重新提取了整个包,在某个地方只是二进制文件,在某个地方我们只需要运行源代码。

由于需要使用源代码,使用旧版本对于工程师来说非常不方便。更不用说这种模式下的安装和更新需要更多时间。您不必每小时设置 10 台服务器,而只需在一台服务器上花费一小时。

我们很早就知道,如果您拥有一个没有系统依赖项的二进制文件,可以在任何发行版上运行,并且不会遇到不同版本的库和系统架构差异的问题,那么情况会好得多。我们希望这个工具是一样的。

使用 nxs-backup 最小化 docker 镜像并在配置文件中支持 ENV

最近,很多项目都在容器化环境中运行。这些项目也需要备份,我们在容器中运行 nxs-backup。对于容器化环境,最小化图像大小并能够使用环境变量非常重要。

旧版本没有提供使用环境变量的机会。主要问题是密码必须直接存储在配置中。因此,您必须将整个配置放入一个变量中,而不是一组仅包含密码的变量。编辑大型环境变量需要工程师更加集中精力,并且使故障排除变得更加困难。

此外,在使用旧版本时,我们必须使用已经很大的 Debian 映像,其中我们需要添加多个库和应用程序以进行正确的备份。

即使使用图像的精简版本,我们也得到了约 250Mb 的最小大小,这对于一个小型实用程序来说是相当大的。在某些情况下,这会影响收集的启动过程,因为图像被拉到节点上的时间较长。我们想要获得不大于 50 MB 的图像。

无需保险丝即可使用远程存储

容器环境的另一个问题是使用fuse挂载远程存储。

当您在主机上运行备份时,这仍然是可以接受的:您已经安装了正确的软件包并在内核中启用了熔断器,现在它可以工作了。

当你需要在容器中添加保险丝时,事情就会变得有趣。如果不升级直接访问主机系统核心的权限,问题就没有解决,而且安全级别明显下降。

这需要协调,并不是所有客户都同意削弱安全策略。这就是为什么我们不得不制定大量我们甚至不想回忆的解决方法。此外,附加层增加了故障概率,并且需要对已安装资源的状态进行额外监视。直接使用他们的 API 来使用远程存储会更安全、更稳定。

监控状态并不仅向电子邮件发送通知

如今,团队在日常工作中使用电子邮件的情况越来越少。这是可以理解的,因为在群聊或群组通话中讨论问题要快得多。 Telegram、Slack、Mattermost、MS Teams 和其他类似产品由此广泛传播。

我们还有一个机器人,它会发送各种警报并通知我们。当然,我们希望看到像 Telegram 这样的工作空间中的备份崩溃的报告,而不是电子邮件以及数百封其他电子邮件。顺便说一句,一些客户还希望在其 Slack 或其他通讯工具中查看有关故障的信息。

此外,您很希望能够实时跟踪状态并查看工作的详细信息。为此,您需要更改应用程序的格式,将其变成恶魔。

性能不足

另一个急性疼痛是在某些情况下表现不足。

其中一个客户端有一个几乎 1 TB 的巨大文件转储,并且所有这些文件都是小文件 - 文本、图片等。我们正在收集这些内容的增量副本,并遇到以下问题 - 每年的副本需要三天。是的,好吧,旧版本无法在不到一天的时间内消化掉这一卷。

鉴于目前的情况,我们实际上无法恢复特定日期的数据,这是我们根本不喜欢的。

最初,我们使用 Python 实现了备份解决方案,因为它简单且灵活。然而,随着需求的增长,基于 Python 的解决方案变得不够用了。经过充分讨论,我们决定用 Go 重写系统,原因如下:

  1. 编译和依赖:Go 的 AOT 编译器生成通用的、无依赖的二进制文件,简化了跨不同系统的部署;
  2. 性能:Go 固有的多线程能力保证了更好的性能;
  3. 团队专业知识:我们拥有 Go 经验丰富的开发人员,而不是 Python 经验丰富的开发人员。

寻找解决方案

所有上述问题都或多或少地给IT部门带来了相当明显的痛苦,导致他们将宝贵的时间花费在固然重要的事情上,但这些成本本来是可以避免的。此外,在某些情况下,会给企业主带来一定的风险——某一天没有数据的概率虽然极低,但并非为零。我们拒绝接受现状。

Nxs-备份3.0

我们的工作成果是 nxs-backup v 3.0 的新版本,最近更新到了 v3.8.0
新版本的主要特点:

  • 实现所有存储设施和所有类型备份的相应接口。作业和存储在开始时初始化,而不是在工作运行时初始化;
  • 通过 API 使用远程存储。为此,我们使用各种库;
  • 在配置中使用环境变量,这要归功于我们在项目中使用的 go-nxs-appctx 迷你应用程序框架;
  • 通过钩子发送日志事件。您可以配置不同的级别并仅接收所需级别的错误或事件;
  • 不仅指定备份的时间段,还指定具体的备份次数;
  • 备份现在只需在从 2.6 内核开始的 Linux 上运行即可。这使得使用非标准系统变得更加容易,并且构建 Docker 镜像的速度也更快。镜像本身减少至 23 MB(包含额外的 MySQL 和 SQL 客户端);
  • 能够以 Prometheus 兼容的格式收集、导出和保存不同的指标。
  • 限制本地磁盘速率和远程存储的资源消耗。

我们尝试保留大部分配置和应用程序逻辑,但存在一些更改。都与上一版本缺陷的优化和修正有关。

例如,我们将远程存储库的连接参数放入基本配置中,这样我们就不会每次为不同类型的备份指定它们。

下面是备份基本配置的示例。它包含通知通道、远程存储、日志记录和作业列表等常规设置。这是邮件通知的基本主要配置,我们强烈建议使用电子邮件通知作为默认方法。如果您需要更多功能,可以查看文档中的参考。

server_name: wp-server
project_name: My Best Project

loglevel: info

notifications:
  mail:
    enabled: true
    smtp_server: smtp.gmail.com
    smtp_port: 465
    smtp_user: j.doe@gmail.com
    smtp_password: some5Tr0n9P@s5worD
    recipients:
      - j.doe@gmail.com
      - a.smith@mail.io
  webhooks: []
storage_connects: []
jobs: []
include_jobs_configs: [ "conf.d/*.conf" ]

关于陷阱的几句话

我们预计会面临某些挑战。否则的话就是愚蠢的。但有两个问题造成了最强烈的伤害。

Image description

内存泄漏或非最佳算法

即使在以前版本的 nxs-backup 中,我们也使用自己的文件归档实现。该解决方案的逻辑是尽量避免使用外部工具来创建备份,而使用文件是最简单的步骤。

在实践中,该解决方案被证明是可行的,尽管从测试中可以看出,对于大量文件来说并不是特别有效。当时我们把它写成 Python 的细节,并希望当我们切换到 Go 时看到显着的差异。

当我们最终进行新版本的负载测试时,我们得到了令人失望的结果。性能没有任何提升,内存消耗甚至比以前更高。我们正在寻找解决方案。阅读了很多关于这个主题的文章和研究,但他们都说使用“filepath.Walk”和“filepath.WalkDir”是最好的选择。这些方法的性能只会随着语言新版本的发布而提高。

为了优化内存消耗,我们甚至在创建增量副本时犯了错误。顺便说一句,损坏的选项实际上更有效。由于显而易见的原因,我们没有使用它们。

最终,一切都取决于要处理的文件数量。我们测试了1000万。垃圾收集器似乎无法清除这么多生成的变量。

最终,意识到我们可能会在这里浪费太多时间,我们决定放弃我们的实现,转而采用经过时间考验且真正有效的解决方案 - GNU tar。

当我们想出更有效的解决方案来处理数千万个文件时,我们可能会回到自我实现的想法。

如此不同的ftp

使用 ftp 时出现了另一个问题。事实证明,不同的服务器对于相同的请求表现不同。

对于同一个请求,你要么得到正常的答案,要么得到与你的请求无关的错误,或者在你期望的时候没有得到错误,这是一个非常严重的问题.

因此,我们不得不放弃使用库“prasad83/goftp”,转而使用更简单的“jlaffaye/ftp”,因为第一个库无法与 Selectel 服务器正常工作。错误是在连接时,第一个尝试获取工作目录中的文件列表,并得到了上级目录访问权限的错误。使用“jlaffaye/ftp”就不存在这样的问题,因为它更简单,并且不会向服务器发送任何请求。

下一个问题是没有请求时断开连接。并非所有服务器都这样做,但有些服务器确实如此。所以我们必须在每次请求之前检查连接器是否脱落并重新连接。

最重要的是从服务器获取文件的问题,或者说清楚,尝试获取不存在的文件。有些服务器在尝试访问此类文件时会出错,其他服务器会返回一个甚至可以读取的有效 io.Reader 接口对象,只有你得到一个空字节。

所有这些情况都是凭经验发现的,必须自己处理。

结论

最重要的是,我们修复了旧版本的问题,影响工程师工作并给业务带来一定风险的事情。

我们还有上个版本中未实现的“愿望”,例如:

  • 备份加密;
  • 使用 nxs-backup 工具从备份恢复;
  • 用于管理作业列表及其设置的 Web 界面。

此列表现已添加新列表:

  • 自己的作业调度程序。使用自定义设置代替系统克隆;
  • 新的备份类型(Clickhouse、Elastic、lvm 等)。

当然,我们很乐意了解社区的意见。您还看到哪些其他发展机会?您会添加哪些选项?

您可以在其网站上阅读文档并了解有关 nxs-backup 的更多信息,如果您想留下任何问题,我们的网站上还有故障排除部分。

我们已经在 Telegram 频道中对即将推出的功能进行了民意调查。关注我们,参与此类活动,为工具的发展做出贡献!

下次再见!

以上是维护开源备份工具:见解等的详细内容。更多信息请关注PHP中文网其他相关文章!

声明:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn