并发、锁定和版本控制¶
并发性¶
这个 FileIndex
对象是“无状态的”,应该可以在线程之间共享。
A Reader
对象(位于 Searcher
对象)包装打开的文件,通常单个方法依赖于一致的文件光标位置(例如,它们有两个 file.read()
如果另一个线程在两个read调用之间移动光标,就会发生坏事情)。您应该在代码中每个线程使用一个读卡器/搜索器。
读卡器/搜索者倾向于缓存信息(例如用于排序的字段缓存),因此如果您可以在多个搜索请求之间共享一个信息,这将是一个巨大的性能胜利。
锁定¶
一次只能有一个线程/进程写入索引。当您打开一个编写器时,它会锁定索引。如果试图在另一个线程/进程中打开同一索引上的写入程序,它将引发 whoosh.store.LockError
.
在多线程或多进程环境中,您的代码需要注意,如果编写器已打开,则打开编写器可能会引发此异常。whoosh包括几个示例实现( whoosh.writing.AsyncWriter
和 whoosh.writing.BufferedWriter
)解决写锁问题的方法。
在编写器打开和提交期间, 索引仍可以读取. Existing readers are unaffected and new readers can open the current index normally.
锁定文件¶
锁定索引是通过获取 <indexname>_WRITELOCK
索引目录中的文件。释放文件锁后不会删除该文件,因此该文件存在 does not 表示索引已锁定。
版本¶
打开读卡器/搜索器时,读卡器表示 current version 索引的如果有人将更改写入索引,则任何已打开的读卡器 will not 自动选取更改。读卡器总是在读卡器打开时看到索引的存在。
如果在多个搜索请求中重新使用搜索者,可以使用 whoosh.searching.Searcher.up_to_date()
. 如果搜索者不是最新的,可以使用 whoosh.searching.Searcher.refresh()
::
# If 'searcher' is not up-to-date, replace it
searcher = searcher.refresh()
(如果搜索者有最新版本的索引, refresh()
只需返回即可。)
调用 Searcher.refresh()
更有效的方法是关闭搜索者并打开一个新的搜索者,因为它将重新使用任何未更改的底层读卡器和缓存。