内存中的关系数据库



我知道这个问题在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. _user_id
  3. _数据字段大小根据应用程序和用户的类型从5KB到1MB不等
  4. 应用程序可以更新选择性属性

我们认为的解决方案:

MySQL InnoDB

我认为MySQL由于对高读写的要求而无法扩展。

MySQL内存表

这个解决方案的问题是

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

Redis

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

  1. 它只支持一组let’s数据类型。我只能在列表中存储字符串。我需要将字段存储为JSON或其他格式
  2. 若客户端想要更新特定的属性,他们需要下载完整的值,然后对对象进行解析并重新发布到服务器。也许我错了,有办法吗
  3. 无法根据值进行筛选。也许我错了,有办法吗

TMPFS文件系统上的MySQL InnoDB

这看起来很有希望。但不要不,在内存表中,它的规模会足够类似于Redis或MySQL。

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

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

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

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

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

例如:

  • 每个作业一个哈希对象。密钥是_unique_key。散列的字段应该与关系表的列相对应
  • 每个状态值一组
  • is_set_stopped 2套
  • 每个userid值一组

对于每个作业插入,您需要通过管道传输以下命令:

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,瓶颈可能是网络,尤其是在数据字段很大的情况下。我希望你能有更多5KB的工作,而不是1MB的工作。例如,1 MB对象的1000次写入/秒表示8 GB/秒,可能超过您的网络所能承受的速度。Redis和MySQL都是如此。

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

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

或者,如果你喜欢的话,你也可以在tmpfs上使用它,并使用流式复制到磁盘上的数据库来进行硬拷贝。

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

由于您似乎也有很多文本字段,另一个功能可能会有所帮助,postgresql可以在一行上存储一个文本搜索向量,您可以在该向量上添加一个索引,并通过触发器更新它,其中包含您正在搜索的所有行的连接内容。与在mysql中编写文本搜索的任何方式相比,在多列上进行文本搜索时,这将极大地提高性能。

无论使用何种数据库

你说_data是varchar[1024],但你说它包含5K到1M的数据?这真的是一个斑点吗?即使是长度错误,mysql也不支持长度超过65535字节的varchar字段!我想它没有其他行更新得那么多,明智的做法是将其分为两个表,一个表包含静态数据,另一个表具有动态数据,以最大限度地减少磁盘访问。

相关内容

  • 没有找到相关文章

最新更新