2

我知道这个问题在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. _状态
    3. is_set_stopped
    4. _用户身份
  3. _data 字段大小从 5KB 到 1 MB 不等,具体取决于应用程序和用户的类型。
  4. 应用程序可以更新选择性属性。

我们认为的解决方案:

MySQL InnoDB

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

内存表中的 MySQL

这个解决方案的问题是

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

雷迪斯

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

  1. 它只支持一组数据类型。我只能在列表中存储字符串。我需要将字段存储为 JSON 或其他格式。
  2. 如果客户端想要更新特定属性,他们需要下载完整值,然后解析对象并重新推送到服务器。 可能是我错了有没有办法做到这一点?
  3. 无法根据值进行过滤。 可能是我错了有没有办法做到这一点?

TMPFS 文件系统上的 MySQL InnoDB

这看起来很有希望。但是不要不,它的扩展性足够类似于内存表中的 Redis 或 MySQL。

4

2 回答 2

4

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

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

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

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

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

例如:

  • 每个作业一个哈希对象。密钥是_unique_key。散列的字段应与关系表的列相对应。
  • 每个状态值一组
  • 2 套 is_set_stopped
  • 每个用户 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,瓶颈很可能是网络,尤其是在数据字段很大的情况下。我希望您将拥有比 1MB 更多的 5KB 工作。例如,1 MB 对象的 1000 次写入/秒表示 8 GBits/秒,可能超过您的网络可以承受的速度。Redis 和 MySQL 都是如此。

于 2012-10-13T11:59:24.350 回答
1

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

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

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

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

由于您似乎还有很多文本字段,因此另一个功能可能会有所帮助,postgresql 可以将文本搜索向量存储在一行上,您可以在其上添加索引并通过触发器使用您的所有行的连接内容更新它正在搜索。在对多列进行文本搜索时,与您可以在 mysql 中编写的任何方式相比,这将给您带来令人难以置信的性能提升。

无论您使用什么数据库

您说 _data 是 varchar[1024],但您说它包含 5K 到 1M 的数据?这实际上是一个blob吗?即使是长度错误,mysql 也不支持长度超过 65535 字节的 varchar 字段!我想它没有像其他行那样更新,将它分成两个表可能是明智的,一个带有静态数据,另一个带有动态数据,以最大程度地减少磁盘访问。

于 2012-10-13T12:25:06.487 回答