Lucene是Apache软件基金会下的一个非常著名的全文搜索引擎,一般地Lucene本身可以不存储数据,Lucene实现的只是在已有的信息上建立索引,所以Lucene可以是完全独立于应用本身,只是基于相应数据生成索引信息的一个产品,当然有些时候,Lucene也会被当作一个数据库在用,比如用作LBS服务时。
Lucene关系图
Lucene Spatial建立空间索引采用与MongoDB类似的Geohash实现,通过把经度(longitude)和纬度(latitude)转化为一维字符串后建立索引。
Lucene在LBS应用中,被当作一个数据库使用,即使Lucene本身只是一个索引引擎,Lucene通过Lucene Spatial实现对地理位置索引支持
Lucene独立于底层数据源,所以在很多数据存储上,都可以使用Lucene建立索引信息,当做独立数据库使用时,Lucene还支持Spatial索引,通过维护内存中两份索引的方式,可以做到实时索引目的
Lucene从数据源读取数据建立索引,对外只提供查询接口,这种应用适合于数据改动不是很大的应用,由于Lucene不支持update操作,数据一旦发生改变,需要通过delete/insert操作进行索引数据的更新,主索引在打开的情况下对更新是不可见的,造成索引中的信息可能会不准确,所以,对于Lucene来说,经常性重做索引是必要操作。在LBS服务中,可以把Lucene脱离数据源当作独立的数据库来进行使用,由于LBS类服务对数据的实时性要求比较高,Lucene在部署的时候需要进行特殊的设置,即需要维护两份索引,主索引和增量索引,主索引可以定时每天在业务量比较小的时间段更新,增量索引用于位置更新的实时记录,Lucene的索引在没有重新打开前的任何操作对当前所有用户都是不可见的(类似于数据库的MVCC),所以通过在主索引中删除数据,然后在增量索引中插入数据来实现update操作是可行的。Lucene一般常用的实时索引部署如下:
Lucene一般部署
上图中所有的文档插入都保存到Ram-IndexA中,Ram-IndexA就是一个内存索引,所有新插入的文档都在内存中,这样随着文档数量的增加,必定造成内存的耗竭,所以给内存设定一个阈值,当内存索引达到一定量时转化为Ram-IndexB,Ram-IndexB被称为合并索引,合并索引把内存中的信息合并到磁盘上,而此时,需要重新开一块内存索引用于接收新的插入文档,内存索引和文档索引就相当于两个可以互为替换的内存块,一个做索引插入,一个做索引合并。
上面的部署中同时也存在几个问题:
1. 查询实时性,由于Ram-IndexB变成了合并索引,没有提供对外服务,索引在Ram-IndexB中的数据将无法被外部查询到。
2. Full-IndexA通过索引合并后,需要重新打开才可以访问最新合并过来的索引信息,而一般磁盘上的索引都比较大,重新打开的代价将非常大。
3. Ram-IndexA、Ram-IndexB都为内存索引,数据没有持久化,如果一旦发生索引机器宕机,内存中部分数据会被丢失。
当然要避免以上1、2两个问题,还是可以通过对Ram-IndexB和Full-IndexA各增加一个IndexReader解决,Ram-IndexB提供对外的IndexReader,在进行索引Merge时可以对外提供查询服务,而Full-IndexA增加一个IndexReader,索引Merge完后通过新的IndexReader重新打开索引,老的IndexReader继续向外提供服务直至新的IndexReader打开完毕,这样整个架构就变得非常复杂。
相对来说,Lucene要做到真正的实时更新比较难,或多或少有时间上的延迟,而且意外宕机时,丢失的数据也比较多,对于实时性和数据完整性要求比较高的LBS应用中,Lucene相对其余3者,处于劣势地位。
通过上面对几个产品的初步分析,我们得出下面这个功能对比表,单从功能支持的角度,比较下各个产品之间的功能特点:
功能 |
MySQL |
PostGIS |
MongoDB |
Lucene |
事务 |
支持 |
支持 |
不支持 |
不支持 |
Spatial Index |
支持 |
支持 |
支持 |
支持 |
索引类型 |
R Tree |
R Tree/ GIST |
Geohash |
Geohash |
Replication |
支持 |
支持 |
支持 |
不支持 |
故障转移 |
不支持 |
不支持 |
支持 |
不支持 |
Sharding |
不支持 |
不支持 |
支持 |
不支持 |
标准支持 |
较弱 |
强 |
较强 |
较弱 |
数据量 |
中小型 |
中小型 |
大型 |
中小型 |
精确度 |
一般 |
高 |
较高 |
较高 |
适用 |
简单空间操作 |
复杂空间操作 |
复杂空间操作 |
简单空间操作 |
功能对比表
通过上面的表可以看出:
MySQL适合数据量不是很大,并且空间操作要求和精确度都不是很高的应用
PostGIS适合数据量不是很大,但对空间操作要求和精确度都比较高的应用
MongoDB适合数据量比较大,对性能和空间要求都比较高的应用
Lucene适合数据量不是很大,允许丢失部分数据的情况
本文来自网易实践者社区,经作者蒋鸿翔授权发布。