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

时间:2018-08-14 11:38:00

标签: ruby-on-rails ruby multithreading

我相信,如果我们在内存中保留一些嵌套哈希和数组的简单数据结构,那么我们的用户匹配和搜索功能将大大提高性能。这还不够复杂,无法使用像ElasticSearch这样的专用内存搜索,也不是主要针对自由文本搜索。问题是如何保持更新?

因此,我正在考虑在加载时保留一个线程,以每隔5分钟左右刷新和替换存储在类变量中的该索引(这样做只需要一两秒钟)。麻烦的是,这让人感觉很古板。保留整个线程,以便只坐在那里睡觉!可能最好在每个请求之后仅生成一个短寿命的线程,以检查是否需要更新?但是我不希望这总是在错误的时刻为请求争取CPU。没有引入像事件机器这样的事件库,是否有更标准的讽刺方法?

我了解到,这种共享状态通常不建议由Redis等中介机构进行管理,但我对突变风险非常满意,因为我将冻结此数据结构。另外,该索引具有数万个哈希键和文本项,因此我认为针对每个请求从redis反序列化将使很多好处失去作用。

3 个答案:

答案 0 :(得分:0)

这个问题有点矛盾;您同时要求一种Railsy的方式来解决您的问题,同时明确拒绝所有常见的解决方案,并坚持您的发明计划最合适。

听起来您将不得不付出很多努力来手动推出“不太复杂”的解决方案。我强烈建议您反对。但是:

是否选择定时或事件到期将在很大程度上取决于您是单个缓存还是多个独立缓存。如果它是一个进程内高速缓存,并且您有多个进程,则没有实际方法可以按需触发过期,因此必须采用计时器方法。 (我在这里看不到事件机器的任何意义。)

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

答案 1 :(得分:0)

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

我建议您在Redis商店中查看Rails caching。 虽然这将包括网络/反序列化,但我会说这是最Rails的方式,以我的经验,它足够快。 如果您尝试过此方法,但仍然很慢,那么可以尝试其他解决方案。或自己动手。但是第一步,不要只是假设。

答案 2 :(得分:0)

此后,我发现了sucker punch,这是sidekiq的创建者strongly recommended所流行的宝石。

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

其他答复者指出,通过多个进程,我将需要一种同步方法。 Redis符合要求,我会使用它。但是,如果我们遵循这样的前提:结构太大而无法在每个请求上从Redis反序列化,那么我们需要一些额外的进程内并发来维护共享的反序列化缓存对象。

我了解为什么其他回答者不喜欢ruby这样的策略,因为它实际上并不适合于进程内并行性,因此它不是我们文化的重要组成部分(直到神话般的ruby 3.0,我们才可以在进程中进行并发)。这并不意味着它永远不是正确的答案。

Suckerpunch以一种混乱的方式解决了后台处理的需求-就像sidekiq一样-但是进行中,因此可以直接共享对象访问。