我正在开发一个介于电子邮件服务和社交网络之间的网络应用程序。我觉得它有可能在未来发展得非常大,所以我很关心可扩展性。
我决定为每个事件用户创建一个单独的 SQLite 数据库,而不是使用一个集中式 MySQL/InnoDB 数据库然后对其进行分区:每个“分片”一个事件用户。
这样备份数据库就像每天将每个用户的小数据库文件复制到远程位置一样简单。
扩展就像添加额外的硬盘来存储新文件一样简单。
当应用程序超出单个服务器时,我可以使用 GlusterFS 在文件系统级别将服务器链接在一起,并在不变的情况下运行应用程序,或者安装一个简单的 SQLite 代理系统,允许每个服务器操作相邻服务器中的 sqlite 文件。
并发问题将是最小的,因为每个 HTTP 请求一次只会触及一两个数据库文件,数千个,而且 SQLite 无论如何只会阻塞读取。
我敢打赌,这种方法将使我的应用程序能够优雅地扩展并支持许多很酷且独特的功能。我赌错了吗?我错过了什么吗?
更新 我决定采用一种不那么极端的解决方案,目前为止运行良好。我使用的是固定数量的分片——准确地说是 256 个 sqlite 数据库。每个用户都通过一个简单的哈希函数分配并绑定(bind)到一个随机分片。
我的应用程序的大多数功能只需要访问每个请求的一个或两个分片,但有一个特别需要在 256 个分片中的 10 到 100 个不同分片上执行简单查询,具体取决于用户。测试表明,如果所有数据都缓存在 RAM 中,则大约需要 0.02 秒或更短时间。我想我可以接受!
UPDATE 2.0 我将应用程序移植到 MySQL/InnoDB,并且能够为常规请求获得大致相同的性能,但对于需要分片遍历的请求,innodb 快 4-5 倍.出于这个原因,以及其他原因,我放弃了这个架构,但我希望有人能在某个地方找到它的用途……谢谢。
最佳答案
这会失败的地方是,如果您必须执行所谓的“分片遍历”——即找出一组不同用户的所有数据。这种特殊类型的“查询”必须以编程方式完成,依次询问每个 SQLite 数据库——这很可能是您站点中最慢的方面。在数据已“分片”到单独的数据库中的任何系统中,这都是一个常见问题。
如果所有数据对用户来说都是独立的,那么这应该可以很好地扩展 - 使其成为有效设计的关键是了解数据可能如何使用以及数据是否来自一个人将与来自另一个(在您的上下文中)的数据进行交互。
您可能还需要注意文件系统资源——SQLite 很棒、很棒、速度很快等等——但是当使用“标准数据库”(即 MySQL、PostgreSQL 等)时,您确实可以获得一些缓存和写入的好处,因为他们是如何设计的。在您提议的设计中,您会错过其中的一些内容。
关于database - 极端分片 : One SQLite Database Per User,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/128919/
为了防止在迁移到生产站点期间出现数据库事务错误,我们遵循了https://github.com/LendingHome/zero_downtime_migrations中列出的建议。(具体由https://robots.thoughtbot.com/how-to-create-postgres-indexes-concurrently-in概述),但在特别大的表上创建索引期间,即使是索引创建的“并发”方法也会锁定表并导致该表上的任何ActiveRecord创建或更新导致各自的事务失败有PG::InFailedSqlTransaction异常。下面是我们运行Rails4.2(使用Acti
我正在使用最新版本的Capistrano和我的Rails4应用程序。运行capdpeloy时。我得到了很多输出,包括这次失败:DEBUG[04b6e226]Running/usr/bin/env[-f/var/www/skateboxes/releases/20131022135522/config/database.yml]on162.243.33.179DEBUG[04b6e226]Command:[-f/var/www/skateboxes/releases/20131022135522/config/database.yml]DEBUG[04b6e226]Finishedin0
我想创建一个RailsController,从网上下载一系列jpg文件,并直接将它们作为二进制文件写入数据库(我不是要上传表格)关于如何做到这一点的任何线索?谢谢编辑:这是我已经使用attachment-fugem编写的一些代码:http=Net::HTTP.new('awebsite',443)http.use_ssl=truehttp.verify_mode=OpenSSL::SSL::VERIFY_NONEhttp.start(){|http|req=Net::HTTP::Get.new("image.jpg")req.basic_authlogin,passwordrespon
我们刚刚将虚拟机升级到我认为相同的ruby配置(通过RVM...Ruby1.9.2、Rails3.0.7、DataMapper1.1.0)。最大的区别是我们从MySQL5.0升级到5.1。出于某种原因,在我们的旧VM上运行的完全相同的代码/database.yml现在在我们的新VM尝试连接到数据库时失败了。问题是这个YAML:mysql_defaults:&mysql_defaultsadapter:mysqlencoding:UTF-8username:userpassword:passhost:localhostdevelopment:正在扩展到:"mysql_defaults
我正在开发一个通过表单发送数据的Rails应用程序。我想在表单发送之后,但在它被处理之前修改表单的一些“参数”。我现在拥有的{"commit"=>"Create","authenticity_token"=>"0000000000000000000000000""page"=>{"body"=>"TEST","link_attributes"=>[{"action"=>"Foo"},{"action"=>"Bar"},{"action"=>"Test"},{"action"=>"Blah"}]}}我想要什么{"commit"=>"Create","authenticity_token"
当我尝试使用capistrano部署我的应用程序时,我会收到此错误:failed:"sh-c'cp/var/www/my_app/releases/20120313115055/config/database.staging.yml/var/www/my_app/releases/20120313115055/config/database.yml'"onIP_ADDR我的database.yml即空的,database.staging.yml:production:adapter:mysql2encoding:utf8reconnect:falsedatabase:my_dbpool
我最近一直在研究NoSql选项。我的场景如下:我们从位于世界各地偏远地区的定制硬件收集和存储数据。我们每15分钟记录一次来自每个站点的数据。我们最终希望每1分钟移动一次。每条记录有20到200个测量值。一旦设置好硬件,每次都会记录和报告相同的测量值。我们面临的最大问题是我们从每个项目中获得了一组不同的衡量标准。我们测量大约50-100种不同的测量类型,但是任何项目都可以有任意数量的每种测量类型。没有可以容纳数据的预设列集。因此,当我们在系统上设置和配置项目时,我们创建并构建了每个项目数据表,其中包含所需的确切列。我们提供工具来帮助分析数据。这通常包括更多的计算和数据聚合,其中一些我们也
我从GitHub存储库克隆了一个应用程序文件夹,在捆绑安装gems之后,我尝试使用rakedb:setup和rakedb:migrate命令,但都没有用,这是我的错误消息:**arun997@promanager:~/workspace(master)$rakedb:setuprequire'rails/all'...2.470sBundler.require...7.590srakeaborted!Cannotload`Rails.application.database_configuration`:Couldnotloaddatabaseconfiguration.Nosuchf
我有一个修改数据库中记录的后台进程。模型使用如下方式连接到数据库:dbconfig=YAML::load(File.open('database.yml'))ActiveRecord::Base.establish_connection(dbconfig["development"])classClcar所有模型类的顶部都有这些行。我同意这是一种糟糕的做法。有没有更好的方法来连接到模型类?如何将连接传递给模型?我希望能够在不同的环境(比如“生产”)中运行我的后台进程。我该如何实现? 最佳答案 我会在您的后台进程开始时设置一次连接。一
我正在尝试使用db/seed.rb文件和rakedb:seed命令将一些数据播种到我正在开发的Rails3应用程序中。我播种的数据涉及一个名为Meeting的数据库表,该表具有三列:字符串标题、日期时间开始日期、日期时间结束日期。我尝试插入的日期时间采用“mm/dd/yyyyhh:mm”格式——例如。“01/02/200313:23”=2003年1月2日下午1:23。但是,DateTime.parse()始终会出现“无效日期”错误——因为它试图以“dd/mm/yyyy”格式解析日期。根据我的谷歌搜索,我被引导相信在解析DateTime对象时,编译器会查看传入的字符串并进行一些仓促的模式