使数据库与文件系统[PHP/Postgresql/Linux]上的图片保持同步


Keeping database in sync with pictures on filesystem [PHP/Postgresql/Linux]

BACKSTORY

我维护并正在重新设计几个基于PHP的网络应用程序,有一个主题我还没有找到一个优雅的解决方案,所以我正在寻找一些输入,这可能会让我找到更好的方法。

当前状态

我的一些应用程序允许用户除了存储大量数据外,还存储图像。所有的数据最终都在PostgreSQL集群中,但是出于性能和可维护性的考虑,我选择不将图像本身存储在数据库中。图像的元数据存储在数据库中(如原始文件名、宽度/高度等),一旦数据库事务成功,我就会将文件系统上的图像移动到图像目录中(存储为.jpg)

问题

所有这些功能都很好,但由于应用程序被大量使用,多人同时使用,并且在互联网上使用,而且PHP的错误/异常处理并不是所有场景中最可靠的,我偶尔会担心无法将图像(在文件系统上)存储在数据库的事务中(因为它发生在文件系统中)。我还担心,因为如果文件系统上的图像文件被损坏/更改/删除,数据库的记录将无法正确更新(没有引用完整性)。

解决方案

到目前为止,我想到的是:

选项A)将实际图像(不仅仅是元数据,而是整个二进制文件)存储在数据库中。——我不喜欢这个,因为目前数据库虽然很复杂,但仍然很小(不超过60MB或以上)。相关的映像总共有很多GB,所以这将大大增加我安装PostgreSQL的占地面积。此外,它还会使我的数据库备份和复制场景复杂化。

选项B)保留当前的设计(文件系统上的图像,postgres中的数据),并在使用数据的每一点都尝试在应用程序级别考虑损坏的数据。——它使应用程序更加复杂和容易出错。

选项C)我发现了一个名为Flourishlib的PHP ORM框架,它包含一个模拟文件系统事务的文件系统类(基本上,如果你调用$file->rename(),它会检查这是否可能,但在你提交事务之前不会真正重命名)——这是我迄今为止找到的最好的解决方案,然而,我已经在使用另一个ORM框架(Propel),对于这种规模的项目,我更喜欢它,所以我需要两个功能重叠的框架。

Sooo

所以,我想这里的许多其他人以前也会遇到同样的"问题",我相信有些人想出了一些我还没有想到的解决方案。感谢任何指点、建议或批评。

在我看来,这是两个独立的问题。

第一个问题:你是如何保持完整的,你已经解决了。我唯一会考虑的是在数据库事务期间执行文件系统操作,如果出现问题则回滚。这里的权衡是性能,因为文件系统操作相当慢,但没有那么慢;)你可以试试…

第二个问题:如何在外部文件操作后保持完整性。在这里,我建议使用phpPHPINotify来查看inotofy。它允许您实现一个观察者模式,以便在文件系统上发生更改时得到通知。

以下是我对选项D:的建议

  1. 将实际图像及其元数据和哈希存储在数据库中(整个二进制)(请参阅图像哈希的用途是什么?)。

  2. 构建一个微服务,负责将二进制映像从数据库转换到文件系统或CDN。通过比较哈希,这个微服务可以检查图像的完整性。它甚至可以负责存储以前的版本和日志。一旦事务完成,就可以删除数据库中的二进制数据,以保持其轻量级。

  3. 设计一个消息队列架构(例如AmazonSQS)来启动和管理这个微服务。它将独立于您的主应用程序运行,并准备好处理故障、数据库维护、错误等。

希望这能有所帮助,即使是在8年后。

您总是可以从高级下载页面获取Flourish的子集。只需选择fFile,它就会选择依赖项。不幸的是,随着时间的推移,自动依赖性检测变得有点不准确(因此它将包括fEmail,这确实是可选的),但您可以删除它,留下一些文件系统类和一些核心/异常内容。