说明

在上一篇文章dotnetcore 与 hbase 之二——thrift 客户端的制作中已经可以找到 c# hbase 客户端的使用方法了,为什么这里单独列出一篇文章来讲述呢?最简单的理由就是,本篇将为客户端的使用讲述一些简化性工作以及需要注意的事项。为此,我们做了一些工作HbaseNetCore

存在的差异

在 c# hbase 客户端中,接口基本只接受或返回 byte 数组型的参数,比如:

  Task<List<byte[]>> getTableNamesAsync(CancellationToken cancellationToken); # 获取所有hbase中的表名
Task<List<TRowResult>> getRowAsync(byte[] tableName, byte[] row, Dictionary<byte[], byte[]> attributes, CancellationToken cancellationToken); # 根据rowkey获取一行数据

所以,大多数的工作将是 customer's class 与 byte array 之间的转换。需要注意的事项正是来源于 c#与 java 的一些差异。

1. byte 数组大小端

在我的工作中遇到的 java 主要使用类org.apache.hadoop.hbase.util.Bytes来进行二进制化(例如:Bytes.toBytes(/**/)),以此来达到和 hbase 进行数据交换的目的。在 Java 中 byte 数组与网络字节流采取一致的大小端模式——大端模式。而在 c#中,主要使用类System.BitConverter来获取二进制流,得到的 bytes 结果是小端模式的。因此,为了通用,我们需要使用Array.Reverse()方法来进行大小端反转。也可以使用System.Net.IPAddress.HostToNetworkOrder()来直接获取网络字节顺序的 bytes。但是其结果不是 byte[],仍然需要使用System.BitConverter来获取 byte[]。此外,单字节编码的字符串(比如:ASCII 、utf-8)不存在大小端的问题,双字节及以上需要注意大小端(比如:utf-16、GB2312)。

2. 基本值类型的对应

在 Java 中,基本数据类型(byte、short、int、long、float、double、char、boolean)中不存在无符号型。而在 c#中(bool、byte、char、decimal、double、float、int 32、long、sbyte、short、uint、ulong、ushort)有无符号型。所以在使用数据类型上需要注意对应。此外,二者在布尔类型上也有差异。从转换的 byte[]中可以看出来:

//java
true:[-1]
false:[0]
//c#
true:01 # 幸运的是所有非零值转bool都是true。BitConverter.ToBoolean(BitConverter.GetBytes((sbyte)-1))
false:00

在 java 中,short 是 4 字节的,而 c#中仅为 2 字节:

//java
System.out.println("short:" + Arrays.toString(Bytes.toBytes('d')));
short:[0, 0, 0, 100] # 十进制
//c#
Console.WriteLine($"short:{BitConverter.ToString(((short)'d').ToBytes())}");# 注意:方法ToBytes获取了bytes并反转了大小端
short:00-64 # 十六进制

customer's class 与 byte array 之间的转换

为了提高工作效率,需要做一些转换工具,以此来减少 byte[]与用户数据之间的徒手转换工作。

1. 为 hbase 仓储而创建的特性与接口

特性类 HbaseTableAttribute 构造函数接受一个可选参数,以此指明与 hasee 对应的表名。

public HbaseTableAttribute(string table = null)

特性类 HbaseColumnAttribute 构造函数接受两个可选参数,以此指明列簇名与列名

public HbaseColumnAttribute(string family = DefaultFamily, string column = null)

接口 IHbaseTable 强制提供 byte[]转换为用户类时提供的 RowKey 属性。

public interface IHbaseTable
{
string RowKey { get; set; }
}

举一student类为例:

[HbaseTable("student")]
public class Student : IHbaseTable
{
public string RowKey { get; set; }
[HbaseColumn]
public string Name { get; set; }
[HbaseColumn]
public int Age { get; set; }
[HbaseColumn]
public bool IsWork { get; set; }
public DateTime JoinSchool { get; set; }
[HbaseColumn]
public List<string> Hobbies { get; set; }
}

2.为 c# hbase 客户端与用户类之间转换创建的辅助工具类

目前实现的转换接口有:

public interface IHbaseParser
{
//用户类转 hbase 客户端
List<Mutation> ToMutations<T>(T obj) where T : class;
//用户类转 hbase 客户端
BatchMutation ToBatchMutation<T>(T obj) where T : class, IHbaseTable;
//用户类集合转 hbase 客户端
List<BatchMutation> ToBatchMutations<T>(IEnumerable<T> objs) where T : class, IHbaseTable;
// hbase 客户端转用户类
T ToReal<T>(TRowResult trr) where T : class, IHbaseTable, new();
// hbase 客户端转用户类集合
List<T> ToReals<T>(IEnumerable<TRowResult> trrs) where T : class, IHbaseTable, new();
}

帮助性接口:

 public interface IHbaseHelper
{
//获取特性HbaseTableAttribute中的表名
string GetTableName<T>() where T : class, new();
//获取特性HbaseColumnAttribute中的列簇名
List<string> GetTableColumnNames<T>() where T : class, new();
}

使用方式如:

//c# hbase 客户端准备
var _clientTransport = new TSocketClientTransport(IPAddress.Loopback, 9090);
var protocol = new TBinaryProtocol(_clientTransport);
var _client = new Hbase.Client(protocol);
var _hbaseHelper = new HbaseHelper();
var _HbaseParser = new HbaseParser(); var cancel = new CancellationToken();
//在hbase创建表
var table = _hbaseHelper.GetTableName<Student>();
var colNames = _hbaseHelper.GetTableColumnNames<Student>();
var columnFamilies = colNames
.Select(t => new ColumnDescriptor { Name = t.ToBytes() })
.ToList();
await _client.createTableAsync(table.ToBytes(), columnFamilies, cancel); //写入1000条数据
var range = Enumerable.Range(0, 1000).ToList();
var students = range
.Select(t => new Student { RowKey = t.ToString().Reverse2String(), Name = $"hsx{t}", Age = t })
.ToList();
students.Last().Hobbies = new List<string> { "running", "dance" };
students.Last().IsWork = true;
var batchs = _HbaseParser.ToBatchMutations(students);
await _client.mutateRowsAsync(table.ToBytes(), batchs, null, cancel); //从‘0’开始扫描数据
var id = await _client.scannerOpenAsync(
table.ToBytes(),
"0".ToBytes(),
null,
null,
cancel);
students = new List<Student>();
List<Student> perStudents = null;
do
{
var tRows = await _client.scannerGetListAsync(id, 500, cancel);
perStudents = _HbaseParser.ToReals<Student>(tRows);
students.AddRange(perStudents);
} while (perStudents?.Count > 0);

总结

虽然我们可以进行 hbase 的读写,但是效率上的差距依然明显,基本在几倍的读性能差距上,写数据性能差异尚未测试。作为 net 了解 hbase 的一个学习窗口吧。

更多细节,请查看HbaseNetCore项目。c# hbase 客户端基本告一段落,如有更新,也基本只会出现在本项目源代码中。

dotnetcore 与 hbase 之三——c# for hbase 客户端的使用的更多相关文章

  1. HBase(一): c#访问hbase组件开发

    HDP2.4安装系列介绍了通过ambari创建hbase集群的过程,但工作中一直采用.net的技术路线,如何去访问基于Java搞的Hbase呢? Hbase提供基于Java的本地API访问,同时扩展了 ...

  2. HBase轻松入门之HBase架构图解析

    2018-12-13 2018-12-20 本篇文章旨在针对初学者以我本人现阶段所掌握的知识就HBase的架构图中各模块作一个概念科普.不对文章内容的“绝对.完全正确性”负责. 1.开胃小菜 关于HB ...

  3. Hbase理论&&hbase shell&&python操作hbase&&python通过mapreduce操作hbase

    一.Hbase搭建: 二.理论知识介绍: 1Hbase介绍: Hbase是分布式.面向列的开源数据库(其实准确的说是面向列族).HDFS为Hbase提供可靠的底层数据存储服务,MapReduce为Hb ...

  4. 【HBase调优】Hbase万亿级存储性能优化总结

    背景:HBase主集群在生产环境已稳定运行有1年半时间,最大的单表region数已达7200多个,每天新增入库量就有百亿条,对HBase的认识经历了懵懂到熟的过程.为了应对业务数据的压力,HBase入 ...

  5. 【HBase】zookeeper在HBase中的应用

    转自:http://support.huawei.com/ecommunity/bbs/10242721.html Zookeeper在HBase中的应用 HBase部署相对是一个较大的动作,其依赖于 ...

  6. Hbase框架原理及相关的知识点理解、Hbase访问MapReduce、Hbase访问Java API、Hbase shell及Hbase性能优化总结

    转自:http://blog.csdn.net/zhongwen7710/article/details/39577431 本blog的内容包含: 第一部分:Hbase框架原理理解 第二部分:Hbas ...

  7. HBase(十)HBase性能调优总结

    一. HBase的通用优化 1 高可用 在 HBase 中 Hmaster 负责监控 RegionServer 的生命周期,均衡 RegionServer 的负载,如果 Hmaster 挂掉了,那么整 ...

  8. HBase(九)HBase表以及Rowkey的设计

    一 命名空间 1 命名空间的结构 1) Table:表,所有的表都是命名空间的成员,即表必属于某个命名空间,如果没有指定, 则在 default 默认的命名空间中. 2) RegionServer g ...

  9. HBase(八)HBase的协处理器

    一.协处理器简介 1. 起源 Hbase 作为列族数据库最经常被人诟病的特性包括:无法轻易建立“二级索引”,难以执 行求和.计数.排序等操作.比如,在旧版本的(<0.92)Hbase 中,统计数 ...

随机推荐

  1. 小程序 跳转web-view 点击左上角返回需要点击2次才能返回

    小程序  跳转web-view  点击左上角返回需要点击2次才能返回 再html页面引入js即可解决 <script type="text/javascript" src=& ...

  2. C++操作Mysql数据库/Linux下

    本文链接:https://blog.csdn.net/Tanswer_/article/details/72796570想用C++写项目,数据库是必须的,所以这两天学了一下C++操作Mysql数据库的 ...

  3. Oracle列信息表 all_tab_columns中的data_length和data_precision字段区别

    Oracle列信息表 all_tab_columns中的data_length和data_precision字段区别 区别: 这两个属性都属于user_tab_columns视图,他们的含义:1,da ...

  4. Andorid SQLite数据库开发基础教程(3)

    Andorid SQLite数据库开发基础教程(3) 数据库生成方式 数据库的生成有两种方式,一种是使用数据库管理工具生成的数据库,我们将此类数据库称为预设数据库,另一种是使用代码生成的数据库. 使用 ...

  5. flutter DateTime日期&时间选择器

    import 'package:flutter/material.dart'; import 'package:intl/intl.dart'; import 'dart:async'; class ...

  6. 开源配置中心xxl-conf的核心原理分析

    XXL-CONF是一款轻量级的开源配置中心项目,由国内大牛许雪里开发.下面是官方对其优点作出的描述: 一个轻量级分布式配置管理平台,拥有"轻量级.秒级动态推送.多环境.跨语言.跨机房.配置监 ...

  7. ASP中如何将数据库内容导入到数组?并进行字符串对比

    dim Arr sql1="select id from [aaa] where reader not like '%"&userid&"%'" ...

  8. android多图选择器 图片/视频 单选or多选,以及视频录制。

    PictureSelector 最近项目中用到多图选择上传的需求,考虑到android机型众多问题就自己花时间写了一个,测试了大概60款机型,出现过一些问题也都一一修复了,基本上稳定了特分享出来,界面 ...

  9. nginx client_body_buffer_size

    http://www.bubuko.com/infodetail-1760832.html 上传文件过大时,nginx会报链接里面的warn,请求body写磁盘到缓存文件,导致性能降低,可适当调大该参 ...

  10. php mkdir没有权限不能创建成功的问题

    php用mkdir创建目录时,必须保证要创建的目录的父级目录有用户权限才行, 比如当前执行脚本的用户是www用户,要创建的目录是/data/www/bbs/attach/2018 则/data/www ...