ReganHoo 2010-03-12
四 查询分析器
默认情况下,Compass使用它自己的基于Lucene的查询分析器。Compass允许配置多个查询分析器(用所登记的名称查找),也可以覆盖默认的Compass查询分析器(用default已注册的名字)。自定义的查询分析器能用于扩展默认的查询语言支持,通过添加已解析的查询缓冲等等。一个自定义的查询分析器必须实现LuceneQueryParser接口。
这是一个配置自定义查询分析器的例子,注册名称为test:
<compass name="default"> <connection> <file path="target/test-index" /> </connection> <searchEngine> <queryParser name="test" type="eg.MyQueryParser"> <setting name="param1" value="value1" /> </queryParser> </searchEngine> </compass>
五 索引结构
理解搜索引擎索引时如何组织的是非常重要的,那样我们就可以稍后讨论事务,优化和子索引散列发。下面的结构显示了搜索引擎的索引结构:
图
每个子索引有他自己的完整机能索引结构(匹配单个Lucene索引)。Lucene索引部分持有一个关于索引“元数据”文件(叫做segments)和从0到n的segment文件。segment可以是一个单个文件(如果复合设置启用)或多个文件(如果复合设置没有启用)。一个segment接近于一个完整的功能索引,它保存有真实的倒转索引数据。
索引分割是Compass的一个主要特点,考虑到灵活的而且可配置的方式去管理复杂的索引和性能顾虑。下面章节将要讲述更多为什么这个特点是重要的细节,尤其是在使用事务管理的方面。
六:事务Compass搜索引擎抽象提供了对Lucene之上的事务管理的支持。抽象支持下面的事务处理:read_committed,lucene和async.Compass只提供了两种语法负责支持公共事务级别。
1 加锁(Locking)
Compass利用Lucene内部和外部处理锁机制并且利用他们建立它的事务锁。应该注意到事务锁是在子索引级别,这意味着脏操作只加锁他们各自的子索引的索引上。所以,越多的别名/可搜索内容匹配到相同的索引,就有越多的别名/可搜索内部当被执行脏操作的时候被锁定,但是搜索的速度就会越快。Lucene用一个特定的锁文件去管理内部和外部处理锁,这个文件可以在Compass配置中设置。你可以使用Compass配置管理事务超时和轮询间隔。
一个Compass事务只有当针对索引的脏操作发生时才会获得一个锁(对于read_committed和lucene这意味着:create,save或delete),他们尽可能快的创建“只读”事务。下面的配置文件说明怎么去控制加锁的两个主要设置,加锁超时(默认为10秒)和加锁轮询间隔(Compass将多久检查一次一个锁是否被释放)(默认为100毫秒)<compass name="default"> <connection> <file path="target/test-index" /> </connection> <transaction lockTimeout="15" lockPollInterval="200" /> </compass>
2事务处理器
(1)read_committed
读已提交的事务处理器允许隔离一个事务完成修改直到另一个事务提交。考虑到当前事务所做的变动
他也允许Load/get/find操作。这意味着如果就在删除操作之后一个搜索执行在同一个事务中,这个事务中发生的删除操作将被过滤。当开始一个read_commited事务,得不到锁。读操作也不会得到锁。只有当脏操作发生时才会得到锁。只有在关联到脏操作的别名/可搜索内容的索引上才会得到锁,比如子索引,将会锁定映射到那个子索引的所有其他别名/可搜索内容。 如果是对很多子索引执行的操作,read_commited事务支持并发提交,提交处理将同时发生在其他子索引上。它使用Compass的内部执行管理,很多线程还有执行管理的类型都可以配置。只有相关存储支持并发提交才会使用。
默认情况下,read_commited事务工作在异步模式(如果搜索引擎存储允许)。Compass执行者服务用于使用多线程执行销毁操作。考虑到更多更快的执行和当对象被索引或从搜索引擎移除时继续处理应用程序级别逻辑的能力。为了禁用这个,compass.transaction.processor.read_commited.concurrentOperations应该设置为false.
一旦一个读/搜索操作发生,read_commited语义通过等待所有当前操作完成仍然维持着。注意,当异步操作启用,伴随着索引对象的问题将会出现,不是以引发真实操作的结果,而是当commit,flush或read/seach的时候。CompassSession的flush操作也可以用于等待所有当前操作去执行。
有很多设置可以控制异步执行。compass.trasaction.processor.read_commited.concurrencyLevel控制着
用于处理脏操作的线程数量(默认为5)。
compass.transaction.propcessor.read_committed.hashing控制如何操作哈希到各自的线程处理,并且可以是由uid或子索引(默认是uid)。compass.transaction.processor.read_connitted,backlog控制着已允许的未决的破坏性操作的数量。如果完整,脏操作将被阻塞直到空间变为可用的(默认为100).最后,compass.transaction.processor.read_committed.addTimeOut控制着如果backlog已满将脏操作添加到backlog的等待时间。它默认为10秒并且接受Compass时间格式(10millis,30s,...).注意。所有的设置都是运行时设置,就是说可以用CompassSession的getSettings()方法控制特定的事务然后设置各自的。read_committed事务处理器运行针对有一个事务日志(一个简单的另一个Lucene索引)。事务日志可以保存在内存中或在文件系统中,默认情况下事务日志保存在内存里,下面是如何配置:
<compass name="default"> <connection> <file path="target/test-index" /> </connection> <transaction processor="read_committed"> <processors> <readCommitted transLog="ram://" /> </processors> </transaction> </compass> compass.engine.connection=target/test-index compass.transaction.readcommitted.translog.connection=ram://
使用read_committed事务处理器也可以用下面的代码在运行时完成配置:
CompassSessionsession=compass.openSession();
session.getSettings().setSettings(LuceneEnvironment.Transaction.Processor.Type,LuceneEnvironment.Transaction.Processor.ReadCommited.NAME);FS事务日志将事务数据保存在文件系统上。这考虑到当与由于性能的随机事务日志比较时更大的事务(在数据方面更大)将会运行。fs事务日志可以用一个path去配置那里保存事务日志(默认指向Java.io.tmpdir系统属性)。path然后添加到compass/translog并且每个事务都有唯一一个目录创建下面是一个如何配置fs事务的例子:
<compass name="default"> <connection> <file path="target/test-index" /> </connection> <transaction processor="read_committed"> <processors> <readCommitted transLog="file://" /> </processors> </transaction> </compass> compass.engine.connection=target/test-index compass.transaction.readcommitted.translog.connection=file://
CompassSession和CompassIndexSession提供flushCommit操作。当使用read_committed事务处理器时,意味着当前对搜索引擎的改变将被flush或commit的操作。这个操作对其他sessions或compass实例是可见的而且在事务上的回滚操作不会回滚他们。flushCommit是随时可以执行的,有一个长期运行的session执行索引和事务不如间歇性对其他session做出改变重要。
事务日志设置是一个可设置的session设置级别的。这允许改变Compass将如何为每个session保存事务日志,并且不全是在Compass实例级别配置。注意,在session上的唯一应用是负责创建事务,下面的例子说明它是如何完成的:
CompassSessionsession=compass.openSession();
session.getSettings().setSettings(LuceneEnvironment.Transaction.Processor.ReadCommitted.TransLog.CONNECTION,"file://temp/");(2) lucene一个特别的事务处理器,Lucene(以前被认知为批插入)事务处理器是一个类似于read_committed隔离级别的处理器,除了在同一个事务中有脏操作的时候不能执行get/load/find操作。对一个长期运行的批量脏操作这个隔离级别是随手可得的,并且要比read_committed快。Compass的很多使用模式能够与Lucene隔离级别完美的合作。
在提交时使用合并操作,所以理解这个事务级别是很重要的。Lucene可能在提交阶段执行很多合并操作,这依赖于使用compass.engine.mergeFactor配置的合并因子。这是与read_committed处理器不同的地方,read_committed在提交时不会执行合并。可能合并有时会引发提交,所以一种做法就是配置一个大的合并因子并且让优化器做它自己的不可思议(你可以为优化器配置一个不同的合并因子)。
当使用这个事务隔离级别时另一个重要参数是compass.engine.ramBufferSize(默认是16.0Mb),这个取代最大缓冲doc参数并且控制事务数据在内存中保存的数量。越大的值越能产生更好的性能并且尽可能地分配最多是最好的。
默认情况下,Lucene事务工作在异步模式。Compass执行器service用于使用多线程类执行这些破坏性操作。这就允许在对象被搜索引擎索引或删除的时候可以有更快的执行速度和继续处理应用程序级别逻辑的能力。为了使这个失效,compass.transaction.processor.lucene.concurrentOperations应该设置为false.注意,当异步操作可行的时候,索引对象的问题将会出现,不是以所引起真是操作的结果出现,而是在commit或flush阶段。CompassSession的flush操作也可用于等待所有当前操作去执行的时候。同样注意,不像read_committed事务(由于Lucene事务处理器的语法,在read/search操作中不会反应到当前操作),search/read操作时,无需等待异步脏操作先去处理。
有很多设置参数可以控制异步执行(javadoc在LuceneEnvironment.Transaction.Processor.Lucene部分)。compass.transaction.processor.lucene.comcurrencyLevel控制着用于处理脏操作的线程数(每个事务,默认为5)。compass.transaction.processor.lucene.hashing控制操作如何散列处理各自的线程,也可以使用uid或subindex(默认使用uid).compass.transaction.processor.lucene.backlog控制着允许的销毁操作的数量。如果已满,脏操作会堵塞,直到空间有空(默认为100)。最后,compass.transaction.processor.lucene.addTimeout控制如果backlog已满,等待将脏操作添加到backlog的时间。默认是10秒并且可以接受Compass时间格式。注意,所以的设置也可以通过控制特定事务在运行时设置,用CompassSession的getSettings()操作然后各自设置。
如果某个操作是针对多个子索引执行的,lucene事务支持并发提交,提交处理将会同时发生在不同的子索引上。使用Compass内部的执行管理器,在这里线程的数量和执行管理器的类型可以配置。
CompassSession和CompassIndexSession提供flushCommit操作,当使用Lucene事务处理器时,该操作意味着当时对搜索引擎的改变将会被flush并提交。这个操作对其他session或compass实例是可见的并且在事务上的回滚操作将不会回滚他们。 当有一个长期运行的执行索引和处理事务的session 没有 将所做的变化间歇性对其他Session可见 重要时flushCommit可以容易获得。这里说明如何将隔离级别配置为默认的:
<compass name="default"> <connection> <file path="target/test-index" /> </connection> <transaction processor="lucene" /> </compass> compass.engine.connection=target/test-index compass.transaction.processor=lucene
使用Lucene事务处理器也可以使用下面代码在运行时完成配置:
CompassSession session = compass.openSession(); session.getSettings().setSettings(LuceneEnvironment.Transaction.Processor.Type, LuceneEnvironment.Transaction.Processor.Lucene.Name);
(3) 异步
异步事务处理器允许异步化处理事务,不用招致任何真正执行事务线程的高层。事务(每个事务由一个或多个破坏性操作组成--create/upgrade/delete)并发积聚并且异步处理。注意,异步事务处理器当脏操作在一个事务内发生时不会获得锁。
注意,当Compass的多个实例使用这种事务处理器在运行,事务的顺序是不维护的,可能的结果会是应用于索引的事务可能在事务顺序之外。当有一个单个的实例在运行时,默认情况下,一旦脏操作对子索引操作时就会获得排序锁来维护事务的顺序(类似于Lucene的写锁),一旦事务提交或回滚就会释放。为了失效这个排序,compass.transaction.processor.async.maintainOrder可以设置为false.
未处理事务的数量是有限制的并且默认为10.如果处理器在处理事务方面落后,提交操作将阻塞,直到backlog降低到它的开始。p42backlog可以使用compass.transaction.processor.async.backlog进行设置。它可以用compass.transaction.processor.saync.assTimeout设置改变(接受时间格式配置)。
处理事务是后台等待事务的线程完成的。一旦有一个事务需要处理,首先会设法等待其他的事务。将会堵塞100毫秒(使用compass.transaction.processor.async.batchJobTimeout配置),并且如果有一个被添加,将会继续等待直到达到5次(使用compass.transaction.processor.async.batchJobSize配置)。一旦基于公休的批量任务完成,处理器将以非阻塞方式设法达到5个或更多的事务(使用compass.transaction.processor.async.nonBlockingBatchJobSize配置)。
当所有的事务任务都积聚了,处理器开动5个线程(使用compass.transaction.processor.async.concurrencyLevel配置)去处理所有针对索引的事务任务。散列真实操作(create/update/delete)也可以基于uid(resource的)或子索引来完成。默认情况下,散列可以基于uid完成也可以使用compass.transaction.processor.async.hashing设置。CompassSession与CompassIndexSession提供了flushCommit方法。这个方法,当用于异步事务处理器时,意味着所有的改变积聚到这点(flushConnit)时将被转到处理(类似commit)除了session仍然为其他的给别开着.
这就允许,对于长期运行的索引session来说,周期性flush并且提交修改(否则内训消耗将持续增长)将代替提交并关闭当前session,再重新打开一个新的session.
当事务处理器关闭,默认情况下它要等待所有的事务完成。为了失效这点,compass.transaction.processor.async.processBeforeClose参数应该设置为false.
这里是如何将事务隔离级别设置为默认使用的:<compass> <connection> <file path="target/test-index"/> </connection> <transaction processor="async"/> </compass> compass.engine.connection=target/test-index compass.transaction.processor=async
也可以使用下面的代码在运行时设置异步事务处理器:
CompassSession session = compass.openSession(); session.getSettings().setSetting(LuceneEnvironment.Transaction.Process.Type,LuceneEviroment.Transaction.Processor.Async.Name);
(4) mt(多线程Multi Threaded)
mt事务处理器时一个有效的线程安全事务处理器,允许使用同一个CompassIndexSession(或者CompassSession)跨越多个线程。当在一个逻辑索引Session中多个线程在更新索引时事务处理器时很容易获得的。
一旦一个脏操作使用事务处理器被执行,它各自的子索引将被加锁并且其他session也不会有脏操作,直到session被提交或回滚或关闭。由于mt事务处理器的自然性,flushCommit操作时非常便利的。当它被调用的时候将有效地提交所有改变而不用关闭或提交session.当搜索时这对其他session是透明的。注意,这也意味着flush提交的操作在调用rollback操作时不会回滚。
在提交和索引时完成合并方面,理解这个事务隔离级别是非常重要的。Lucene可能在提交时间执行一些合并时依赖compass.engine.mergeFactor配置的合并因子。这与在执行提交时没有合并的read_committed处理器是不同的。
可能有时合并会引发提交,所以一个做法就是配置一个大的合并因子并且让优化器做它的不可思议(你可以为优化器配置一个不同的合并因子)。
另一个重要参数是当使用事务隔离级别时,compass.engine.ramBufferSize(默认为16Mb)将取代最大缓冲doc参数并且控制保存在内存中事务数据的数量。较大的值将发挥更好的性能并且设置为尽可能越大越好。
如果在search/readAPI时使用mt事务处理器,它基本扮演一个与Lucene事务处理器的类似方式,意味着搜索操作将注意索引的最新版本,在事务期间没有执行当前的改变。这个规则有一个例外,如果flushCommit操作被调用,Compass内部的缓冲将无效(或异步或明确地调用refresh或clear缓冲接口),然后搜索结果将反映一直到flushCommit操作的修改。
这是如何将事务隔离级别设为默认的配置:<compass name="default"> <connection> <file path="target/test-index" /> </connection> <transaction processor="mt" /> </compass> compass.engine.connection=target/test-index compass.transaction.processor=mt
也可以使用下面的代码在运行时配置mt事务处理器:
CompassSession session = compass.openSession(); session.getSettings().setSetting(LuceneEnvironment.Transaction.Processor.TYPE, LuceneEnvironment.Transaction.Processor.MT.NAME);
(5)搜索 一个优化的事务处理器,只提供搜索能力。事务处理器是当session设置为read only(使用CompassSession的setReadOnly()方法)时自动使用的,或者当打开一个搜索session(使用Compass的openSeesion()方法)。
(6)tc(Terracotta)
(7)自定义
实现一个自定义事务处理器时非常简单的。Compass提供简单API和需要简单实现的简单基类