在内存关系数据库中

时间:2012-10-13 10:47:51

标签: mysql linux redis tmpfs

我知道在stackoverflow中多次询问此问题。 我发布这个问题是为了找出什么是我设计的最佳选择。 我的工作细节有以下架构。

_unique_key        varchar(256) NULL
_job_handle        varchar(256) NULL
_data              varchar(1024) NULL
_user_id           int(11) NULL
_server_ip         varchar(39) NULL
_app_version       varchar(256) NULL
_state             int(11) NULL
_is_set_stopped    bool

我们在这张桌子上做了什么操作:

  1. 对于每个作业,我们将在此表上进行一次更新和10次选择查询。所以我们需要高频读写。
  2. 有许多应用程序通过对以下内容进行操作来操作此表:
    1. _unique_key
    2. _STATE
    3. is_set_stopped
    4. _user_id
  3. _data字段大小根据应用程序和用户的类型从5KB到1 MB不等。
  4. 应用程序可以更新选择性属性。
  5. 我们认为解决方案:

    MySQL InnoDB

    我认为由于要求高读写,MySQL不够扩展。

    MySQL内存表

    此解决方案的问题在于

    1. 它不支持动态字段大小。 MEMORY表使用固定长度的行存储格式。诸如VARCHAR的可变长度类型使用固定长度存储。来源http://dev.mysql.com/doc/refman/5.0/en/memory-storage-engine.html
    2. 选择....更新它将锁定整个表。我不知道会不会有问题。
    3. Redis

      Redis看起来是个不错的选择。但我认为我的表对键值缓存服务器不好。

      1. 它只支持非常让我们设置的数据类型。我只能在列表中存储字符串。我需要将字段存储为JSON或其他格式。
      2. 如果客户想要更新特定属性,则需要下载完整值,然后解析对象并重新启动到服务器。 可能我错了是否有办法做到这一点?
      3. 无法根据值进行过滤。 可能我错了是否有办法做到这一点?
      4. TMPFS文件系统上的MySQL InnoDB

        这看起来很有希望。但是不要没有它会在内存表中扩展到类似于Redis或MySQL的程度。

2 个答案:

答案 0 :(得分:4)

在这个问题中,您将原始性能(即效率)与可伸缩性混淆。它们是不同的概念。

在InnoDB和内存引擎之间,InnoDB可能是最具扩展性的。 InnoDB支持多版本的并发控制,有很多优化来处理争用,因此它将比内存引擎更好地处理并发访问。即使在某些I / O限制情况下它可能会更慢。

Redis是一个单线程服务器。所有操作都是序列化的。它具有零可扩展性。这并不意味着效率低下。相反,它可能会支持MySQL的更多连接(由于其基于epoll的事件循环)和更多的流量(由于其非常有效的无锁实现和内存数据结构)。

要回答你的问题,我会尝试使用InnoDB进行MySQL。如果配置正确(没有同步提交,足够的缓存缓冲等等),它可以维持良好的吞吐量。而不是在tmpfs上运行它,我会考虑SSD硬件。

现在,如果你更喜欢使用Redis(它不是​​btw的关系存储),你当然可以这样做。无需系统地序列化/反序列化您的数据。如果您可以预测所有访问路径并找到适应的数据结构,那么过滤确实是可能的。

例如:

  • 每个作业一个哈希对象。关键是_unique_key。哈希的字段应对应于关系表的列。
  • 每个州值一套
  • 为is_set_stopped设置了2套
  • 每个用户ID值一组

对于每个作业插入,您需要传递以下命令:

HMSET job:AAA job_handle BBB data CCC user_id DDD server_ip EEE app_version FFF state GGG is_set_stopped HHH
SADD state:GGG AAA
SADD is_set_stopped:HHH AAA
SADD user_id:DDD AAA

如果您维护相应的设置,则可以轻松更新任何字段。

您可以通过交叉集来执行过滤查询。例如:

SINTER is_set_stopped:HHH state:GGG

使用Redis,瓶颈可能是网络,特别是如果数据字段很大。我希望你的工作量比5MB的工作量多1MB。例如,1000 MB / s的1 MB对象代表8 GBits / s,可能比您的网络可以支持的多。这对Redis和MySQL都是如此。

答案 1 :(得分:1)

我建议postgresql,它比mysql更有能力(具有更多功能和更好的复杂查询和数据类型支持),并且有很多调优选项。

如果给postgresql足够的内存并调整参数,它会将所有内容缓存在内存中。

或者你可以在tmpfs上使用它,如果这是你的偏好并使用流式复制到磁盘数据库以获得硬拷贝。

流式复制有异步,接收和fsync三种操作模式。如果使用第一个async,则不必等待复制服务器上的磁盘同步,因此使用tmpfs的任何更新都会非常快。

由于你似乎也有很多文本字段,另一个功能可能会有所帮助,postgresql可以在一行上存储一个textsearch矢量,你可以在其上添加一个索引,并通过一个触发器更新它,并连接所有内容您正在搜索的行。在对多列进行文本搜索时,这将为您提供令人难以置信的性能提升,而不是您可以在mysql中编写的任何方式。

无论您使用哪种数据库

你说_data是varchar [1024],但是你说它包含5K到1M的数据?这实际上是一团吗?即使长度错误,mysql也不支持长度超过65535字节的varchar字段!我认为它没有像其他行那样更新,将它分成两个表是明智的,一个表用静态数据,另一个用动态数据表示最小化磁盘访问。

相关问题