【发布时间】:2014-02-09 23:16:51
【问题描述】:
我有一个集群应用程序,它分为一个控制器和一堆工人。控制器在专用主机上运行,工作人员通过网络打电话并接手工作,到目前为止一切正常。 (基本上是 zeromq 手册中的“divide-and-conquer pipeline”,带有特定于工作的皱纹。现在这并不重要。)
控制器的核心数据结构是伪 C++ 中的unordered_map<string, queue<string>>(控制器实际上是用 Python 实现的,但我对用其他东西重写它的可能性持开放态度)。队列中的字符串定义作业,映射的键是作业的分类。控制器播种了一组作业;当工作人员启动时,控制器从其中一个队列中删除一个字符串并将其作为工作人员的第一项工作分发。工作人员可能会在运行期间崩溃,在这种情况下,作业会被放回适当的队列中(有一个未完成作业的辅助表)。如果它成功完成了作业,它会发回一个新的作业字符串列表,控制器将把它分类到适当的队列中。然后它将从某个队列中拉出另一个字符串并将其作为下一个作业发送给工作人员;通常,但并非总是如此,它会为该工作人员选择与上一个作业相同的队列。
现在,问题。此数据结构目前完全位于主内存中,这对于小规模测试运行来说很好,但在全规模时,它会独自吃掉控制器上所有可用的 RAM。控制器还有其他几项任务要完成,所以这不好。
我应该采取什么方法?到目前为止,我已经考虑过:
a) 将其转换为主要在磁盘上的数据结构。它可以在一定程度上缓存在 RAM 中以提高效率,但作业需要数十秒才能完成,所以如果它没有那么效率也没关系,
b) 使用关系数据库 - 例如SQLite,(但 SQL 模式非常不适合 AFAICT),
c) 使用具有持久性支持的 NoSQL 数据库,例如Redis(数据结构映射微不足道,但这看起来仍然非常以 RAM 为中心,让我确信内存占用问题实际上会消失)
具体数字:对于全面运行,散列中将有 1 到 1000 万个键,每个队列中的条目少于 100 个。字符串长度变化很大,但不太可能超过 250 个字节。因此,假设的(不可能的)零开销数据结构将需要 234 – 237 字节的存储空间。
【问题讨论】:
-
虽然这个问题很有趣,但您可能需要重新表述它。如您所知,要求图书馆的问题并不适合 SO!此外,一些数字会很有用。例如,哈希表中有多少项?
-
@Shahbaz 我知道这样的问题是不鼓励的,但在这种情况下,我无法找到更好的场所或更好的方式来构建问题。扩展它(“我应该对这个数据结构做些什么,以便它更适合内存和/或主要存在于磁盘上?”也许)只会使它更多成为一个见仁见智的问题,我认为。我会在正文中添加一些具体的数字。
-
@zack 稍作编辑以避免偏离主题的讨论。
-
使所有内容都固定大小,超大哈希表和 mmap() 每次请求都会花费 2-3 个页面错误。参考的局部性会很糟糕(除非在少数热点上进行大量操作)。只需计算一下:你能承受几百 GB 的 VM 占用空间吗?另外:你想要持久性,即使在崩溃之后?
-
@zack 你能澄清一下你需要在多少时间(例如每小时)内处理多少工作?你为什么一开始就把所有的东西都放在内存中?
标签: data-structures language-agnostic scalability