极限分片:每个用户一个 SQLite 数据库

Posted

技术标签:

【中文标题】极限分片:每个用户一个 SQLite 数据库【英文标题】:Extreme Sharding: One SQLite Database Per User 【发布时间】:2010-09-12 20:04:55 【问题描述】:

我正在开发一个介于电子邮件服务和社交网络之间的网络应用程序。我觉得它在未来有很大的发展潜力,所以我担心可扩展性。

我决定为每个活跃用户创建一个单独的 SQLite 数据库:每个“分片”一个活跃用户,而不是使用一个集中式 mysql/InnoDB 数据库然后在那个时候对其进行分区。

这样备份数据库就像每天一次将每个用户的小型数据库文件复制到远程位置一样简单。

扩展就像添加额外的硬盘来存储新文件一样简单。

当应用程序超出单个服务器时,我可以使用 GlusterFS 在文件系统级别将服务器链接在一起并保持不变地运行应用程序,或者安装一个简单的 SQLite 代理系统,允许每个服务器操作相邻服务器中的 sqlite 文件。

并发问题将最小化,因为每个 HTTP 请求一次只会触及一个或两个数据库文件,超过数千个,而且 SQLite 无论如何只会阻塞读取。

我敢打赌,这种方法将使我的应用程序能够优雅地扩展并支持许多很酷且独特的功能。我赌错了吗?我错过了什么吗?

更新我决定采用一种不那么极端的解决方案,到目前为止效果很好。我正在使用固定数量的分片 - 准确地说是 256 个 sqlite 数据库。每个用户都通过一个简单的散列函数分配并绑定到一个随机分片。

我的应用程序的大多数功能只需要每个请求访问一个或两个分片,但有一个特别需要对 256 个分片中的 10 到 100 个不同的分片执行简单查询,具体取决于用户。测试表明,如果所有数据都缓存在 RAM 中,大约需要 0.02 秒或更短的时间。我想我可以忍受!

UPDATE 2.0 我将应用程序移植到 MySQL/InnoDB 并能够获得与常规请求大致相同的性能,但对于需要分片遍历的请求,innodb 快 4-5 倍.出于这个原因和其他原因,我放弃了这个架构,但我希望有人能在某个地方找到它的用途......谢谢。

【问题讨论】:

这是一篇相当老的帖子,您对 Gluster 的体验现在可能不太相关,但您最终是否尝试使用 sqlite 而不是 GlusterFS? 对于考虑研究这种架构的人,我建议查看开源 actordb ;每个参与者都是一个 sqlite 筒仓,筒仓使用 raft 协议分布和复制 - actordb.com 【参考方案1】:

http://freshmeat.net/projects/sphivedb

SPHiveDB 是一个用于 sqlite 数据库的服务器。它使用 JSON-RPC over HTTP 来公开网络接口以使用 SQLite 数据库。它支持将多个 SQLite 数据库合并到一个文件中。它还支持使用多个文件。它是为极端分片模式设计的——每个用户一个 SQLite 数据库。

【讨论】:

【参考方案2】:

我正在考虑使用相同的架构,因为我基本上想使用服务器端 SQLLIte 数据库作为客户端的备份和同步副本。我查询所有数据的想法是使用 Sphinx 进行全文搜索,并从所有数据的平面转储到 Scribe 运行 Hadoop 作业,然后将结果公开为 webservies。然而,这篇文章让我停下来思考,所以我希望人们继续用他们的意见作出回应。

【讨论】:

【参考方案3】:

每个用户拥有一个数据库当然可以很容易地恢复单个用户的数据,但正如@John 所说,架构更改需要一些工作。

不足以让它变得困难,但足以让它变得不平凡。

【讨论】:

【参考方案4】:

一个可能的问题是,为每个用户使用一个数据库将非常低效地使用磁盘空间和 RAM,并且随着用户群的增长,使用轻量级和快速数据库引擎的好处将完全丧失。

此问题的一个可能解决方案是创建“minishards”,其中可能包含 1024 个 SQLite 数据库,每个数据库最多可容纳 100 个用户。这将比每个用户的 DB 方法更有效,因为数据的打包效率更高。并且比 Innodb 数据库服务器方法更轻,因为我们使用的是 Sqlite。

并发性也会很好,但查询会不太优雅(shard_id yuckiness)。你怎么看?

【讨论】:

【参考方案5】:

如果您的数据如此容易分片,为什么不使用标准数据库引擎,并且如果您的规模足够大以至于数据库成为瓶颈,那么对数据库进行分片,在不同的实例中使用不同的用户?效果是一样的,但你没有使用几十个很小的数据库。

实际上,您可能至少有一些不属于任何单个用户的共享数据,并且您可能经常需要访问多个用户的数据。不过,这会导致任一系统出现问题。

【讨论】:

【参考方案6】:

如果您为每个用户创建一个单独的数据库,听起来您并没有建立关系......那么为什么要使用关系数据库呢?

【讨论】:

好问题。每个用户的数据库都有关系。此外,SQLite 允许您通过将一个数据库“附加”到另一个数据库来执行与多个数据库中的表的连接。【参考方案7】:

这将失败的地方是,如果您必须执行所谓的“分片遍历” - 即找出一群不同用户的所有数据。这种特定类型的“查询”必须以编程方式完成,依次询问每个 SQLite 数据库——并且很可能是您网站中最慢的方面。在任何将数据“分片”到单独数据库中的系统中,这都是一个常见问题。

如果所有数据对用户来说都是独立的,那么这应该可以很好地扩展 - 使其成为有效设计的关键是了解数据可能会被如何使用,以及数据是否来自一个人将与来自另一个(在您的上下文中)的数据进行交互。

您可能还需要注意文件系统资源 - SQLite 非常棒、很棒、速度快等 - 但是在使用“标准数据库”(即 MySQL、PostgreSQL 等)时,您确实会获得一些缓存和写入优势,因为他们是如何设计的。在您提出的设计中,您会错过其中的一些内容。

【讨论】:

这是一个很好的答案。另一个考虑因素是“规模经济”——将相似数据与相似数据保存在一起可以实现高效压缩、更好的磁盘使用(您可能在缓存注释中提到过)等等。 我面临着类似的情况。我正在使用 Db4o,而 Db4o 基本上将整个数据库加载到内存中进行查询。所以我认为每个用户拥有一个数据库并将数据库动态加载到内存中而不是一次加载一个巨大的数据库会更有效。关于这个问题的任何想法【参考方案8】:

在我看来,这就像一场维护噩梦。当所有这些数据库上的架构发生变化时会发生什么?

【讨论】:

架构更改可以动态推出。在启用使用该功能的新应用程序代码之前,可以在一周内一次向一个用户推出兼容的架构更改(例如添加一列)。在打开每个数据库文件时,可以推出不兼容的更改。没有停机时间。 对于 Fogbugz 来说似乎不是问题,每个客户端都有自己的 SQL Server 数据库... 如果您的架构迁移是自动处理的,这不是问题。手工操作很棘手;但是您可能希望对生产数据库进行手动更新以避免诱惑。

以上是关于极限分片:每个用户一个 SQLite 数据库的主要内容,如果未能解决你的问题,请参考以下文章

SQLite:如何使用复合键从单个表中选择“每个用户的最新记录”?

如何将机器添加到 SQL 数据库中已经分片的数据?

Firebase 或 SQLite [关闭]

分布式任务elastic-job分片获取fetchdata时候怎么控制数据不重复

SQLite 是不是适合网站使用

Hadoop知识体系完整笔记(未完)