Rails:如何维护内存中进程内搜索索引?



我相信,如果我们保持一些嵌套哈希和数组的简单内存数据结构,我们可以在用户匹配和搜索功能中获得巨大的性能提升。这还不够复杂,无法使用像ElasticSearch这样的专用内存搜索,而且它也不是主要关于自由文本搜索。问题是如何保持更新?

所以我正在考虑在加载时保留一个线程,以每 5 分钟左右刷新和替换存储在类变量中的索引(只需一两秒钟即可完成(。问题是这感觉很卡顿。保留一整条线只是为了大部分时间坐在那里睡觉!在每个请求之后生成一个短暂的线程以检查是否该更新会更好吗?但我不希望这总是在错误的时刻与请求争夺 CPU。除了引入像事件机器这样的事件库之外,是否有更标准的轨道方法来做到这一点?

我知道,如果不由像 redis 这样的中介机构管理,通常不鼓励这种共享状态,但我对突变风险很满意,因为我将冻结此数据结构。此外,这个索引有数万个哈希键和文本项,所以我想为每个请求从 redis 反序列化将失去大部分好处。

这个问题有点矛盾;你同时要求一种 Railsy 的方式来解决问题,同时明确地忽略了所有常见的解决方案,并坚持认为你发明的计划是最合适的。

听起来你最终会付出很多努力来手工推出一个"不太复杂"的解决方案。我强烈建议不要这样做。然而:

选择定时到期还是事件过期在很大程度上取决于您是具有单个缓存还是多个独立缓存。如果它是一个进程内缓存,并且您有多个进程,则没有实际的方法可以按需触发过期,并且必须采用计时器方法。(我看不出事件机器在这里有什么关系。

Redis 确实是一个更适合这项工作的工具。使用 Redis 的要点是,您不需要反序列化所有内容:您在 Redis 中进行查找,然后仅反序列化匹配的部分。

由于您有多个进程和多个硬件:过时、不同步的数据是不可避免的。 发明自己的缓存解决方案(用于查找、过期、同步、刷新、预加载和防止它占用所有内存,...(将比仅仅使用已经存在的东西更复杂和容易出错(我想到 Redis,还有其他(。

我建议你看看 Rails 缓存和 Redis 存储。 虽然这将包括网络/反序列化,但我认为这是最Rails的方式,而且根据我的经验,已经足够快了。 如果您尝试过此操作并且仍然很慢,那么您可以尝试另一种解决方案。或者自己滚。但首先衡量,不要只是假设。

从那以后,我发现了吸盘拳,这是一种流行的宝石,由 sidekiq 的创建者强烈推荐。

我不会说这是完美的答案,因为它不是为长时间运行的线程设计的,当我可以在控制器回调上启动自己的短寿命线程时,可能会矫枉过正。

其他回答者提出了一个很好的观点,即对于多个进程,我需要一种同步方法。Redis符合要求,我会使用它。但是,如果我们遵循问题的前提,即结构太大而无法在每个请求上从 redis 反序列化,那么我们需要一些额外的进程内并发来维护共享反序列化缓存对象。

我理解为什么其他回答者对这样的策略感到不舒服,因为 ruby 真的不适合进程内并行性,所以它不是我们文化的重要组成部分(直到神话般的 ruby 3.0,我们只能在进程中进行并发(。这并不意味着它永远不是正确的答案。

Suckerpunch 以一种 railsy 的方式解决了后台处理的需求——很像 sidekiq——但在进程中,直接共享对象访问也是如此。

最新更新