azure databricks使用external hive metastore跨工作区共享元数据
为什么要使用external hive metastore
可以跨workspace的共享元数据,不用每次创建workspace的时候都重复的把元数据重建一次。
更好的元数据集中管理,Create once, use everywhere。
为灾难恢复(DR)做好为准备,并降低复杂性。(PAAS一样会存在意外的,不要以为不会,所以DR是必须的)
可以更好控制元数据存储DB的一些配置,比如常见的字符集问题导致视图不能使用非ascii码而无法查询出数据
元数据存储在自己的数据库中,可以和其它的产品(数据治理或者资产软件)做整合。
实现环境
azure china
创建azure SQL
步骤1:创建数据库服务器
底部输入服务器管理员账号名和密码
后面的配置默认或者按需自己设置即可,最后点击创建
步骤2:配置网络和private endpoint
后面把所有databricks的子网都加进去来
步骤3:创建数据库用于存储hive metadata
配置数据库:我这是测试,创建一个简单的即可
排序规则要注意:如果你有中文comment、视图中有中文,这里不要用默认的,建议选择Chinese_PRC_CI_AS,可以防止中文乱码,比如开头说的视图乱码问题导致无法查询出数据的问题。
其它默认配置,点击创建即可。
注意:如果使用severless并且设置了自动启停,不建议开启replicas服务,因为可能导致会一直有链接,从而导致自动启停无法生效的,就会一直计费。
创建hive metadata元数据
步骤1:下载hive建表语句脚本。
从此处下载用于创建 Hive 元数据的 DDL 脚本。由于我使用的databricks runtime是11.3,因此我选择了2.3.9版本。
具体的差异可以参阅下微软官网:外部 Apache Hive 元存储 - Azure Databricks | Microsoft Learn
步骤2:执行建表语句
找到建表语句,copy内容,到db中执行即可。
步骤3:创建hive db独立的读写账号
用管理员账号登录到server上,选择master数据库,执行如下SQL
-- master db执行,创建Login
CREATE LOGIN hivedbadmin WITH password='xxx';
CREATE USER hivedbadmin FOR LOGIN hivedbadmin WITH DEFAULT_SCHEMA=[dbo]
在hive metadata db上创建用户和授权
-- hiveextmetadatadb 上执行,创建user并授权db_owner角色
CREATE USER hivedbadmin FROM LOGIN hivedbadmin;
EXEC sp_addrolemember 'db_owner', 'hivedbadmin';
验证登录
如果服务器禁止了公网访问,则需要添加白名单IP到database的fire rule里面,否则会一直报错说登录失败
-- master DB执行
EXEC [sys].[sp_set_database_firewall_rule] N'Allow Azure', '120.235.19.25', '120.235.19.25';
-- 注意:sp_set_firewall_rule是服务器级别的,服务器级别和database级别是独立的
databricks集群配置
我们需要分别创建两个workspace。
我们测试两个hive version的,一个是2.3.7,这个配套Databricks Runtime7.0-9.X使用。一个是2.3.9.这个配套Databricks Runtime 10.0 及更高版本
两个workspace都配置访问同一个key vault,用于访问sql的账号密码,key vault自行配置
Hive 2.3.7 (Databricks Runtime 7.0 - 9.x)
注意:
databricks 运行时版本 9.1,因此按照微软官网的建议,将 hive 版本设置为 2.3.7:spark.sql.hive.metastore.version 2.3.7
spark.sql.hive.metastore.jars builtin,对于2.3.7我测试是不行的,要先设置成maven,执行任意sql命令,让他下载jar包,然后把jar包放到dbfs固定地方,然后用init script把jar包cp到本地,然后把builtin换成这个jar的路径,具体可以参考我历史的文章:【原创】Databricks 更改hive metastore version - John.Xiong - 博客园 (cnblogs.com)
对于密码,可以使用机密。我们需要提供如下配置值:spark.hadoop.javax.jdo.option.ConnectionPassword {{secrets/xxxscope/xxxsecretname}}
以明文形式提供了密码,不建议这样做。
hive metadata db不要有-(横线),我测试会报错,建议最好就是一连串的字母。
在第1个workspace创建cluster:wk1-cluster9.1-2.3.7,选择9.1 LTS runtime,在spark config中设置如下:
spark.hadoop.javax.jdo.option.ConnectionDriverName com.microsoft.sqlserver.jdbc.SQLServerDriver spark.hadoop.javax.jdo.option.ConnectionURL jdbc:sqlserver://aaslab-sql.database.chinacloudapi.cn:1433;database=hiveextmetadatadb;encrypt=true;trustServerCertificate=false;hostNameInCertificate=*.database.chinacloudapi.cn;loginTimeout=30; spark.hadoop.javax.jdo.option.ConnectionUserName {{secrets/aaslab-kv1/hive-metastore-db-user}} spark.hadoop.javax.jdo.option.ConnectionPassword {{secrets/aaslab-kv1/hive-metastore-db-userpwd}} spark.sql.hive.metastore.jars /databricks/hive_metastore_jars/* spark.sql.hive.metastore.version 2.3.7
/databricks/hive_metastore_jars/*,是因为我提前jar包下载下来了,具体参考注意中说的文章。
在init scripts中要配置下那个cp jar的脚本
%python dbutils.fs.put("/databricks/scripts/hive-metastore-init",""" #!/bin/bash sleep 10s mkdir -p /databricks/hive_metastore_jars && cp -r /dbfs/lib/hive_metastore_jars/* /databricks/hive_metastore_jars """, True)
创建mount
%python storageAccountName = "storage account" fileSystemName = "blob container" appID = "xxx" tenantID = "xxx" configs = {"fs.azure.account.auth.type": "OAuth", "fs.azure.account.oauth.provider.type": "org.apache.hadoop.fs.azurebfs.oauth2.ClientCredsTokenProvider", "fs.azure.account.oauth2.client.id": appID, "fs.azure.account.oauth2.client.secret": dbutils.secrets.get(scope="aaslab-kv1",key="aas-lab-sp-secret"), "fs.azure.account.oauth2.client.endpoint": "https://login.partner.microsoftonline.cn/{0}/oauth2/token".format(tenantID)} dbutils.fs.mount( source = "abfss://{0}@{1}.dfs.core.chinacloudapi.cn/".format(fileSystemName, storageAccountName), mount_point = "/mnt/aaslabdw", extra_configs = configs)
创建db和table
%python spark.sql("create database if not exists mytestDB") #read the sample data into dataframe df_flight_data = spark.read.csv("/databricks-datasets/flights/departuredelays.csv", header=True) #create the delta table to the mount point that we have created earlier dbutils.fs.rm("/mnt/aaslabdw/mytestDB/flight_data", recurse=True) df_flight_data.write.format("delta").mode("overwrite").save("/mnt/aaslabdw/mytestDB/flight_data") spark.sql("drop table if exists mytestDB.flight_data") spark.sql("create table if not exists mytestDB.flight_data using delta location '/mnt/aaslabdw/mytestDB/flight_data'")
查询数据
view也不会乱码
在第2个workspace创建cluster:wk2-cluster9.1-2.3.7,选择9.1 LTS runtime,在spark config中设置如下,当然也是要按照注意那里引用的文章中的一样先下载下来jar,再配置才可以的。(当然也可以直接把workspace1的那些jar通过dbfs cli下载下来,直接传到2的dbfs上也可以的,更快)
启用后可以直接看到db、table等元数据了,但是浏览table时候会报错,报路径不存在。
执行一样的mount命令,mount一样的路径到workspace2即可。
正确在space2读取到数据
最后把spark config和init scripts等保持了space1中cluster1一样即可。
Hive 2.3.9(Databricks Runtime 10.0 及更高版本)
类似的操作,只是把spark.sql.hive.metastore.version设置为2.3.9,也是先maven下载,再配置固定的jars路径。
注意:如果同一个workspace下有多个cluster是不同版本的hive version,jars存储的路径要分开下。
例如workspace2里面创建了一个2.3.9的hive版本的cluster,我还是要访问同样的元数据,我需要下载2.3.9的jar到一个新的dbfs目录,防止冲突,然后init script也是从新的jars目录copy到cluster VM的目录上
%python dbutils.fs.put("/databricks/scripts/hive-metastore-init-239",""" #!/bin/bash sleep 10s mkdir -p /databricks/hive_metastore_jars_239 && cp -r /dbfs/lib/hive_metastore_jars_239/* /databricks/hive_metastore_jars_239 """, True)
遇到的错误
1、org.apache.spark.sql.AnalysisException: org.apache.hadoop.hive.ql.metadata.HiveException: java.lang.RuntimeException: Unable to instantiate org.apache.hadoop.hive.ql.metadata.SessionHiveMetaStoreClient
ans:对应的jar包版本应该不对,需要maven下载后按照上面的来配置。
作者:DataStrategy
出处:https://www.cnblogs.com/xiongnanbin/
联系:1183744742@qq.com;xiongnanbin@126.com
本文版权归作者和博客园共有(转载的归原作者所有),欢迎转载,但是请在文章页面明显位置给出原文连接。如有问题或建议,请多多留言、赐教,非常感谢。