我知道这个问题在stackoverflow中被多次询问。 我发布这个问题,以找出什么是我的devise的最佳select。 我有我的工作细节以下架构。
_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
我们在这张桌子上做了什么样的操作:
我们认为解决scheme
MySQL的InnoDB
由于高读写要求,我认为MySQL不会有足够的扩展性。
MySQL在内存表
这个解决scheme的问题在于
Redis看起来是个不错的select。 但是我认为我的表对于键值caching服务器来说并不好。
MySQL InnoDB在TMPFS文件系统上
这看起来有希望。 但是,在内存表中,它不会像Redis或MySQL那样足够大。
在这个问题中,您将原始性能(即效率)与可伸缩性混为一谈。 他们是不同的概念。
在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时,瓶颈将可能是网络,特别是在数据字段很大的情况下。 我希望你会有比1MB的工作多5KB的工作。 例如,1000 MB / s的1 MB对象代表8 GBits / s,可能比您的网络所能承受的更多。 Redis和MySQL都是如此。
我建议postgresql,它比mysql更有能力(有更多的功能和更好的支持复杂的查询和数据类型),并有很多调优选项。
如果你给postgresql足够的内存,并调整参数,它会缓存所有内存。
另外,你也可以在tmpfs上使用它,如果这是你的首选项,并使用流式复制到硬盘上的磁盘数据库。
流式复制异步,接收和fsync有3种操作模式。 如果您使用第一个异步服务器,则不必等待复制服务器上的磁盘同步,因此使用tmpfs时,任何更新都将非常快速。
由于您似乎还有很多文本字段,所以另一个功能可能会有所帮助,postgresql可以将一个文本搜索向量存储在一行中,并且您可以添加一个索引并通过触发器更新它,并将所有行的连接内容正在搜索。 当你在多列上进行文本搜索的时候,这会给你一个难以置信的提升,而不是任何你可能用mysql编写的方式。
无论您使用的数据库如何 :
你声明_data是varchar [1024],但你说它包含5K到1M的数据? 这实际上是一个blob? 即使是长度错误,mysql也不支持长度超过65535字节的varchar字段! 我想这不会像其他行那样更新,将它分成两个表格是很明智的,一个是静态数据,另一个是动态数据,以最小化磁盘访问。