【C#】通过Thrift操作HBase系列

阅读更多

题外话:C#  调用 Java 的几种方法

1.将Java端的接口通过WebService方式发布,C#可以方便的调用

2.先使用C++ 通过 JNI 调用 Java,C# 调用C++的接口

3.使用开源的库直接使用C#调用Java ,详细信息请点击

4.使用IKVM实现C#调用Java,参考:http://www.ikvm.net/

 

之所以说这些,是因为自己这边客户端要调用HBase接口(Java实现),刚开始我是使用WS方式实现调用,这种方式很简单,而且通用性好。之后一段时间发现了上面所说的第三种方式,并成功调用,但是写这个库的哥们,好像没有维护自己写的这个库,里面有几个很明显的BUG,而且在循环调用的时间,会报内存错误,由于对JNI不太熟悉,也就放弃了这种方式,如果对这种方式感兴趣的童鞋可以给他完善一下,再提个醒,这个开源库依赖jvm.dll,只有32位的JavaJDK才行。至于第二种和第四种方式没有深入研究,在这也就不说了。

 

最终我并没有采用上面的任何一种方式,而我采用的是Thrift方式,虽然比Java API 慢一点,但也在可接受的范围之内。接下来就要进入正题了:

 

准备阶段:

1. 下载 Thrift 的源代码包,http://thrift.apache.org/

2. 下载 Thrift compiler for Windows ,http://www.apache.org/dyn/closer.cgi?path=/thrift/0.9.0/thrift-0.9.0.exe

生成Thrfit接口类:

1. 从HBase包中,得到HBase.Thrift文件。(..\hbase-0.94.6.1\src\main\resources\org\apache\hadoop\hbase\thrift 在此目录下)

2. 将Thrift-0.9.0.exe 与 HBase.Thrift文件放到同意目录下(当然也可以不在同一目录)

3. 进入命令行, Thrift-0.9.0.exe -gen CSharp HBase.Thrift此目录下就成了名为gen-csharp的文件夹

构建解决方案

该准备的项目代码都已完成,新建VS Project , 将Thrift 的源代码项目与刚刚生成的接口接口类引入。

【C#】通过Thrift操作HBase系列_第1张图片

开始集群的Thrift服务

hbase-daemon.sh start thrift   端口号默认9090

编写测试代码

【C#】通过Thrift操作HBase系列_第2张图片

通过HBase.Thrift 所生成的接口类中,其中Hbase.cs为核心类,所有客户端操作HBase的接口的定义和实现都在此类中,如果想查看Thrift服务端的代码,请参考HBase源代码。

以下是类中所定义的查询接口:

 

[java]  view plain copy print ?
 
  1. List getRow(byte[] tableName, byte[] row, Dictionary<byte[], byte[]> attributes);  
  2. List getRowWithColumns(byte[] tableName, byte[] row, List<byte[]> columns, Dictionary<byte[], byte[]> attributes);  
  3. List getRowTs(byte[] tableName, byte[] row, long timestamp, Dictionary<byte[], byte[]> attributes);  
  4. List getRowWithColumnsTs(byte[] tableName, byte[] row, List<byte[]> columns, long timestamp, Dictionary<byte[], byte[]> attributes);  
  5. List getRows(byte[] tableName, List<byte[]> rows, Dictionary<byte[], byte[]> attributes);  
  6. List getRowsWithColumns(byte[] tableName, List<byte[]> rows, List<byte[]> columns, Dictionary<byte[], byte[]> attributes);  
  7. List getRowsTs(byte[] tableName, List<byte[]> rows, long timestamp, Dictionary<byte[], byte[]> attributes);  
  8. List getRowsWithColumnsTs(byte[] tableName, List<byte[]> rows, List<byte[]> columns, long timestamp, Dictionary<byte[], byte[]> attributes);  
  9. int scannerOpenWithScan(byte[] tableName, TScan scan, Dictionary<byte[], byte[]> attributes);  
  10. int scannerOpen(byte[] tableName, byte[] startRow, List<byte[]> columns, Dictionary<byte[], byte[]> attributes);  
  11. int scannerOpenWithStop(byte[] tableName, byte[] startRow, byte[] stopRow, List<byte[]> columns, Dictionary<byte[], byte[]> attributes);  
  12. int scannerOpenWithPrefix(byte[] tableName, byte[] startAndPrefix, List<byte[]> columns, Dictionary<byte[], byte[]> attributes);  
  13. int scannerOpenTs(byte[] tableName, byte[] startRow, List<byte[]> columns, long timestamp, Dictionary<byte[], byte[]> attributes);  
  14. int scannerOpenWithStopTs(byte[] tableName, byte[] startRow, byte[] stopRow, List<byte[]> columns, long timestamp, Dictionary<byte[], byte[]> attributes);  
  15. List scannerGet(int id);  
  16. List scannerGetList(int id, int nbRows);  
  17. void scannerClose(int id);  

 

结合项目的应用介绍几个比较常用的接口(其实只要用过HBaseAPI的童鞋,上面这些接口就不在话下了):

1.getRow(这类查询简单,通过rowkey获取数据,接口的大部分参数类型为字节数组)

【C#】通过Thrift操作HBase系列_第3张图片

结果:

【C#】通过Thrift操作HBase系列_第4张图片

2.scannerOpenWithStop(通过RowKey的范围获取数据)

 

[csharp]  view plain copy print ?
 
  1.         ///   
  2.         /// 通过RowKey的范围获取数据  
  3.         ///   
  4.         ///   
  5.         ///   
  6.         ///   
  7.         /// 结果集包含StartRowKey列值,不包含EndRowKey的列值  
  8.         static void GetDataFromHBaseThroughRowKeyRange(string tablename,  
  9.             string stRowkey,string endRowkey)  
  10.         {  
  11.             transport.Open();  
  12.             int ScannerID = client.scannerOpenWithStop(Encoding.UTF8.GetBytes(tablename),   
  13.                 Encoding.UTF8.GetBytes(stRowkey), Encoding.UTF8.GetBytes(endRowkey),   
  14.                 new List<byte[]> { Encoding.UTF8.GetBytes("i:Data") }, null);  
  15.   
  16.             List reslut = client.scannerGetList(ScannerID, 100);  
  17.             foreach (var key in reslut)  
  18.             {  
  19.                 Console.WriteLine(Encoding.UTF8.GetString(key.Row));  
  20.   
  21.                 foreach (var k in key.Columns)  
  22.                 {  
  23.                     Console.Write(Encoding.UTF8.GetString(k.Key) + "\t");  
  24.                     Console.WriteLine(Encoding.UTF8.GetString(k.Value.Value));  
  25.                     Console.WriteLine("++++++++++++++++++++++++++++++++++++++");  
  26.                 }  
  27.             }  
  28.         }  
  29.   
  30.         //调用  
  31.         static void Main(string[] args)  
  32.         {  
  33.            GetDataFromHBaseThroughRowKeyRange("HStudy""001""006");  
  34.         }  

结果:

【C#】通过Thrift操作HBase系列_第5张图片

3.scannerOpenWithPrefix(通过RowKey的前缀进行匹配查询)

 

[csharp]  view plain copy print ?
 
  1. ///   
  2. /// 通过Rowkey前缀Fliter  
  3. ///   
  4. ///   
  5. ///   
  6. ///   
  7. static void GetDataFromHBaseThroughRowKeyPrefix(string tablename, string Prefixrowkey)  
  8. {  
  9.     transport.Open();  
  10.     int ScannerID = client.scannerOpenWithPrefix(Encoding.UTF8.GetBytes(tablename), Encoding.UTF8.GetBytes(Prefixrowkey), new List<byte[]> { Encoding.UTF8.GetBytes("i:Data") }, null);  
  11.     /* 
  12.     *  scannerGetList(string ID),源码中其实调用scannerGetList(string ID,int nbRow)方法,nbRow传值为1 
  13.     */  
  14.     List reslut = client.scannerGetList(ScannerID,100);             
  15.     foreach (var key in reslut)  
  16.     {  
  17.         Console.WriteLine(Encoding.UTF8.GetString(key.Row));  
  18.   
  19.         foreach (var k in key.Columns)  
  20.         {  
  21.             Console.Write(Encoding.UTF8.GetString(k.Key) + "\t");  
  22.             Console.WriteLine(Encoding.UTF8.GetString(k.Value.Value));  
  23.             Console.WriteLine("++++++++++++++++++++++++++++++++++++++");  
  24.         }  
  25.     }  
  26. }  
  27. /调用  
  28. static void Main(string[] args)  
  29. bsp;      {  
  30.    GetDataFromHBaseThroughRowKeyPrefix("HStudy""00");  
  31. }  

 

4.scannerOpenWithScan(通过过滤器进行查询)

这个接口是所有查询接口中最麻烦的一个吧,因为它用到了过滤器,也就是HBaseAPI中的Filter。这个接口的参数中有一个参数类型为TScan,基本结构如下:

 

[csharp]  view plain copy print ?
 
  1. public partial class TScan : TBase  
  2.    {  
  3.        private byte[] _startRow;  
  4.        private byte[] _stopRow;  
  5.        private long _timestamp;  
  6.        private List<byte[]> _columns;  
  7.        private int _caching;  
  8.        private byte[] _filterString;  
  9.    }  

 

 

前面的几个参数不多说,这里说一下_filterString (关于HaseAPI中各种Filter这里就不多说),以常见的SingleColumnValueFilter为例,如果我想定义一个查询PatientName为小红的一个过滤器:

            stringfilterString = "SingleColumnValueFilter('s','PatientName',=,'substring:小红')";

            byte[]_filterString = Encoding.UTF8.GetBytes(filterString);


如果要定义多个过滤器,过滤器之间用‘AND’连接。

 

[csharp]  view plain copy print ?
 
  1. ///   
  2. /// 通过Filter进行数据的Scanner  
  3. ///   
  4. ///   
  5. ///   
  6. static void GetDataFromHBaseThroughFilter(string tablename, string filterString,List<byte[]> _cols)  
  7. {  
  8.     TScan _scan = new TScan();  
  9.     //SingleColumnValueFilter('i', 'Data', =, '2')  
  10.     _scan.FilterString =Encoding.UTF8.GetBytes(filterString);  
  11.     _scan.Columns = _cols;  
  12.     transport.Open();  
  13.     int ScannerID = client.scannerOpenWithScan(Encoding.UTF8.GetBytes(tablename), _scan,null);  
  14.   
  15.     List reslut = client.scannerGetList(ScannerID, 100);  
  16.     foreach (var key in reslut)  
  17.     {  
  18.         Console.WriteLine(Encoding.UTF8.GetString(key.Row));  
  19.   
  20.         foreach (var k in key.Columns)  
  21.         {  
  22.             Console.Write(Encoding.UTF8.GetString(k.Key) + "\t");  
  23.             Console.WriteLine(Encoding.UTF8.GetString(k.Value.Value));  
  24.             Console.WriteLine("++++++++++++++++++++++++++++++++++++++");  
  25.         }  
  26.     }  
  27. }  
  28.   
  29.   
  30. static void Main(string[] args)  
  31. {  
  32.     ////GetDataFromHBaseThroughRowKeyRange("HImages", "123.456.1", "123.456.9");  
  33.     List<byte[]> _byte = new List<byte[]>();  
  34.     _byte.Add(Encoding.UTF8.GetBytes("s:PatientName"));  
  35.     _byte.Add(Encoding.UTF8.GetBytes("s:StudyInstanceUID"));  
  36.     _byte.Add(Encoding.UTF8.GetBytes("s:PatientSex"));  
  37.   
  38.     ////string filterString = "((SingleColumnValueFilter('s','PatientName',=,'substring:Jim')) AND (SingleColumnValueFilter('s','PatientSex',=,'substring:10')))";  
  39.     string filterString = "SingleColumnValueFilter('s','PatientName',=,'substring:小红')";             
  40.     GetDataFromHBaseThroughFilter("HStudy", filterString, _byte);  
  41.     Console.ReadLine();  
  42.   
  43. }  

说一下Thrift中使用很平凡的API(新建表,删除表,插入数据,更新数据,删除数据),最后发一下,为了方便使用Thrift写的一个Helper类。

 

 

[csharp]  view plain copy print ?
 
  1. void createTable(byte[] tableName, List columnFamilies);  
  2. void mutateRow(byte[] tableName, byte[] row, List mutations, Dictionary<byte[], byte[]> attributes);  
  3. void mutateRowTs(byte[] tableName, byte[] row, List mutations, long timestamp, Dictionary<byte[], byte[]> attributes);  
  4. void mutateRows(byte[] tableName, List rowBatches, Dictionary<byte[], byte[]> attributes);  
  5. void mutateRowsTs(byte[] tableName, List rowBatches, long timestamp, Dictionary<byte[], byte[]> attributes);  
  6. void deleteTable(byte[] tableName);  
  7. void deleteAll(byte[] tableName, byte[] row, byte[] column, Dictionary<byte[], byte[]> attributes);  
  8. void deleteAllTs(byte[] tableName, byte[] row, byte[] column, long timestamp, Dictionary<byte[], byte[]> attributes);  
  9. void deleteAllRow(byte[] tableName, byte[] row, Dictionary<byte[], byte[]> attributes);  
  10. void deleteAllRowTs(byte[] tableName, byte[] row, long timestamp, Dictionary<byte[], byte[]> attributes);  



值得注意的是,Thrift 插入行和更新行使用的同一函数(mutateRow等一类函数),使用过HBaseAPI的童鞋,这点不足为奇。这几个API都比较简单,下面我就直接贴出Helper类及简单的测试类。

 

 

[csharp]  view plain copy print ?
 
  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Text;  
  5. using System.Threading.Tasks;  
  6. using ThriftHelper;  
  7. using IThrift;  
  8. using Thrift.Transport;  
  9. using Thrift.Protocol;  
  10. namespace Test  
  11. {  
  12.     class Program  
  13.     {  
  14.         /* 
  15.          *   表名: HTest 
  16.          *   列簇: i 
  17.          *   子列: Data 
  18.          */  
  19.         static void Main(string[] args)  
  20.         {  
  21.             #region Test  
  22.   
  23.             Helper.Open();  
  24.             Printer("CreateTable:");  
  25.             ColumnDescriptor _cd = new ColumnDescriptor();  
  26.             _cd.Name = Encoding.UTF8.GetBytes("i");  
  27.   
  28.             if (Helper.CreateTable("ITest"new List { _cd }))  
  29.                 Printer("CreateTable is Success");  
  30.             else  
  31.                 Printer("CreateTable Occurred Error");  
  32.   
  33.             Printer("++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++");  
  34.             Printer("MutateRowHBase:");  
  35.             Mutation _mutation = new Mutation();  
  36.             _mutation.Column = Encoding.UTF8.GetBytes("i:one");  
  37.             _mutation.Value = Encoding.UTF8.GetBytes("1");  
  38.   
  39.             if (Helper.MutateRowHBase("ITest""001"new List { _mutation }))  
  40.                 Printer("MutateRowHBase is Success");  
  41.             else  
  42.                 Printer("MutateRowHBase Occurred Error");  
  43.   
  44.             Printer("++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++");  
  45.   
  46.             Printer("GetDataFromHBase:");  
  47.             List _result = Helper.GetDataFromHBase("ITest""001");  
  48.             Printer(_result);  
  49.   
  50.             Printer("++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++");  
  51.   
  52.             Printer("MutateRowHBase:");  
  53.             _mutation = new Mutation();  
  54.             _mutation.Column = Encoding.UTF8.GetBytes("i:one");  
  55.             _mutation.Value = Encoding.UTF8.GetBytes("-1");  
  56.   
  57.             if (Helper.MutateRowHBase("ITest""001"new List { _mutation }))  
  58.                 Printer("MutateRowHBase is Success");  
  59.             else  
  60.                 Printer("MutateRowHBase Occurred Error");  
  61.   
  62.             Printer("++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++");  
  63.   
  64.             Printer("GetDataFromHBase:");  
  65.             _result = Helper.GetDataFromHBase("ITest""001");  
  66.             Printer(_result);  
  67.   
  68.             Printer("++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++");  
  69.   
  70.             Printer("DeleteRow:");  
  71.             if (Helper.DeleteAllRow("ITest""001"))  
  72.                 Printer("DeleteAllRow is Success");  
  73.             else  
  74.                 Printer("DeleteAllRow Occurred Error");  
  75.             Helper.Close();  
  76.  
  77.  
  78.             #endregion  
  79.   
  80.             Console.ReadKey();  
  81.              
  82.         }  
  83.   
  84.         static void Printer(List reslut)  
  85.         {  
  86.             if (reslut.Count == 0)  
  87.                 return;  
  88.             foreach (var key in reslut)  
  89.             {  
  90.                 Console.WriteLine(Encoding.UTF8.GetString(key.Row));  
  91.   
  92.                 foreach (var k in key.Columns)  
  93.                 {  
  94.                     Console.Write(Encoding.UTF8.GetString(k.Key) + "\t");  
  95.                     Console.WriteLine(Encoding.UTF8.GetString(k.Value.Value));  
  96.                     Console.WriteLine("++++++++++++++++++++++++++++++++++++++");  
  97.                 }  
  98.             }  
  99.         }  
  100.         static void Printer(string conent)  
  101.         {  
  102.             Console.Write(conent);  
  103.         }  
  104.     }  
  105. }  

 

 

Helper类:

 

 

[csharp]  view plain copy print ?
 
  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Text;  
  5. using System.Threading.Tasks;  
  6. using Thrift;  
  7. using IThrift;  
  8. using Thrift.Transport;  
  9. using Thrift.Protocol;  
  10.   
  11. namespace ThriftHelper  
  12. {  
  13.     public static class Helper  
  14.     {  
  15.         static TTransport transport = new TSocket("192.168.2.200", 9090);  
  16.         static TProtocol tProtocol = new TBinaryProtocol(transport);  
  17.         static Hbase.Client client = new Hbase.Client(tProtocol);  
  18.   
  19.         public static void Open()  
  20.         {  
  21.             transport.Open();  
  22.         }  
  23.   
  24.         public static void Close()  
  25.         {  
  26.             transport.Close();  
  27.         }  
  28.   
  29.         ///   
  30.         /// 通过rowkey获取数据  
  31.         ///   
  32.         ///   
  33.         ///   
  34.         public static List GetDataFromHBase(string tablename, string rowkey)  
  35.         {  
  36.             List reslut = client.getRow(Encoding.UTF8.GetBytes(tablename), Encoding.UTF8.GetBytes(rowkey), null);  
  37.             return reslut;  
  38.         }  
  39.   
  40.         ///   
  41.         /// 通过Rowkey前缀Fliter  
  42.         ///   
  43.         ///   
  44.         ///   
  45.         ///   
  46.         public static List GetDataFromHBaseThroughRowKeyPrefix(string tablename, string Prefixrowkey,List<string> _cols)  
  47.         {  
  48.             List<byte[]> _bytes = new List<byte[]>();  
  49.             foreach (string str in _cols)  
  50.                 _bytes.Add(Encoding.UTF8.GetBytes(str));  
  51.   
  52.               
  53.             int ScannerID = client.scannerOpenWithPrefix(Encoding.UTF8.GetBytes(tablename), Encoding.UTF8.GetBytes(Prefixrowkey),  
  54.                 _bytes, null);  
  55.             /* 
  56.             *  scannerGetList(string ID),源码中其实调用scannerGetList(string ID,int nbRow)方法,nbRow传值为1 
  57.             */  
  58.             List reslut = client.scannerGetList(ScannerID, 100);  
  59.             return reslut;  
  60.         }  
  61.   
  62.         ///   
  63.         /// 通过RowKey的范围获取数据  
  64.         ///   
  65.         ///   
  66.         ///   
  67.         ///   
  68.         /// 结果集包含StartRowKey列值,不包含EndRowKey的列值  
  69.         public static List GetDataFromHBaseThroughRowKeyRange(string tablename,  
  70.             string stRowkey, string endRowkey,List<string> _cols)  
  71.         {  
  72.             List<byte[]> _bytes = new List<byte[]>();  
  73.             foreach (string str in _cols)  
  74.                 _bytes.Add(Encoding.UTF8.GetBytes(str));  
  75.   
  76.               
  77.             int ScannerID = client.scannerOpenWithStop(Encoding.UTF8.GetBytes(tablename),  
  78.                 Encoding.UTF8.GetBytes(stRowkey), Encoding.UTF8.GetBytes(endRowkey),  
  79.                 _bytes, null);  
  80.   
  81.             List reslut = client.scannerGetList(ScannerID, 100);  
  82.             return reslut;  
  83.         }  
  84.   
  85.         ///   
  86.         /// 通过Filter进行数据的Scanner  
  87.         ///   
  88.         ///   
  89.         ///   
  90.         public static List GetDataFromHBaseThroughFilter(string tablename, string filterString, List<byte[]> _cols)  
  91.         {  
  92.             TScan _scan = new TScan();  
  93.             //SingleColumnValueFilter('i', 'Data', =, '2')  
  94.             _scan.FilterString = Encoding.UTF8.GetBytes(filterString);  
  95.             _scan.Columns = _cols;  
  96.               
  97.             int ScannerID = client.scannerOpenWithScan(Encoding.UTF8.GetBytes(tablename), _scan, null);  
  98.   
  99.             List reslut = client.scannerGetList(ScannerID, 100);  
  100.             return reslut;  
  101.         }  
  102.   
  103.         public static bool MutateRowHBase(string tablename, string rowkey, List _mutations)  
  104.         {  
  105.             try  
  106.             {  
  107.                 client.mutateRow(Encoding.UTF8.GetBytes(tablename), Encoding.UTF8.GetBytes(rowkey), _mutations, null);  
  108.                 return true;  
  109.             }  
  110.             catch (Exception e)  
  111.             {  
  112.                 return false;  
  113.             }  
  114.         }  
  115.   
  116.         public static bool MutateRowsHBase(string tablename, List _BatchMutation)  
  117.         {  
  118.             try  
  119.             {  
  120.                 client.mutateRows(Encoding.UTF8.GetBytes(tablename), _BatchMutation, null);  
  121.                 return true;  
  122.             }  
  123.             catch (Exception e)  
  124.             {  
  125.   
  126.                 return false;  
  127.             }  
  128.   
  129.         }  
  130.   
  131.         public static bool DeleteRowHBase(string tablename, string rowkey, string column)  
  132.         {  
  133.             try  
  134.             {  
  135.                 client.deleteAll(Encoding.UTF8.GetBytes(tablename), Encoding.UTF8.GetBytes(rowkey),  
  136.                     Encoding.UTF8.GetBytes(column), null);  
  137.                 return true;  
  138.             }  
  139.             catch (Exception e)  
  140.             {  
  141.   
  142.                 return false;  
  143.             }  
  144.   
  145.         }  
  146.   
  147.         public static bool DeleteAllRow(string tablename, string rowkey)  
  148.         {  
  149.             try  
  150.             {  
  151.                 client.deleteAllRow(Encoding.UTF8.GetBytes(tablename), Encoding.UTF8.GetBytes(rowkey), null);  
  152.                 return true;  
  153.             }  
  154.             catch (Exception e)  
  155.             {  
  156.                 return false;  
  157.             }  
  158.              
  159.         }  
  160.   
  161.         public static bool DeleteTable(string tablename)  
  162.         {  
  163.             try  
  164.             {  
  165.                 client.deleteTable(Encoding.UTF8.GetBytes(tablename));  
  166.                 return true;  
  167.             }  
  168.             catch (Exception e)  
  169.             {  
  170.                 return false;  
  171.             }  
  172.               
  173.         }  
  174.   
  175.         public static bool CreateTable(string tablename, List _cols)  
  176.         {  
  177.             try  
  178.             {  
  179.                 client.createTable(Encoding.UTF8.GetBytes(tablename), _cols);  
  180.                 return true;  
  181.             }  
  182.             catch (Exception e)  
  183.             {  
  184.                 return false;  
  185.             }  
  186.               
  187.         }  
  188.     }  
  189. }  



好了,关于Thrift的基本操作就写到这,当然Thrift也支持Hbase中比较高级的操作,在以后的博客会不断更新。谢谢大家,个人水平有限,不足之处请谅解。

 

 

你可能感兴趣的:(Hbase)