lucene+hadoop 分布式並行計算搜尋方塊架

來源:互聯網
上載者:User

Nut
lucene+hadoop 分布式並行計算搜尋方塊架
Alpha 9 文檔
作者:曾年仔
mail:zengnianzai@163.com
blog: http://www.blogjava.net/nianzai/
code: http://code.google.com/p/nutla/
1、概述
不管程式效能有多高,機器處理能力有多強,都會有其極限。能夠快速方便的橫向與
縱向擴充是Nut設計最重要的原則,以此原則形成以分布式並行計算為核心的架構設計。以
分布式並行計算為核心的架構設計是Nut區別於Solr、Katta的地方。
Nut是一個Lucene+Hadoop分布式並行計算搜尋方塊架,能對千G以上索引提供7*24小時搜
索服務。在伺服器資源足夠的情況下能達到每秒處理100萬次的搜尋請求。
Nut開發環境:
jdk1.6.0.23+lucene3.0.3+eclipse3.6.1+hadoop0.20.2+zookeeper3.3.2+hbase0.20.6+m
emcached+mongodb+linux
2、特新
a、熱插拔
b、可擴充
c、高負載
d、易使用,與現有項目無縫整合
e、支援排序
f、7*24服務
g、失敗轉移
3、搜尋流程
Nut由Index、Search、Client、Cache和DB五部分構成。(Cache實現了對memcached的支援,DB
實現了對hbase,mongodb的支援)
Client處理使用者請求和對搜尋結果排序。Search對請求進行搜尋,Search上只放索引,數
據儲存在DB中,Nut將索引和儲存分離。Cache緩衝的是搜尋條件和結果文檔id。DB儲存著
資料,Client根據搜尋排序結果,取出當前頁中的文檔id從DB上讀取資料。
使用者發起搜尋請求給由Nut Client構成的叢集,由某個Nut Client根據搜尋條件查詢Cache
伺服器是否有該緩衝,如果有緩衝根據緩衝的文檔id直接從DB讀取資料,如果沒有緩衝將
隨機播放一組搜尋伺服器組(Search Group i),將查詢條件同時發給該組搜尋伺服器組裡的
n台搜尋伺服器,搜尋伺服器將搜尋結果返回給Nut Client由其排序,取出當前頁文檔id,
將搜尋條件和當前文檔id緩衝,同時從DB讀取資料。
4、索引流程
Hadoop Mapper/Reducer 建立索引。再將索引從HDFS分發到各個索引伺服器。
對索引的更新分為兩種:刪除和添加(更新分解為刪除和添加)。
a、刪除
在HDFS上刪除索引,將產生的*.del檔案分發到所有的索引伺服器上去或者對HDFS
索引目錄刪除索引再分發到對應的索引伺服器上去。
b、添加
新添加的資料用另一台伺服器來產生。
刪除和添加步驟可按不同定時策略來實現。
5、Nut分布式並行計算特點
Nut分布式並行計算雖然也是基於M/R模型,但是與Hadoop M/R模型是不同的。在Hadoop M/R
模型中 Mapper和Reducer是一個完整的流程,Reducer依賴於Mapper。資料來源通過Mapper
分發本身就會消耗大量的I/O,並且是消耗I/O最大的部分。所以Hadoop M/R 並發是有限的。
Nut M/R模型是將Mapper和Reducer分離,各自獨立存在。在Nut中 索引以及索引管理 構成
M,搜尋以及搜尋伺服器組 構成 R。
以一個分類統計來說明Nut分布式並行計算的流程。假設有10個分類,對任意關鍵詞搜尋要
求統計出該關鍵詞在這10個分類中的總數。同時假設有10組搜尋伺服器。索引以及索引管
理進行索引資料的Mapper,這塊是後台獨自運行管理的。Nut Client將這10個分類統計分
發到10組搜尋伺服器上,每組搜尋伺服器對其中一個分類進行Reducer,並且每組搜尋服務
器可進行多級Reducer。最後將最終結果返回給Nut Client。
6、設計圖
Nut Client
使用者
Nut Search
發起請求 發起請求
返回評分結果
返回排序結果
client 1 。。。。。。Client m
負載平衡器
發起請求
返回排序結果
Nut Cache 排序結果
搜尋條件:文檔ids
返回結果
Nut DB
Key:value
ids
返回
Nut Index
















Zookeeper 伺服器狀態管理
MR 1 MR 2 。。。。。。MR p
sg 1
Search group 1
運行中搜尋伺服器組
S 1 S 2 。。。 S n
備用中搜尋伺服器組(可選)
B 1 B 2 。。。B i
sg 1 sg 2 。。。。。。sg h
Search group h
7、Zookeeper伺服器狀態管理原則
在架構設計上通過使用多組搜尋伺服器可以支援每秒處理100萬個搜尋請求。
每組搜尋伺服器能處理的搜尋請求數在1萬—1萬5千之間。如果使用100組搜尋伺服器,理
論上每秒可處理100萬個搜尋請求。
假如每組搜尋伺服器有100份索引放在100台正在運行中搜尋伺服器(run)上,那麼將索引按
照如下的方式放在備用中搜尋伺服器(bak)上:index 1,index 2,index 3,index 4,index
5,index 6,index 7,index 8,index 9,index 10放在B 1 上,index 6,index 7,index 8,index
9,index 10,index 11,index 12,index 13,index 14,index 15放在B 2上。。。。。。index
96,index 97,index 98,index 99,index 100,index 5,index 4,index 3,index 2,index 1
放在最後一台備用搜尋伺服器上。那麼每份索引會存在3台機器中(1份正在運行中,2份備
份中)。
儘管這樣設計每份索引會存在3台機器中,仍然不是絕對安全的。假如運行中的index
1,index 2,index 3同時宕機的話,那麼就會有一份索引搜尋服務無法正確啟用。這樣設計,
作者認為是在安全性和機器資源兩者之間一個比較適合的方案。
備用中的搜尋伺服器會定時檢查運行中搜尋伺服器的狀態。一旦發現與自己索引對應的服
務器宕機就會向lock申請分布式鎖,得到分布式鎖的伺服器就將自己加入到運行中搜尋服
務器組,同時從備用搜尋伺服器組中刪除自己,並停止運行中搜尋伺服器檢查服務。
為能夠更快速的得到搜尋結果,設計上將搜尋伺服器分優先等級。通常是將最新的資料放
Zookeeper 伺服器狀態管理
Sg 1 Sg 2 。。。。。。 Sg h
run lock bak
Search group 1
運行中搜尋伺服器組
S 1 。。。 S n
備用中搜尋伺服器組
B 1 。。。。B i
在一台或幾台記憶體搜尋伺服器上。通常情況下前幾頁資料能在這幾台搜尋伺服器裡搜尋到。
如果在這幾台搜尋伺服器上沒有資料時再向其他舊資料搜尋伺服器上搜尋。
優先搜尋等級的邏輯是這樣的:9最大為搜尋全部伺服器並且9不能作為level標識。當搜尋
等級level為1,搜尋優先順序為1的伺服器,當level為2時搜尋優先順序為1和2的伺服器,依此
類推。
8、web.xml配置
<!-- 啟動zookeeper串連檢查 -->
<servlet>
<servlet-name>ZooKeeperInitServlet</servlet-name>
<servlet-class>nut.nianzai.servlet.ZooKeeperInitServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<!-- 伺服器狀態顯示 -->
<servlet>
<servlet-name>StatusServlet</servlet-name>
<servlet-class>nut.nianzai.servlet.StatusServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>StatusServlet</servlet-name>
<url-pattern>/status.cgi</url-pattern>
</servlet-mapping>
9、搜尋外掛程式
a、通過實現QueryPlugin介面來實現自訂查詢功能
public class ExampleQueryPlugin implements QueryPlugin
{
@Override
/**
* 將自己要實現的查詢功能在這實現
*/
public Query query(String keyword) throws Exception
{
Analyzer analyzer = new ChineseAnalyzer();
QueryParser parser1 = new QueryParser(Version.LUCENE_30,"title", analyzer);
QueryParser parser2 = new QueryParser(Version.LUCENE_30,"descs", analyzer);
Query query1 = parser1.parse(keyword);
query1.setBoost(1.2f);
Query query2 = parser2.parse(keyword);
query2.setBoost(0.8f);
BooleanQuery bq = new BooleanQuery();
bq.add(query1, BooleanClause.Occur.MUST);
bq.add(query2, BooleanClause.Occur.SHOULD);
return bq;
}
@Override
/**
* 實現自己的排序功能
*/
public Sort sort()
{
Sort sort=new Sort(new SortField("reviews", SortField.INT, true));
return sort;
}
@Override
/**
* 實現自己的filter功能
*/
public Filter filter()
{
return null;
}
}
b、配置plugin.properties檔案
#自訂查詢外掛程式名稱=自訂查詢外掛程式實作類別名
basicQuery=nut.nianzai.plugin. ExampleQueryPlugin
c、將自訂查詢外掛程式和plugin.properties打包產生nut-plugin.jar部署在每台服務的
lib目錄中
10、索引外掛程式
a、通過實現IndexPlugin介面來實現自訂產生索引功能
public class ExampleIndexPlugin implements IndexPlugin
{
private static Analyzer analyzer = new ChineseAnalyzer();
@Override
public void create(File file,Iterable<Text> values)
{
try
{
IndexWriter indexWriter = new
IndexWriter(NIOFSDirectory.open(file),analyzer,true,IndexWriter.MaxFieldLength.UNLIMITED)
;
indexWriter.setRAMBufferSizeMB(256);
indexWriter.setUseCompoundFile(false);
for (Text str : values)
{
Document doc = new Document();
String[] ss=str.toString().split("<<,>>");
doc.add(new Field("id",ss[0], Field.Store.YES,Field.Index.NOT_ANALYZED));
doc.add(new Field("title", ss[1], Field.Store.NO,Field.Index.ANALYZED));
doc.add(new Field("descs", ss[2], Field.Store.NO,Field.Index.ANALYZED));
doc.add(new Field("reviews",ss[3],Field.Store.YES,Field.Index.NOT_ANALYZED));
indexWriter.addDocument(doc);
}
indexWriter.optimize();
indexWriter.close();
}
catch(Exception e)
{
e.printStackTrace();
}
}
@Override
public void merge(Directory[] dirs,Directory localWorkingDir) throws IOException
{
IndexWriter writer = new IndexWriter(localWorkingDir, analyzer,
true,IndexWriter.MaxFieldLength.UNLIMITED);
writer.setRAMBufferSizeMB(256);
writer.setUseCompoundFile(false);
writer.addIndexesNoOptimize(dirs);
writer.optimize();
writer.close();
}
@Override
public void delete(Directory dir, String ids) throws IOException
{
IndexWriter writer = new
IndexWriter(dir,analyzer,false,IndexWriter.MaxFieldLength.UNLIMITED);
writer.deleteDocuments(NutUtil.getTerms(ids));
writer.close();
}
b、配置hadoop.properties檔案
indexplugin=nut.nianzai.plugin.ExampleIndexPlugin
c、將自訂建索引外掛程式和hadoop.properties檔案打包成nut-index.jar放在hadoop環境
中運行
11、HBase資料插入外掛程式
a、通過實現HBasePlugin介面來實現自訂插入資料功能
public class ExampleHBasePlugin implements HBasePlugin
{
@Override
public Put insert(Text value)
{
String[] ss=value.toString().split("<<,>>");
Put put = new Put(Bytes.toBytes(Integer.parseInt(ss[0])));
put.add(Bytes.toBytes("title"), Bytes.toBytes(""), Bytes.toBytes(ss[1]));
put.add(Bytes.toBytes("descs"), Bytes.toBytes(""), Bytes.toBytes(ss[2]));
put.add(Bytes.toBytes("reviews"), Bytes.toBytes(""), Bytes.toBytes(ss[3]));
return put;
}
}
b、配置hadoop.properties檔案
indexplugin=nut.nianzai.plugin.ExampleHBasePlugin
c、將自訂建索引外掛程式和hadoop.properties檔案打包成nut-hbase.jar放在hadoop環境
中運行
12、測試
public class NutTest
{
//分布式搜尋例子
public static void main(String[] arg)
{
try
{
ZkCheck.start();
Thread.sleep(6*1000);//等待6秒,用於通訊初始化
//構造查詢對象
Parameter parameter=new Parameter();
parameter.setQuery("basicQuery");
parameter.setKeyword("soho");
parameter.setNo(1);
parameter.setPs(2);
parameter.setSortfield("reviews");//如果實現了排序,指明排序欄位,需要根據
這個來對結果進行排序
//只統計
int n=Client.parallelTotal(parameter);
System.out.println(n);
//搜尋
NutDB db=new MongoDB(House.class);
NutCached cached=new MemCached();
List<Object> ll=Client.parallelSearch(cached,db,parameter);
System.out.println(parameter.getRscount());//返回搜尋記錄總數
for(int i=0;i<ll.size();i++)
{
System.out.println(((House)ll.get(i)).getId());
System.out.println(((House)ll.get(i)).getTitle());
System.out.println(((House)ll.get(i)).getDescs());
System.out.println(((House)ll.get(i)).getReviews());
}
}
catch(Exception e)
{e.printStackTrace();}
}
}
13、伺服器端部署
將nut壓縮包解壓部署在伺服器上,根據服務操用途使用相應的啟動服務命
a、運行搜尋伺服器啟用命令nutserver.sh或nutserver.bat
b、備用搜尋伺服器啟用命令checkserver.sh或checkserver.bat
14、使用者管理工具
nut.sh(nut.bat)為命令列使用者管理工具。
a、建立一個zookeeper根節點
sh nut.sh zk create 192.168.195.128:2181 nutzk
b、查看根節點nutzk下的子節點
sh nut.sh zk list 192.168.195.128:2181 nutzk
c、刪除根節點nutzk
sh nut.sh zk delete 192.168.195.128:2181 nutzk
d、將目錄(檔案)從hdfs 複製到本地目錄
sh nut.sh copy h2l hdfs://192.168.195.128:9000/user/nianzai/nutindex/0/
/home/nianzai/index/
e、將目錄(檔案)從本地複製到hdfs
sh nut.sh copy l2h /home/nianzai/1.txt hdfs://192.168.195.128:9000/user/nianzai/input/
f、建立搜尋節點
sh nut.sh zk searchgroup 192.168.195.128:2181 sg1

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.