HBase和Solr可以通過副處理器Coprocessor的方式向Solr發出請求,Solr對於接收到的資料可以做相關的同步:增、刪、改索 引的操作。 將存儲與索引放在不同的機器上,這是大資料架構的必須品,但目前還有很多不懂得此道的同學,他們對於這種思想感到很新奇,不過,這絕對是好的方 向,所以不懂得抓緊學習吧。
有個朋友給我的那篇博客留言,說CDH也可以做這樣的事情,我還沒有試過,他還問我要與此相關的代碼,於是我就稍微整理了一下,作為本篇文章的主要內容。 關於CDH的事,我會儘快嘗試,有知道的同學可以給我留言。
下面我主要講述一下,我測試對HBase和Solr的性能時,使用HBase副處理器向HBase添加資料所編寫的相關代碼,及解釋說明。
一、編寫HBase副處理器Coprocessor
一旦有資料postPut,就立即對Solr裡相應的Core更新。 這裡使用了ConcurrentUpdateSolrServer,它是Solr速率性能的保證,使用它不要忘記在Solr裡面配置autoCommit喲。
/* *版權:王安琪 *描述:監視HBase,一有資料postPut就向Solr發送,本類要作為觸發器添加到HBase *修改時間:2014-05-27 *修改內容:新增 */ package solrHbase.test; import java.io.UnsupportedEncodingException; import * **; public class SorlIndexCoprocessorObserver extends BaseRegionObserver { private static final Logger LOG = LoggerFactory .getLogger( SorlIndexCoprocessorObserver.class); private static final String solrUrl = "HTTP://192.1.11.108:80/solr/core1"; private static final SolrServer solrServer = new ConcurrentUpdateSolrServer( solrUrl, 10000, 20); /** * 建立solr索引 * * @throws UnsupportedEncodingException */ @Override public void postPut(final ObserverCoNtext<RegionCoprocessorEnvironment> e, final Put put, final WALEdit edit, final boolean writeToWAL) throws UnsupportedEncodingException { inputSolr(put); } public void inputSolr(Put put) { try { solrServer.add(TestSolrMain.getInputDoc(put)); } catch (Exception ex) { & nbsp; LOG.error(ex.getMessage()); } } }
注意:getInputDoc是這個HBase副處理器Coprocessor的精髓所在,它可以把HBase內的Put裡的內容轉化成Solr需 要的值。 其中String fieldName = key.substring(key.indexOf(columnFamily) + 3, key.indexOf(" 我在這")).trim();這裡有一個亂碼字元,在這裡看不到,請大家注意一下。
public static SolrInputDocument getInputDoc(Put put) { SolrInputDocument doc = new SolrInputDocument(); doc.addField("test_ID", Bytes.toString(put.getRow())); for ( KeyValue c : put.getFamilyMap().get(Bytes.toBytes(columnFamily))) { String key = Bytes.toString(c.getKey()); & nbsp; String value = Bytes.toString(c.getValue()); if (value.isEmpty()) { continue; } Stri ng fieldName = key.substring(key.indexOf(columnFamily) + 3, key.indexOf("")).trim(); & nbsp; doc.addField(fieldName, value); & nbsp; } return doc; }
二、編寫測試程式入口代碼main
這段代碼向HBase請求建了一張表,並將類比的資料,向HBase連續地提交資料內容,在HBase中不斷地插入資料,同時記錄時間,測試插入性能。
/* *版權:王安琪 *描述:測試HBaseInsert,HBase插入性能 *修改時間:2014-05-27 *修改內容:新增 */ package solrHbase.test; import hbaseInput.HbaseInsert; import ***; public class TestHBaseMain { private static Configuration config; private static String tableName = " angelHbase"; private static HTable table = null; private static final String columnFamily = "wanganqi"; /** * @param args */ public static void main(String[] args) { config = HBaseConfiguration.create(); config.set(" hbase.zookeeper.quorum", "192.103.101.104"); HbaseInsert.createTable( config, tableName, columnFamily); try { table = new HTable(config, Bytes.toBytes(tableName)); for (int k = 0; k < 1; k+ +) { Thread t = new Thread () { public void run()& nbsp; { for (int i  ;= 0; i < 100000; i++) { HbaseInsert.inputData(table,&n bsp; PutCreater.createPuts(1000, columnFamily)); & nbsp; Calendar c = Calendar.getInstance(); String dateTime&nbs p;= c.get(Calendar.YEAR) + "-" + c.get(Calendar.MONTH) + "-" &nbs p; + c.get(Calendar.DATE) + "T" &nb sp; + c.get(Calendar.HOUR) + ":" & nbsp; + c.get(Calendar.MINUTE) + ": " &nbs p; + c.get(Calendar.SECOND) + ":" + c.get(Calendar.MILLISECOND)&nbs p;+ "Z 寫入: "   ; + i * 1000; System.out.println(dateTime); &nb sp; } } &nbs p; }; & nbsp; t.start(); } } catch& nbsp;(IOException e1) { e1.printStackTrace(); } } }
下面的是與HBase相關的操作,把它封裝到一個類中,這裡就只有建表與插入資料的相關代碼。
/* *版權:王安琪 *描述:與HBase相關操作,建表與插入資料 *修改時間:2014-05-27 *修改內容:新增 */ package hbaseInput; import ***; import org.apache.hadoop.hbase.client.Put; public class HbaseInsert { public static void createTable( Configuration config, String tableName, String columnFamily) { HBaseAdmin hBaseAdmin; try { hBaseAdmin = new HBaseAdmin(config); if (hBaseAdmin.tableExists(tableName)) { return; } HTableDescriptor tableDescriptor = new HTableDescriptor(tableName); tableDescriptor.addFamily(new HColumnDescriptor(columnFamily)); hBaseAdmin.createTable(tableDescriptor); hBaseAdmin.close (); } catch (MasterNotRunningException e) { e.printStackTrace(); } catch (ZooKeeperConnectionException e) { e.printStackTrace( ); } catch (IOException e) { e.printStackTrace(); } } public static void inputData(HTable table, ArrayList<Put> puts) { try { table.put(puts); tabl e.flushCommits(); puts.clear(); & nbsp; } catch (IOException e) { e.printStackTrace (); } } }
三、編寫類比資料Put
向HBase中寫入資料需要構造Put,下面是我構造類比資料Put的方式,有字串的生成, 我是由mmseg提供的詞典words.dic中隨機讀取一些詞語連接起來,生成一句字串的,下面的代碼沒有體現,不過很easy,你自己造你自己想要的資料就OK了。
public static Put createPut(String columnFamily) { String ss = getSentence(); byte[] family = Bytes.toBytes(columnFamily); byte[] rowKey = Bytes.toBytes("" + Math.abs(r.nextLong())); Put put = new Put(rowKey); put.add(family, Bytes.toBytes("DeviceID"), Bytes.toBytes("" + Math.abs(r.nextInt()) )); ****** put.add(family, Bytes.toBytes("Company_mmsegsm"), Bytes.toBytes("ss")); return put; }
當然在運行上面這個程式之前,需要先在Solr裡面配置好你需要的列資訊,HBase、Solr安裝與配置,它們的基礎使用方法將會在之後的文章中 介紹。 在這裡,Solr的列配置就跟你使用createPut生成的Put搞成一樣的列名就行了,當然也可以使用動態列的形式。
四、直接對Solr效能測試
如果你不想對HBase與Solr的相結合進行測試,只想單獨對Solr的性能進行測試,這就更簡單了,完全可以利用上面的程式碼片段來測試,稍微組裝一下就可以了。
private static void sendConcurrentUpdateSolrServer(final String url, final int count) throws SolrServerE xception, IOException { SolrServer solrServer = new ConcurrentUpdateSolrServer(url, 10000, 20); for (int i = 0; i < count; i++) { solrServer.add(getInputDoc(PutCreater.createPut(columnFamily))); } }
希望可以説明到你規格嚴格-功夫到家。 這次的文章代碼又偏多了點,但代碼是解釋思想的最好的語言,我的提倡就是盡可能的減少代碼的注釋,盡力簡化你的代碼,使你的代碼足夠的清晰易懂,甚至於相似于偽代碼了,這也是《重構》這本書裡所提倡的。
原文連結:HTTP://www.cnblogs.com/wgp13x/p/3927979.html