您使用NoSQL数据存储时遇到了哪些可伸缩性问题?
NoSQL是指与关系数据库和ACID保证的历史相关的非关系数据存储。 stream行的开源NoSQL数据存储包括:
- Cassandra (表格,用Java编写,由思科,WebEx,Digg,Facebook,IBM,Mahalo,Rackspace,Reddit和Twitter使用)
- CouchDB (文档,用Erlang编写,由BBC和Engine Yard使用)
- Dynomite (键值,用Erlang编写,由Powerset使用)
- HBase (键值,用Java编写,Bing使用)
- Hypertable (表格,用C ++编写,百度使用)
- 凯 (键值,写在Erlang)
- MemcacheDB (键值,用C语言编写,由Reddit使用)
- MongoDB (文档,用C ++编写,由Electronic Arts,Github,NY Times和Sourceforge使用)
- Neo4j (graphics,用Java编写,由瑞典一些大学使用)
- Project Voldemort (由Java使用的由Java编写的键值)
- Redis (键值,用C语言编写,由Craigslist,Engine Yard和Github使用)
- Riak (键值,用Erlang编写,由Comcast和Mochi Media使用)
- Ringo (诺基亚使用的Erlang编写的键值)
- Scalaris (关键值,用Erlang编写,由OnScale使用)
- Terrastore (文档,用Java编写)
- ThruDB (文档,用C ++编写,由JunkDepot.com使用)
- 东京内阁/东京暴君 (密钥值,用C语言编写,由Mixi.jp(日本社交网站)使用)
我想知道您的SO读者已经使用数据存储和您使用的NoSQL数据存储解决了哪些具体问题。
问题:
- 您使用NoSQL数据存储来解决哪些可伸缩性问题?
- 您使用了哪些NoSQL数据存储?
- 在切换到NoSQL数据存储之前,您使用了哪个数据库?
我正在寻找第一手的经验,所以请不要回答,除非你有这个。
我已经将一个小的子项目从MySQL切换到CouchDB,以便能够处理负载。 结果是惊人的。
大约两年前,我们在http://www.ubuntuusers.de/ (这可能是德国最大的Linux社区网站)上发布了一个自编的软件。 该网站是用Python编写的,我们添加了一个WSGI中间件,它能够捕获所有exception,并将它们发送到另一个小型的MySQL网站。 这个小网站使用散列来确定不同的错误,并存储发生的次数和最后一次发生的次数。
不幸的是,在发布后不久,traceback-logger网站就没有回应。 我们的主站点的生产数据库有一些locking问题,几乎每个请求都抛出exception,还有一些其他的错误,我们在testing阶段没有探索过。 我们主站点的服务器集群,每秒钟被称为traceback-logger提交页面几次。 对于托pipe追踪logging器的小型服务器(它已经是一台仅用于开发目的的旧服务器)来说太过分了。
在这个时候,CouchDB非常stream行,所以我决定尝试一下,写一个小的跟踪logging器。 新的logging器只包含一个单独的python文件,它提供了一个包含sorting和过滤选项的错误列表以及一个提交页面。 在后台我开始了一个CouchDB进程。 新软件对所有请求的响应非常迅速,我们能够查看大量的自动错误报告。
有一件有趣的事情是,之前的解决scheme是在旧的专用服务器上运行的,而另一方面,新的基于CouchDB的站点只能运行在资源非常有限的共享xen实例上。 而且我甚至没有使用键值存储的实力来横向扩展。 CouchDB / Erlang OTP处理并发请求而不locking任何内容的能力已足以满足需求。
现在,快速编写的CouchDB-tracebacklogging器仍在运行,并且是探索主要网站上的错误的有用方法。 无论如何,大约每个月一次的数据库变得太大,CouchDB进程被杀死。 但是,然后,CouchDB的compact-db命令再次从几个GB减小到一些KB,并且数据库再次启动并运行(也许我应该考虑在那里添加一个cronjob … 0o)。
总之,对于这个子项目来说,CouchDB肯定是最好的select(或者至less比MySQL更好的select),并且它的工作很好。
我目前的项目实际上。
以规范化的结构存储18,000个对象:跨越8个不同的表格90,000行。 花了1分钟检索并将它们映射到我们的Java对象模型,这是正确的索引等。
使用轻量级文本表示将它们存储为键/值对:1个表,18,000行,3秒,全部检索并重构Java对象。
在商业方面:第一个select是不可行的。 第二个选项意味着我们的应用程
技术细节:针对SQL和NoSQL在MySQL上运行! 坚持与MySQL的良好的交易支持,性能和良好的logging,不损坏数据,扩展相当好,支持聚类等。
我们在MySQL中的数据模型现在只是关键字段(整数)和大的“值”字段:基本上只是一个大的TEXT字段。
我们没有和任何新的玩家(CouchDB,Cassandra,MongoDB等)一起去,因为虽然他们各自提供了很好的特性/性能,但是我们的环境总是有缺陷(比如缺less/不成熟的Java支持)。
(ab)使用MySQL的额外好处 – 我们模型中可以关联工作的位可以很容易地链接到我们的键/值存储数据。
更新:这里是我们如何表示文本内容的一个例子,而不是我们的实际业务领域(我们不用“产品”),因为我的老板射击我,但传达的想法,包括recursion方面(一个实体,在这里一个产品,“含有”其他)。 希望很清楚,在规范化的结构中,这可能是不less表格,例如,将产品join其范围的口味,其中包含其他产品等等。
Name=An Example Product Type=CategoryAProduct Colour=Blue Size=Large Flavours={nice,lovely,unpleasant,foul} Contains=[ Name=Product2 Type=CategoryBProduct Size=medium Flavours={yuck} ------ Name=Product3 Type=CategoryCProduct Size=Small Flavours={sublime} ]
托德霍夫的highscalability.com有很多NoSQL的覆盖面,包括一些案例研究。
商用Vertica列式DBMS可能适合您的目的(即使它支持SQL):与传统关系型数据库pipe理系统(DBMS)相比,用于分析查询的速度非常快。 参见Stonebraker等人最近的CACM论文将Vertica与map-reduce进行对比。
更新: Twitterselect了Cassandra ,包括HBase,Voldemort,MongoDB,MemcacheDB,Redis和HyperTable。
更新2:Rick Cattell刚刚在高性能数据存储中发布了几个NoSQL系统的比较。 而highscalability.com对瑞克的论文就是在这里 。
我们把部分数据从mysql移到了mongodb,而不是扩展性,更多的是因为它更适合文件和非表格数据。
在生产中,我们目前存储:
- 2.5万个文件(60GB)
- 其他1.3亿个“文件”(350GB)
每天的营业额约10GB。
数据库使用mongodb python api(pymongo)在两个节点(6x450GB sas raid10)上与apache / wsgi / python客户端进行“配对”configuration。 磁盘设置可能是矫枉过正,但多数民众赞成我们使用的MySQL。
除了pomongo线程池的一些问题和mongodb服务器的阻塞性质,这已经是一个很好的经验。
由于我没有任何第一手经验,所以我对你的粗体文本表示歉意,但是这组博客文章是解决CouchDB问题的一个很好的例子。
CouchDB:案例研究
从本质上讲, textme应用程序使用CouchDB来处理他们爆炸性的数据问题。 他们发现SQL太慢,无法处理大量的档案数据,并将其移至CouchDB。 这是一个很好的阅读,他讨论了解决CouchDB可以解决什么问题以及如何解决问题的整个过程。
我们已经将我们用来存储在Postgresql和Memcached中的一些数据移到了Redis中 。 关键值存储更适合存储分层对象数据。 与使用ORM将blob映射到RDBMS相比,您可以更快速地存储blob数据,而且开发时间和工作量要less得多。
我有一个开源的C#的redis客户端 ,可以让你存储和检索任何POCO对象与1行:
var customers = redis.Lists["customers"]; //Implements IList<Customer> customers.Add(new Customer { Name = "Mr Customer" });
主要价值商店也更容易“扩展”,因为您可以添加新的服务器,然后平均分配负载以包含新服务器。 重要的是,没有中央服务器会限制你的可扩展性。 (尽pipe你仍然需要一致的散列策略来分发你的请求)。
我认为Redis是一个类固化的“托pipe文本文件”,为多个客户端提供了快速,并发和primefaces访问,所以我现在使用的任何文本文件或embedded式数据库都使用Redis。 例如,为了获得所有服务的实时组合滚动错误日志(这对我们来说是众所周知的艰巨任务),现在只需要几行就可以完成,只需在Redis服务器端列表中预先填写错误即可然后修剪清单,只保留最后的1000个,例如:
var errors = redis.List["combined:errors"]; errors.Insert(0, new Error { Name = ex.GetType().Name, Message = ex.Message, StackTrace = ex.StackTrace}); redis.TrimList(errors, 1000);
我没有第一手的经验,但是我发现这个博客很有意思。
我发现将软件域对象(例如aSalesOrder,aCustomer …)映射到二维关系数据库(行和列)需要很多代码来保存/更新,然后再次从多个表中实例化一个域对象实例。 更不用说所有这些连接的性能打击,所有这些磁盘读取…只是查看/操作一个域对象,如销售订单或客户logging。
我们已经切换到对象数据库pipe理系统(ODBMS)。 它们超出了所列的noSQL系统的function。 GemStone / S(Smalltalk)就是这样一个例子。 还有其他ODBMS解决scheme具有多种语言的驱动程序。 一个关键的开发者的好处,你的类层次结构是自动的数据库模式,子类和所有。 只要使用面向对象的语言来使对象持久化到数据库。 ODBMS系统提供ACID级别的交易完整性,所以它也可以在金融系统中工作。
我不。 我想使用一个简单的免费的键值存储,我可以在这个过程中调用,但是这个东西在Windows平台上不存在。 现在我使用Sqlite,但我想使用东京内阁。 BerkeleyDB拥有许可证“问题”。
但是,如果你想使用Windows操作系统,你select的NoSQL数据库是有限的。 并不总是一个C#提供程序
我曾尝试MongoDB,它比Sqlite快40倍,所以也许我应该使用它。 但我仍然希望有一个简单的在线解决scheme。
我使用redis在机器上存储日志消息。 这很容易实现,非常有用。 Redis真的很有趣
我们用一个CouchDB文档数据库replace了一个postgres数据库,因为没有固定的模式对我们来说是一个强大的优势。 每个文档具有可变数目的索引,用于访问该文档。
我从MySQL(InnoDB)切换到cassandra的M2M系统,它基本上为每个设备存储时间序列的传感器。 每个数据按(device_id,date)和(device_id,type_of_sensor,date)进行索引。 MySQL版本包含2000万行。
MySQL的:
- 在主 – 主同步中进行设置。 几乎没有出现同步丢失的问题。 这是有压力,特别是在开始可能需要几个小时才能修复。
- 插入时间不是问题,但随着数据的增长, 查询需要越来越多的内存 。 问题是指标被认为是一个整体。 就我而言,我只是使用索引中非常薄的部分来加载内存(只有百分之几的设备经常受到监控,而且是最新的数据)。
- 这很难备份 。 Rsync无法在InnoDB大表文件上快速备份。
- 很快就很清楚, 无法更新繁重的表格模式 ,因为它花费了太多的时间(小时)。
- 导入数据需要几个小时 (即使索引最后完成)。 最好的救援计划是始终保留数据库的一些副本(数据文件+日志)。
- 从一家托pipe公司转移到另一家是非常重要的 。 复制必须非常小心地处理。
卡桑德拉:
- 比MySQL更容易安装。
- 需要大量的RAM。 一个2GB的实例无法在第一个版本中运行,现在它可以在一个1GB的实例上工作,但这不是个想法(太多的数据刷新)。 在我们的情况下给8GB就够了。
- 一旦你明白你如何组织你的数据,存储是很容易的。 请求有点复杂。 但是,一旦你绕过它,它真的很快(除非你真的想,否则你不能真的犯错误)。
- 如果以前的步骤是正确的,它是和保持超快。
- 数据似乎被组织起来备份。 每个新数据都被添加为新文件。 我个人,但这不是一件好事,每晚和每次关机前(通常是升级)刷新数据,以便恢复需要更less的时间,因为我们有更less的日志来读取。 它不会创build很多文件,它们是压缩的。
- 导入数据就像地狱一样快。 而你有更快的主机。 导出和导入千兆字节的数据已经不再是问题了。
- 没有一个模式是一件非常有趣的事情,因为你可以让你的数据发展,以满足你的需求。 这可能意味着在同一个列族中同时拥有不同版本的数据。
- 添加一个主机很容易(但速度不是很快),但是我没有在多数据中心设置上完成。
注意:我也使用了elasticsearch (基于lucene的面向文档),我认为它应该被视为NoSQL数据库。 它是分布式的,可靠的,而且通常很快(一些复杂的查询可能performance相当糟糕)。
过去我使用过Couchbase,遇到了重新平衡问题和其他问题。 目前我在几个生产项目中使用Redis。 我正在使用redislabs.com ,它是Redis的托pipe服务,负责缩放您的Redis集群。 我在http://thomasjaeger.wordpress.com上的博客上发布了一个关于对象持久性的video,演示了如何在提供者模型中使用Redis,以及如何将C#对象存储到Redis中。; 看一看。
我鼓励任何人阅读这个试用Couchbase,现在3.0已经出来了。 初学者有200多个新function。 Couchbase服务器的性能,可用性,可扩展性和易pipe理function使其成为一个非常灵活,高度可用的数据库。 pipe理UI是内置的,API会自动发现集群节点,因此不需要从应用程序到数据库的负载平衡器。 虽然我们目前还没有托pipe服务,但您可以在AWS,RedHat Gears,Cloudera,Rackspace,CloudStorage等Docker容器上运行couchbase。 关于重新平衡取决于你指的是什么,但是Couchbase在节点失败之后不能自动重新平衡,但是pipe理员可以为第一个节点的失败设置自动故障转移,并使用我们的API,你也可以访问在使它们处于活动状态或使用RestAPI之前,您可以使用副本vbuckets进行读取,您可以通过监视工具强制进行故障转移。 这是一个特例,但是可以做到。
除非节点完全脱机,永远不会再回来,或者一个新的节点准备自动平衡,否则我们往往不会重新平衡任何模式。 这里有几个指南可以帮助任何有兴趣看到性能最好的NoSQL数据库是什么的人。
- Couchbase Server 3.0
- pipe理指南
- REST API
- 开发者指南
最后,我还鼓励你查看N1QL的分布式查询:
- N1QL教程
- N1QL指南
感谢阅读,让我或其他人知道,如果你需要更多的帮助!
奥斯汀