我知道在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
我们在这张桌子上做了什么操作:
我们认为解决方案:
MySQL InnoDB
我认为由于要求高读写,MySQL不够扩展。
MySQL内存表
此解决方案的问题在于
Redis
Redis看起来是个不错的选择。但我认为我的表对键值缓存服务器不好。
TMPFS文件系统上的MySQL InnoDB
这看起来很有希望。但是不要没有它会在内存表中扩展到类似于Redis或MySQL的程度。
答案 0 :(得分:4)
在这个问题中,您将原始性能(即效率)与可伸缩性混淆。它们是不同的概念。
在InnoDB和内存引擎之间,InnoDB可能是最具扩展性的。 InnoDB支持多版本的并发控制,有很多优化来处理争用,因此它将比内存引擎更好地处理并发访问。即使在某些I / O限制情况下它可能会更慢。
Redis是一个单线程服务器。所有操作都是序列化的。它具有零可扩展性。这并不意味着效率低下。相反,它可能会支持MySQL的更多连接(由于其基于epoll的事件循环)和更多的流量(由于其非常有效的无锁实现和内存数据结构)。
要回答你的问题,我会尝试使用InnoDB进行MySQL。如果配置正确(没有同步提交,足够的缓存缓冲等等),它可以维持良好的吞吐量。而不是在tmpfs上运行它,我会考虑SSD硬件。
现在,如果你更喜欢使用Redis(它不是btw的关系存储),你当然可以这样做。无需系统地序列化/反序列化您的数据。如果您可以预测所有访问路径并找到适应的数据结构,那么过滤确实是可能的。
例如:
对于每个作业插入,您需要传递以下命令:
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字段!我认为它没有像其他行那样更新,将它分成两个表是明智的,一个表用静态数据,另一个用动态数据表示最小化磁盘访问。