• 如果您觉得本站非常有看点,那么赶紧使用Ctrl+D 收藏吧

.net hbase client–终于浮出水面的轮子

开发技术 开发技术 1天前 7次浏览

一、开篇

1.背景

大数据时代,HBase 数据库是个绕不开的热门话题。 由于其使用 Java 作为主要开发语言,并且依赖大量的 Java 组件(如 Hadoop、zooKeep),使得其他技术栈想要有一个对应的 hbase 客户端变得有一定难度。在 .net 的世界中,一直缺乏能够直接访问 hbase 的客户端。

2.历程

Apache Thrift 作为社区内比较有名的支持多语言的 Api 服务,可以解决跨语言访问 HBase 数据库的痛点。在以往的文章中业也介绍过 C#如何使用 thrift 访问 hbase,但在真正的生产环境中,该方式的访问效率和原生 Java 客户端比起来真着实让人心灰意冷。此外,thrift 也要求服务端和客户端版本一致。

Protocol Buffers HBase 提供基于 Protocol 的数据访问,这以一种相对高效紧凑的数据交换规则。基于此,我们能够造出属于 .net 的 hbase 客户端。

这是一个造轮子的过程,中间虽有着许多难点就不再赘述。下面直接介绍该项目的使用。

二、HBaseNet 使用

1.HBase 数据库准备

作为项目使用演示,我们就不讨论如何搭建 HBase 集群了,一切以简单便捷为前提,直接使用别人构建好的 docker 镜像就可以轻松获取 HBase 数据库的使用。

在 dockerhub 中搜索 hbase 或者命令行:docker search hbase。结果中找到dajobe/hbase,将其 pull 到本地就行。可以按照作者教程进行部署。其核心操作也就几个简单命令,现作一简单摘抄:

docker pull dajobe/hbase # 拉取镜像到本地
mkdir data # 创建名为data的目录
id=$(docker run --name=hbase-docker -h hbase-docker -d -v $PWD/data:/data dajobe/hbase) #将hbase-docker设置为主机名运行,并将docker容器id赋值给id

命令行docker inspect hbase-docker|grep IPAddress查看 hbase 主机地址:

"SecondaryIPAddresses": null,
"IPAddress": "172.17.0.2",
        "IPAddress": "172.17.0.2",

可以看到我的在 172.17.0.2 上,我们可以直接浏览器访问http://172.17.0.2:16010/,看到habse的主页说明部署成功。此外,最好将本地物理机的hosts修改以作映射,文件中添加一行172.17.0.2 hbase-docker即可。

2.HBaseNet 简单演示

演示项目创建

首先创建控制台项目dotnet new console -o HBaseNetTest,然后添加 HBaseNet 客户端 nuget dotnet add package HBaseNet --version 0.1.0-rc2-final

使用 AdminClient 创建 HBase 表

直接在主函数中写下如下代码:

static async Task Main(string[] args)
{
    // 注意在hosts中添加地址映射
    var ZkQuorum = "hbase-docker";
    var admin = await new AdminClient(ZkQuorum).Build();
    if (admin == null) return;
    var table = "products";
    var cols = new[] { new ColumnFamily("info") };//名为info的列簇
    var create = new CreateTableCall(table, cols)
    {
        SplitKeys = new[] { "8" }// 预分区
    };
    //简单判断表是否存在
    var tables = await admin.ListTableNames(new ListTableNamesCall { Regex = table });
    if (true != tables?.Any())
    {
        //使用高级客户端创建products表
        var createResult = await admin.CreateTable(create);
        Console.WriteLine($"创建表{table}的结果:{createResult}.");
    }
    else
    {
        Console.WriteLine($"表{table}已经存在");
    }
}

运行后控制台输出创建表products的结果:True.。我们再查看主页http://hbase-docker:16010/,找到Tables,可以看到 products 表已经被创建:

default	products	ENABLED	2	0	0	0	0	0	0	0	'products', {NAME => 'info', VERSIONS => '3', DATA_BLOCK_ENCODING => 'FAST_DIFF', BLOCKCACHE => 'False', METADATA => {'TTl' => '2147483647'}}

使用 StandardClient 进行数据的写入和查询

var client = await new StandardClient(ZkQuorum).Build();
if (client == null) return;
var rowKey = "123";
var values = new Dictionary<string, IDictionary<string, byte[]>>
{
    {
        "info", new Dictionary<string, byte[]>
        {
            {"key", "value".ToUtf8Bytes()}
        }
    }
};
//放入一条数据
var rs = await client.Put(new MutateCall(table, rowKey, values));
Console.WriteLine($"放入数据key:{rowKey},结果:{rs.HasProcessed}");
// 根据rowkey获取一条数据
var getResult = await client.Get(new GetCall(table, rowKey));
Console.WriteLine($"获取数据结果key:{rowKey}");
// 使用scanner进行数据扫描
var sc = new ScanCall(table, "1", "")
{
    NumberOfRows = 1000
};
using var scanner = client.Scan(sc);
var scanResults = new List<Result>();
while (scanner.CanContinueNext)
{
    var per = await scanner.Next();
    if (true != per?.Any()) continue;
    scanResults.AddRange(per);
}
Console.WriteLine($"扫描数据共返回结果:{scanResults.Count}行");

控制台输出:

放入数据key:123,结果:True
获取数据结果key:123
扫描数据共返回结果:1行

日志配置

为了方便友好,建议还是开启日志进行使用。这里就以使用Serilog为例,添加以下 nuget 包:

dotnet add package Serilog --version 2.10.0-dev-01226
dotnet add package Serilog.Sinks.Console --version 4.0.0-dev-00839
dotnet add package Microsoft.Extensions.DependencyInjection --version 5.0.0-preview.7.20364.11

在主函数最上面添加:

Log.Logger = new LoggerConfiguration()
    .Enrich.FromLogContext()
    .MinimumLevel.Debug()
    .WriteTo.Console(
        outputTemplate: "[{Timestamp:yyyy-MM-dd HH:mm:ss} {Level:u3}] {Message:lj}{NewLine}{Exception}")
    .CreateLogger();
HBaseConfig.Instance.ServiceProvider = new ServiceCollection()
    .AddLogging(cfg => cfg.AddSerilog(Log.Logger))
    .BuildServiceProvider();

更多细节可以参考项目里的示例代码HBaseNet.Console。

三、最后

在 .neter 中使用 hbase 的人极少,多数人还是在抱怨生态不好。但想一想自己能够做什么,付诸行动总是比无谓的抱怨要好很多的。HBaseNet是一个刚开始的项目,捂了(肝了)几个月还是把它做出来了。如果对它感兴趣,欢迎加入我们或者提出宝贵的修改意见。当然,我最终的愿望是希望它对您有用。开源不易,非常欢迎到项目主页进行 star 鼓励。

感谢。


喜欢 (0)