爲什麼要使用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下載後按照上面的來配置。