gpt4 book ai didi

database - 使用 git 存储库作为数据库后端

转载 作者:IT王子 更新时间:2023-10-29 01:23:05 29 4
gpt4 key购买 nike

我正在做一个处理结构化文档数据库的项目。我有一个类别树(约 1000 个类别,每个级别最多约 50 个类别),每个类别包含数千个(例如,约 10000 个)结构化文档。每个文档都是一些结构化形式的几千字节的数据(我更喜欢 YAML,但它也可能是 JSON 或 XML)。

该系统的用户执行几种类型的操作:

  • 通过 ID
  • 检索这些文档
  • 通过文档中的一些结构化属性搜索文档
  • 编辑文档(即添加/删除/重命名/merge );每个编辑操作都应记录为带有注释的事务
  • 查看特定文档的记录更改历史记录(包括查看谁、何时以及为什么更改了文档,获取较早版本 - 如果需要,可能会恢复到此版本)

  • 当然,传统的解决方案是使用某种文档数据库(例如 CouchDB 或 Mongo)来解决这个问题——然而,这个版本控制(历史)的东西让我产生了一个疯狂的想法——为什么我不应该使用 git存储库作为此应用程序的数据库后端?

    乍一看,它可以这样解决:
  • 类别 = 目录,文档 = 文件
  • 通过 ID 获取文档 => 更改目录 + 读取工作副本中的文件
  • 使用编辑注释编辑文档 => 由不同用户提交 + 存储提交消息
  • 历史 => 正常的 git 日志和旧事务的检索
  • 搜索 => 这是一个稍微棘手的部分,我想这需要定期将类别导出到关系数据库中,并为我们允许按
  • 搜索的列建立索引。

    这个解决方案还有其他常见的缺陷吗?有没有人尝试过实现这样的后端(即对于任何流行的框架 - RoR、node.js、Django、CakePHP)?此解决方案是否对性能或可靠性有任何可能的影响 - 即是否证明 git 会比传统数据库解决方案慢得多,或者是否存在任何可扩展性/可靠性陷阱?我认为推/pull 彼此存储库的此类服务器集群应该相当健壮和可靠。

    基本上,告诉我这个解决方案是否有效以及为什么它会或不会?

    最佳答案

    回答我自己的问题并不是最好的做法,但是,由于我最终放弃了这个想法,我想分享一下在我的案例中起作用的基本原理。我想强调的是,这个基本原理可能并不适用于所有情况,因此由架构师来决定。

    一般来说,我的问题遗漏的第一个要点是,我正在处理并行、并发工作的多用户系统,使用我的服务器和瘦客户端(即只是一个 Web 浏览器)。这样,我必须为所有人维护状态。有几种方法可以解决这个问题,但所有这些方法要么在资源上太难,要么太复杂而难以实现(因此,最初将所有困难的实现内容卸载到 git 的初衷有点不切实际):

  • “直率”方法:1 个用户 = 1 个状态 = 服务器为用户维护的存储库的 1 个完整工作副本。即使我们谈论的是具有 ~100K 用户的相当小的文档数据库(例如,100 秒 MiB),为所有用户维护完整的存储库克隆会使磁盘使用量飙升(即 100K 用户乘以 100MiB ~ 10 TiB) .更糟糕的是,每次克隆 100 MiB 存储库需要几秒钟的时间,即使以相当有效的方式完成(即不使用 git 和解包重新打包的东西),这是 Not Acceptable ,IMO。更糟糕的是——我们应用于主树的每个编辑都应该被 pull 到每个用户的存储库中,这就是 (1) 资源占用,(2) 在一般情况下可能会导致 Unresolved 编辑冲突。

    基本上,就光盘使用而言,它可能与O(编辑次数×数据×用户数)一样糟糕,并且这种光盘使用自动意味着相当高的CPU使用率。
  • “仅活跃用户”方法:仅为活跃用户维护工作副本。这样,您通常不会存储每个用户的完整 repo-clone,而是:
  • 当用户登录时,您克隆存储库。每个活跃用户需要几秒钟和大约 100 MiB 的磁盘空间。
  • 当用户继续在站点上工作时,他会使用给定的工作副本。
  • 当用户注销时,他的存储库克隆被复制回主存储库作为一个分支,因此只存储他的“未应用的更改”,如果有的话,这是相当节省空间的。

  • 因此,在这种情况下,磁盘使用量在 O(编辑次数 × 数据 × 活跃用户数)时达到峰值,通常比总用户数少约 100..1000 倍,但它使登录/注销更加复杂和缓慢,因为它涉及在每次登录时克隆每个用户的分支,并在注销或 session 到期时将这些更改 pull 回(这应该以事务方式完成 => 增加了另一层复杂性)。在绝对数字上,在我的情况下,它将 10 TiB 的磁盘使用量降低到 10..100 GiB,这可能是可以接受的,但是,再一次,我们现在谈论的是相当小的 100 MiB 数据库。
  • “稀疏结帐”方法:使每个活跃用户进行“稀疏结帐”而不是完整的 repo 克隆并没有多大帮助。它可能会节省大约 10 倍的磁盘空间使用量,但代价是在涉及历史的操作上更高的 CPU/磁盘负载,这会破坏目的。
  • “ worker 池”方法:我们可能会保留一个“ worker ”克隆池,随时可以使用,而不是每次都为活跃的人进行全面的克隆。这样,每次用户登录时,他都会占用一个“ worker ”,将他的分支从主仓库 pull 到那里,当他注销时,他释放了“ worker ”,这使得聪明的 git hard reset 再次成为一个主要的 repo 克隆,准备被另一个登录的用户使用。 对磁盘使用没有太大帮助(它仍然很高——每个活跃用户只有完整的克隆),但至少它使登录/退出更快,作为代价更复杂。

  • 也就是说,请注意,我特意计算了相当小的数据库和用户群的数量:100K 用户,1K 活跃用户,100 MiB 的总数据库 + 编辑历史,10 MiB 的工作副本。如果你看看更突出的众包项目,那里的数字要高得多:
    │              │ Users │ Active users │ DB+edits │ DB only │
    ├──────────────┼───────┼──────────────┼──────────┼─────────┤
    │ MusicBrainz │ 1.2M │ 1K/week │ 30 GiB │ 20 GiB │
    │ en.wikipedia │ 21.5M │ 133K/month │ 3 TiB │ 44 GiB │
    │ OSM │ 1.7M │ 21K/month │ 726 GiB │ 480 GiB │

    显然,对于如此大量的数据/事件,这种方法是完全 Not Acceptable 。

    通常,如果可以将 Web 浏览器用作“厚”客户端,即发出 git 操作并将几乎完整的结帐存储在客户端,而不是在服务器端,它就会起作用。

    我还遗漏了其他几点,但与第一点相比,它们并没有那么糟糕:
  • 对于普通的 ORM,例如 ActiveRecord、Hibernate、DataMapper、Tower 等,具有“厚”用户编辑状态的模式是有争议的。
  • 正如我所搜索的那样,从流行的框架中对 git 执行这种方法的现有免费代码库为零。
  • 至少有一种服务能够以某种方式有效地做到这一点——显然是 github — 但是,唉,他们的代码库是闭源的,我强烈怀疑他们内部没有使用普通的 git 服务器/repo 存储技术,即他们基本上实现了替代的“大数据”git。

  • 所以, 底线 :这是可能的,但对于大多数当前用例来说,它不会接近最佳解决方案。汇总您自己的文档编辑历史到 SQL 实现或尝试使用任何现有文档数据库可能是更好的选择。

    关于database - 使用 git 存储库作为数据库后端,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20151158/

    29 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com