(轉)基於MapReduce的HBase開發(續)

示例

代碼:

[java] view plaincopy
  1. import java.io.ByteArrayOutputStream;   
  2. import java.io.DataOutputStream;   
  3. import java.io.IOException;   
  4. import java.util.HashMap;   
  5.    
  6. import org.apache.hadoop.conf.Configuration;   
  7. import org.apache.hadoop.hbase.HBaseConfiguration;   
  8. import org.apache.hadoop.hbase.HColumnDescriptor;   
  9. import org.apache.hadoop.hbase.HTableDescriptor;   
  10. import org.apache.hadoop.hbase.client.HBaseAdmin;   
  11. import org.apache.hadoop.hbase.client.HTable;   
  12. import org.apache.hadoop.hbase.client.Put;   
  13. import org.apache.hadoop.hbase.client.Result;   
  14. import org.apache.hadoop.hbase.client.Scan;   
  15. import org.apache.hadoop.hbase.io.ImmutableBytesWritable;   
  16. import org.apache.hadoop.hbase.mapreduce.MultiTableOutputFormat;   
  17. import org.apache.hadoop.hbase.mapreduce.TableInputFormat;   
  18. import org.apache.hadoop.hbase.util.Base64;   
  19. import org.apache.hadoop.hbase.util.Bytes;   
  20. import org.apache.hadoop.io.Writable;   
  21. import org.apache.hadoop.mapreduce.Job;   
  22. import org.apache.hadoop.mapreduce.Mapper;   
  23.    
  24. public class IndexBuilder {   
  25.    
  26.   // 索引表唯一的一列爲 INDEX_ROW,其中 INDEX 爲列族   
  27.   private static final byte[] INDEX_COLUMN = Bytes.toBytes("INDEX");   
  28.   private static final byte[] INDEX_QUALIFIER = Bytes.toBytes("ROW");   
  29.    
  30.   // 實現 Map 類   
  31.   public static class Map extends   
  32.     Mapper<ImmutableBytesWritable, Result, ImmutableBytesWritable, Writable> {   
  33.    
  34.     // 存儲了“列名”到“表名——列名”的映射   
  35.     // 前者用於獲取某列的值,並作爲索引表的鍵值;後者用戶作爲索引表的表名   
  36.     private HashMap<byte[], ImmutableBytesWritable> indexes;   
  37.     private byte[] family;   
  38.    
  39.     // 實現 map 函數   
  40.     public void map(ImmutableBytesWritable key, Result value,   
  41.         Context context) throws IOException, InterruptedException {
  42.       // indexes是在setup方法中初始化的   
  43.       for (java.util.Map.Entry<byte[], ImmutableBytesWritable> index : indexes   
  44.           .entrySet()) {   
  45.         // 獲取列名   
  46.         byte[] qualifier = index.getKey();   
  47.         // 索引表的表名   
  48.         ImmutableBytesWritable tableName = index.getValue();   
  49.         // 根據“列族:列名”獲得元素值   
  50.         byte[] newValue = value.getValue(family, qualifier);   
  51.    
  52.         if (newValue != null) {   
  53.           // 以列值作爲行健,在列“INDEX:ROW”中插入行健   
  54.           Put put = new Put(newValue);   
  55.           put.add(INDEX_COLUMN, INDEX_QUALIFIER, key.get());   
  56.    
  57.           // 在 tableName 表上執行 put   
  58.           // 操作使用 MultipleOutputFormat 時,   
  59.           //第二個參數必須是 Put 和 Delete 類型   
  60.           context.write(tableName, put);   
  61.         }   
  62.       }   
  63.     }   
  64.    
  65.     // setup爲Mapper中的方法,該方法只在任務初始化時執行一次   
  66.     protected void setup(Context context) throws IOException,   
  67.         InterruptedException {   
  68.       Configuration conf = context.getConfiguration();   
  69.    
  70.       // 通過 Configuration.set()方法傳遞參數   
  71.       String tableName = conf.get("index.tablename");   
  72.       String[] fields = conf.getStrings("index.fields");   
  73.    
  74.       // fields 內爲需要做索引的列名   
  75.       String familyName = conf.get("index.familyname");   
  76.       family = Bytes.toBytes(familyName);   
  77.    
  78.       // 初始化 indexes 方法   
  79.       indexes = new HashMap<byte[], ImmutableBytesWritable>();   
  80.    
  81.       for (String field : fields) {   
  82.         // 如果給 name 做索引,則索引表的名稱爲“heroes‐name”   
  83.         indexes.put(Bytes.toBytes(field),    
  84. new ImmutableBytesWritable(   
  85.             Bytes.toBytes(tableName + "‐" + field)));   
  86.       }   
  87.     }   
  88.   }   
  89.    
  90.   // 初始化示例數據表——“heroes”   
  91.   public static void initHBaseTable(Configuration conf, String tableName)   
  92.       throws IOException {   
  93.     // 創建表描述   
  94.     HTableDescriptor htd = new HTableDescriptor(tableName);   
  95.     // 創建列族描述   
  96.     HColumnDescriptor col = new HColumnDescriptor("info");   
  97.    
  98.     htd.addFamily(col);   
  99.    
  100.     HBaseAdmin hAdmin = new HBaseAdmin(conf);   
  101.    
  102.     if (hAdmin.tableExists(tableName)) {   
  103.       System.out.println("該數據表已經存在,正在重新創建。");   
  104.       hAdmin.disableTable(tableName);   
  105.       hAdmin.deleteTable(tableName);   
  106.     }   
  107.    
  108.     System.out.println("創建表:" + tableName);   
  109.     // 創建表   
  110.     hAdmin.createTable(htd);   
  111.     HTable table = new HTable(conf, tableName);   
  112.     System.out.println("向表中插入數據");   
  113.     // 添加數據   
  114.     addRow(table, "1""info""name""peter");   
  115.     addRow(table, "1""info""email""[email protected]");   
  116.     addRow(table, "1""info""power""absorb abilities");   
  117.    
  118.     addRow(table, "2""info""name""hiro");   
  119.     addRow(table, "2""info""email""[email protected]");   
  120.     addRow(table, "2""info""power""bend time and space");   
  121.    
  122.     addRow(table, "3""info""name""sylar");   
  123.     addRow(table, "3""info""email""[email protected]");   
  124.     addRow(table, "3""info""power""hnow how things work");   
  125.    
  126.     addRow(table, "4""info""name""claire");   
  127.     addRow(table, "4""info""email""[email protected]");   
  128.     addRow(table, "4""info""power""heal");   
  129.    
  130.     addRow(table, "5""info""name""noah");   
  131.     addRow(table, "5""info""email""[email protected]");   
  132.     addRow(table, "5""info""power""cath the people with ablities");   
  133.   }   
  134.    
  135.   // 添加一條數據   
  136.   private static void addRow(HTable table, String row,    
  137. String columnFamily,String column, String value) throws IOException {   
  138.     Put put = new Put(Bytes.toBytes(row));   
  139.     // 參數出分別:列族、列、值   
  140.     put.add(Bytes.toBytes(columnFamily), Bytes.toBytes(column),   
  141.         Bytes.toBytes(value));   
  142.     table.put(put);   
  143.   }   
  144.    
  145.   // 創建數據庫表   
  146.   public static void createIndexTable(Configuration conf,    
  147. String tableName) throws Exception {   
  148.     // 新建一個數據庫管理員   
  149.     HBaseAdmin hAdmin = new HBaseAdmin(conf);   
  150.    
  151.     if (hAdmin.tableExists(tableName)) {   
  152.       System.out.println("該數據表已經存在,正在重新創建。");   
  153.       hAdmin.disableTable(tableName);   
  154.       hAdmin.deleteTable(tableName);   
  155.     }   
  156.    
  157.     // 新建一個表的描述   
  158.     HTableDescriptor tableDesc = new HTableDescriptor(tableName);   
  159.     // 在描述裏添加列族   
  160.     tableDesc.addFamily(new HColumnDescriptor(INDEX_COLUMN));   
  161.    
  162.     // 根據配置好的描述建表   
  163.     hAdmin.createTable(tableDesc);   
  164.     System.out.println("創建" + tableName + "表成功");   
  165.   }   
  166.    
  167.   public static Job configureJob(Configuration conf, String jobName)   
  168.       throws IOException {   
  169.     Job job = new Job(conf, jobName);   
  170.     job.setJarByClass(IndexBuilder.class);   
  171.    
  172.     // 設置 Map 處理類   
  173.     job.setMapperClass(Map.class);   
  174.    
  175.     // 設置 Reduce 個數   
  176.     job.setNumReduceTasks(0);   
  177.    
  178.     // 設置輸入和輸出格式   
  179.     job.setInputFormatClass(TableInputFormat.class);   
  180.     job.setOutputFormatClass(MultiTableOutputFormat.class);   
  181.    
  182.     return job;   
  183.   }   
  184.    
  185.   private static String convertScanToString(Scan scan)   
  186. throws IOException {   
  187.     ByteArrayOutputStream out = new ByteArrayOutputStream();   
  188.     DataOutputStream dos = new DataOutputStream(out);   
  189.     scan.write(dos);   
  190.     return Base64.encodeBytes(out.toByteArray());   
  191.   }   
  192.    
  193.   public static void main(String[] args) throws Exception {   
  194.     Configuration conf = HBaseConfiguration.create();   
  195.     conf.set("hbase.zookeeper.quorum""master");   
  196.     conf.set("hbase.zookeeper.property.clientPort""2181");   
  197.    
  198.     String tableName = "heroes";   
  199.     String columnFamily = "info";   
  200.     String[] fields = { "name""power" };   
  201.     // 第一步:初始化數據庫表   
  202.     IndexBuilder.initHBaseTable(conf, tableName);   
  203.    
  204.     // 第二步:創建索引表   
  205.     for (String field : fields) {   
  206.       IndexBuilder.createIndexTable(conf, tableName + "‐" + field);   
  207.     }   
  208.    
  209.     // 第三步:進行 MapReduce 處理   
  210.     conf.set("mapred.job.tracker""master:9001");   
  211.     conf.set(TableInputFormat.SCAN, convertScanToString(new Scan()));   
  212.     conf.set(TableInputFormat.INPUT_TABLE, tableName);   
  213.  // 設置傳遞屬性值   
  214.     conf.set("index.tablename", tableName);   
  215.     conf.set("index.familyname", columnFamily);   
  216.     conf.setStrings("index.fields", fields);   
  217.    
  218.     Job job = IndexBuilder.configureJob(conf, "Index Builder");   
  219.    
  220.     System.exit(job.waitForCompletion(true) ? 0 : 1);   
  221.   }   
  222. }  

編譯完成後,可在hbase shell下運行:list,查看所創建的表,其他命令來操作表,在此不再贅述。

該示例只有map,沒有reduce。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章