2009-11-04 27 views
8

我们向客户提供的很多LOB应用程序都具有市场/促销性质(抽奖,事件注册等)。大多数应用程序虽然非常简单,但对数据库要求很高。例如,想象一个“注册”类型的网站作为超级碗期间播出的商业广告的支持,例如(是的,我们有几个)。用于写入沉重的Web应用程序的数据库设计

虽然我们已经非常善于优化我们的网络应用程序代码,但尽管应用程序相对简单,数据库仍然是个问题。流程通常是这样的:

  1. 阅读从数据库检测现有记录
  2. 写入数据库,如果记录是新

在许多情况下,这是所有的数据访问我们的应用程序需要执行。但是,鉴于它是应用程序的唯一目的,因此这个简单的过程要大大优化是非常重要的。

就这个问题而言,我们有一台服务器为数据文件运行raid 5磁盘阵列,为日志运行另一个raid 5阵列。此时,操作系统是Windows 2003标准32位,服务器有4 GB的内存。一些应用程序使用SQL 2005标准,而另一些使用MySQL 5.1。我是非常了解某些操作系统和硬件优化在这里是可能的,但我希望首先从软件方面解决我的需求。广泛的性能分析告诉我们,磁盘IO一般是主要瓶颈。尽管大多数读取都是唯一的,并且返回的数据非常少(通常只有一点说明记录是否存在),但我知道缓存并不会有多大帮助,所以我正在考虑跳到内存数据库领域作为实际数据库的写缓存层。鉴于我们大部分的高流量流量本质上是零星的,并且不能持续几个小时,这看起来很合适。另外,在大多数情况下,服务器崩溃导致的几分钟数据可能会丢失。

在最简单的形式,我会修改一个典型的注册应用程序来执行以下操作:

  1. 查询磁盘数据库和内存数据库现有记录
  2. 如果没有,写数据到内存数据库和返回
  3. 定时冲洗内存数据库到磁盘DB

我的问题是:什么是我对这个中间同我的选择mory数据库?我已经尝试过使用内存中的哈希表,数据表等,但我正在寻找其他选项,甚至为完全不同的方法提供建议。

+0

请提供记录的数量和大小的数量级,可能在特定活动之前和之后(即包括活动期间额外记录计数收集的粗略想法)区分计数 – mjv 2009-11-04 16:52:03

+0

在典型的应用程序支持通过电视广告或电台等高交通量的司机,我们可能会在现场后的15-30分钟内看到大约20万次登记尝试。这大部分通常在现场后的3-5分钟内完成,因此存在争用问题。纯粹的卷不是问题,这是问题的并发性。我们有史以来最大的单一短期应用程序数据库在2个月内接近1000万条记录,其中大部分流量来自电视广告和电子邮件活动。 – Chris 2009-11-04 16:58:37

+2

另一种选择是将UPSERT逻辑封装在存储过程中,这将为您节省数据库行程(及相关开销)。 – 2009-11-04 17:02:26

回答

4

拥抱新概念“一切都是信息,数据库是备份”。当你有东西要存储时,创建一条消息并使用XMPP将它发送到黑盒(如eJabberD)。让黑匣子按照自己的时间表更新数据库。这就是Twitter如何工作的网站。

在这个幻灯片请看: http://www.slideshare.net/kellan/beyond-rest

1

SQLite有一个in memory操作模式。如果你的页面点击处理程序后面有一个持久的服务器进程,这将工作。

否则,基于常规文件的数据库可能会被愚弄,将其文件写入内存文件系统,如tmpfs

6

如果您不需要知道是否有实时存在的记录(即,记录到达这里非常重要,但不需要向用户报告它是新的还是现有的),您可以用一种允许非常快的写入时间的方式来构建数据库,内存数据库,如果服务器关闭或工作进程重新启动,会带来很多潜在的问题。

在数据库中为涉及此写入繁重流程的每个表创建两个表。一张表应该是你的“实时”表,并且应该尽可能地进行写优化(即没有索引并且除非移动到读取表时不会读取)。您的其他表格应该是您的读取优化表格 - 适用于任何报告考虑因素等。

每当您写入您的实时表格时,忽略与记录是新的还是现有的记录有关的任何内容除了尽可能快地将数据输入表格并从数据库中取出。设置一个计划作业,将活动表中的记录移到读取优化表中,并担心在那里匹配现有记录。理想情况下,这将在非高峰时段完成,否则您可能需要考虑第三个临时表,以便随时在活动表上不存在争用。

+0

如果数据来自live表应该可以相对快速地阅读,那该怎么办? (即不能等到预定的工作将新数据传输到读取表) – kilonet 2014-11-12 19:27:38

0

我不知道你提到的数据库,但是如果数据库的内容(或者至少是重要的表)适合内存,oracle能够将它固定在缓存中,所以它的行为基本上像在内存数据库中。

我还会检查数据库的隔离级别设置。如果你能够放松那些你可能会减少锁定。

最后考虑删除唯一约束,或在高峰时间禁用它们。

1

在我看来,您应该能够使用具有用户可用缓存的RDBMS来适应您的工作负载。我用一个简单的C++可调用RDBMS和普通硬件每秒看到10000个索引记录的顺序。这包括提交到磁盘。此外,由于您可能只查看记录中的一个小字段,因此请查找一个列式数据库 - 将数据存储在列中。如果你只对一个领域感兴趣,那么整行阅读都没有意义。

1

优化写入数据库架构,而不是读,正如许多人所说,是你的第一个停靠点,但我猜你去过那里已经

前调查内存数据库,您可能希望看看一些可用的ORM,特别是NHibernate。

NHibernate将一些数据保存在内存中,并允许您控制数据更新何时从内存“刷新”并与数据库同步。

您可能会觉得值得一看。

2

没有编程相关,但肯定会有帮助:获得一些较新的固态硬盘。

是的,它们对于尺寸而言是昂贵的,但由于磁盘IO是瓶颈,只需将某些SSD换成当前的HDD即可大大提高性能。

1

编辑:严格专注于磁盘I/O ...

  1. 撕裂了许多不必要的指标,您可以。指数不是免费的 - 空间或时间。
  2. 找出您不需要的任何特殊触发器或约束条件。
  3. 找出并非绝对关键的任何实体关系/关系完整性操作符。
  4. 如果您当前的DBMS支持它,请将事务表分成多个磁盘(例如循环)。考虑添加更多独立于彼此的数据库服务器(即,不涉及复制);要做到这一点,您需要一个调度程序来决定哪个服务器将接受该事务以及合并事务的方案/独立流程。

最小化数据库逻辑和横向添加服务器的数量(与最尖端的服务器技术相对)基本上是ebay采取的方法。

2

这里有一个奇怪的想法:不要使用数据库最初的捕获。设计两个或三个尖叫快速的索引文件,其格式不需要经常更改。捕获这些文件中的数据。

编写一些适当触发的软件,将捕获的数据复制到数据库中,但不会延迟交互式用户。标记复制数据以防止重复的副本,并回收文件中的空间。

现在,您可以设计数据库,以便在多种用途之间共享数据,而不是跟上捕获过程。毕竟,共享数据是数据库真正发光的地方。

+0

这是谷歌Dapper分布式跟踪工具工作原理的基本思想。应用程序写入lcoal文件,然后收集器将这些文件更加懒惰地复制到BigTable。 – fumanchu 2010-04-29 22:47:52

相关问题