在本文中,我们讨论了索引如何在启动时加载以及对传入查询和搜索实例管理的影响。
在较旧的 Sphinx 版本中,如果设置了 preopen 选项,索引将被预读并加载到内存中。在此期间,守护进程将拒绝接受任何传入连接。如果对于小索引来说这不是大问题,因为它们加载得很快。但对于需要加载数十或甚至数百 GB 的巨大索引来说,这确实是一个问题,因为完成加载可能需要几分钟或更长时间。
在 Sphinx 2.3 中,这种情况发生了变化,因为索引文件是 内存映射(使用 mmap),而不是简单地读取并加载到内存中。使用 mmap,守护进程的一个影子线程而不是主线程首先为每个页面读取一个字节,然后继续读取其余数据,慢慢将所有内容带入 RAM,同时也允许访问数据。简而言之,这是一种懒加载索引文件的方式。
这样,守护进程可以在启动后立即接受连接。如果查询需要访问一些尚未加载到内存中的随机数据,它将从磁盘读取。这也意味着查询的执行速度可能比平常慢(取决于存储性能),但至少守护进程可以提供结果。更重要的是,一旦索引的文件加载完成,守护进程可以为其提供“全速”服务,即使其他索引仍在加载中。
虽然这对大多数用户来说是个好消息,但对某些用户来说,“懒惰”加载可能不是最佳选择。例如,使用简单策略(随机或轮询)的负载均衡器不会测量响应时间,将在守护进程启动后立即添加重启的实例。由于查询将需要直接从磁盘读取,实例将提供比平常更高或更高得多的响应时间,这是不希望发生的。相反,如果可能的话,最好在守护进程完成加载索引后再将实例添加到集群中。
为了解决这种情况,自 2.3 以来存在一个 searchd 选项,但不幸的是,直到最近才有文档说明:'--force-preread'。使用此选项,守护进程仍然会 mmap 索引文件,但预读是一个阻塞操作(就像旧版本一样),searchd 在所有内容加载到内存中之前不会响应。