開源的Spark SQL并不支持高可用,但實際應用中高可用對于用戶意義重大。中興大數據平臺DAP在對應的ZDH中實現了Spark SQL的高可用。
Spark SQL的高可用,是兩個Spark SQL服務上線的時候向SQL進行注冊,用戶連接的JDBC URL指定為Zookeeper的列表,連接的時候會通過Zookeeper集群獲取Spark SQL節(jié)點信息,然后連接到Spark SQL服務節(jié)點。
Spark SQL元數據雙主主要是用MySQL實現,MySQL支持單向、異步復制,復制過程中一個服務器充當主服務器,而一個或多個其它服務器充當從服務器。主服務器將更新寫入二進制日志文件,并維護日志文件的索引以跟蹤日志循環(huán)。從服務器接收從那時起發(fā)生的任何更新,然后封鎖并等待主服務器通知下一次更新。
在實際項目中,兩臺分布于異地的主機上安裝有MySQL數據庫,兩臺服務器互為主備,當其中一臺機器出現故障時,另外一臺能夠接管服務器上的應用,這就需要兩臺數據庫的數據要實時保持一致,在這里使用MySQL的同步功能實現雙機的同步復制。
實現方案
目前SparkSQL節(jié)點訪問雙主的元數據庫主要考慮兩種方案:
SparkSQL節(jié)點直接連接MySQL節(jié)點:
下圖中SparkSQL節(jié)點分別連接單個MySQL節(jié)點,不同SparkSQL節(jié)點對元數據庫的更改會在MySQL節(jié)點之間進行同步。
?
?
?
SparkSQL節(jié)點通過MetaStore節(jié)點連接元數據庫:
?
下圖中SparkSQL節(jié)點分別連接多個MetaStore節(jié)點,每個MetaStore節(jié)點連接對應的MySQL節(jié)點,不同SparkSQL節(jié)點對元數據庫的更改會在MySQL節(jié)點之間進行同步。
?
?
上面兩種SparkSQL節(jié)點訪問雙主的元數據庫方案下,客戶端獲取SparkSQL服務的方式是相同的,主要通過如下方式:
?
Beeline連接
?
?
程序通過JDBC端口訪問
?
Beeline方式首先通過Zookeeper集群獲取SparkSQL節(jié)點信息,然后連接到SparkSQL服務節(jié)點。當連接的SparkSQL節(jié)點異常時,可以通過重試幾次獲取SparkSQL服務。
程序通過JDBC端口連接到對應的SparkSQL節(jié)點的方式下,如果正在連接的SparkSQL節(jié)點出現異常,可以通過在代碼中進行異常捕獲的方式重新獲取SparkSQL服務。
下面主要對兩種方案的功能可行性以及異常情況進行驗證。
?
測試環(huán)境
?
MySQL:10.43.183.121和10.43.183.122兩臺主機
SparkSQL: 10.43.183.121和10.43.183.122兩臺主機
Hive MetaStoreServer: 10.43.183.121和10.43.183.122兩臺主機
?
測試場景
?
場景一:SparkSQL節(jié)點直接連接MySQL高可用驗證
每個SparkSQL節(jié)點直接連接一個MySQL節(jié)點。驗證元數據能否成功同步以及MySQL節(jié)點失效能否自動切換。
測試步驟如下:
1.?修改配置
SparkSQL配置修改如下:
?
?
10.43.183.121對應的JDBC連接配置為10.43.183.121上的MySQL
10.43.183.122對應的JDBC連接配置為10.43.183.122上的MySQL
2.?Beeline連接10.43.183.121節(jié)點的SparkSQL。
3.?創(chuàng)建表test,分別查找兩個MySQL的hiveomm數據庫的tbls表,可以看到test記錄。表明元數據同步成功。
4.?將SparkSQL當前連接的MySQL停掉。
5. Beeline 界面執(zhí)行“show tables”命令,查詢異常。
6.?斷開Beeline連接并多次重新連接10.43.183.121節(jié)點的SparkSQL,連接異常。
7.?用SQL URL連接SparkSQL服務!connectjdbc:hive2://10.43.183.121:2181/;serviceDiscoveryMode=zooKeeper;zooKeeperNamespace=sparkThriftServer重試若干次可以連接上SparkSQL服務,通過“show tables”命令可以查到test表。
8.?啟動MySQL節(jié)點,Beeline重新連接10.43.183.121節(jié)點,可以連接到SparkSQL節(jié)點。執(zhí)行“show tables”命令,可以查詢到test表信息。
測試結論:
?
MySQL之間的元數據可以同步。
?
?
MySQL節(jié)點掛掉會導致Beeline無法查詢。
?
?
Beeline重新連接無法連接到對應的SparkSQL節(jié)點。
?
?
Beeline通過SQL URL連接SparkSQL服務,可以在嘗試一定次數之后連接到可用的SparkSQL節(jié)點。
?
?
場景二: SparkSQL節(jié)點通過HiveMetaStoreServer節(jié)點連接MySQL高可用驗證
?
MetaStoreServer節(jié)點主要用于MySQL節(jié)點失效時的容錯,每個MetaStoreServer節(jié)點對應一個MySQL節(jié)點,每個SparkSQL節(jié)點配置多個MetaStoreServer節(jié)點。驗證元數據能否成功同步以及MySQL節(jié)點失效能否自動切換。
測試步驟如下:
1.?修改配置
MetaStoreServer節(jié)點配置修改如下:
?
?
10.43.183.121節(jié)點的MetaStoreServer配置10.43.183.121節(jié)點上的MySQL
10.43.183.122節(jié)點的MetaStoreServer配置10.43.183.122節(jié)點上的MySQL
SparkSQL添加對應配置:
?
?
2.?Beeline連接10.43.183.121節(jié)點的SparkSQL。
3.?創(chuàng)建表test,分別查找兩個MySQL的hiveomm數據庫的tbls表,可以看到test記錄,表明元數據同步成功。
4.?將SparkSQL當前連接的MetaStoreServer(通過日志看到)對應的MySQL停掉。
5.?Beeline 界面執(zhí)行“show tables”命令,查詢異常。
6.?斷開Beeline連接并多次重新連接10.43.183.121節(jié)點的SparkSQL,連接出現異常。
7.?用SQL url連接SparkSQL服務!connectjdbc:hive2://10.43.183.121:2181/;serviceDiscoveryMode=zooKeeper;zooKeeperNamespace=sparkThriftServer始終無法連接上SparkSQL服務,通過“show tables”命令可以查到test表。
8.?重新啟動MySQL節(jié)點,Beeline重新連接10.43.183.121節(jié)點,可以連接到SparkSQL節(jié)點。執(zhí)行“show tables”命令,可以查詢到test表信息。
測試結論:
?
MySQL之間的元數據可以同步。
?
?
MySQL節(jié)點掛掉會導致Beeline無法查詢。
?
?
MySQL節(jié)點掛掉的情況下,Beeline重新連接SparkSQL節(jié)點,無法連接到對應的SparkSQL節(jié)點。
?
?
MySQL節(jié)點掛掉的情況下,Beeline通過SQL URL連接SparkSQL服務無法連接到對應的SparkSQL服務。
?
?
場景三: 代碼的JDBC接口連接到SparkSQL服務
?
服務配置同場景一中的方式,通過JDBC連接到SparkSQL節(jié)點,示例代碼如下:
?
public static void main(String[] args)
{
??? int num = 0;
??? Connection conn = null;
??? ResultSet rs = null;
??? PreparedStatement pstat = null;
??? while (num < 3)
??? {
??????? num = num + 1;
??????? try
??????? {
??????????? Class.forName("org.apache.hive.jdbc.HiveDriver");
??????????? if (conn == null)
??????????? {
??????????????? if (args.length > 0)
????? ??????????????conn = DriverManager.getConnection(args[0], "mr", "mr");
??????????????? else
??????????????????? conn = DriverManager
??????????????????????? .getConnection("jdbc:hive2://10.43.183.121:18000", "mr", "mr");
??????????? }
??????????? pstat = conn.prepareStatement("select * from test");
??????????? rs = pstat.executeQuery();
?
??????????? while (rs.next())
??????????? {
??????????????? System.out.println(rs.getString("name"));
??????????? }
??????????? break;
??????? } catch (Exception e)
??????? {
??????????? e.printStackTrace();
??????????? try
??????????? {
??????????????? conn = DriverManager
??????????????????? .getConnection("jdbc:hive2://10.43.183.122:18000", "mr", "mr");
??????????? } catch (SQLException e1)
??????????? {
??????????????? e1.printStackTrace();
??????????? }
??????? } finally
??????? {
??????????? try
??????????? {
??????????????? rs.close();
??????????????? pstat.close();
??????????????? conn.close();
??????????? } catch (SQLException e)
????? ??????{
??????????????? e.printStackTrace();
??????????? }
??????? }
?
??? }
}
?
測試結論:
?
通過JDBC連接到SparkSQL節(jié)點可以通過異常捕獲的方式實現實現MySQL節(jié)點故障之后獲取SparkSQL服務。
?
?
測試結論
?
SparkSQL訪問元數據服務的兩種方案都可以正常訪問元數據庫并且實現元數據庫的同步,而且元數據庫異常的情況下,兩種方案的處理是一樣的。
但是SparkSQL連接MetaStore節(jié)點需要連接到Hive的MetaStore節(jié)點,對比直接連接MySQL會有多余的MetaStore進程需要維護、更加復雜的元數據庫管理方式以及版本問題。
因此,建議用MySQL雙主的方式實現SparkSQL的雙主高可用,不同的SparkSQL節(jié)點直接連接到不同的MySQL。
訪問SparkSQL服務的方式可以采用兩種方式:
?
Beeline連接SQL URL的方式,對于MySQL異常的情況,可以重新連接繼續(xù)獲取SparkSQL服務。
?
?
調用JDBC接口訪問SparkSQL,捕獲異常并對異常情況作處理,重新連接到其他SparkSQL節(jié)點。
?
?
配置方式
?
SparkSQL節(jié)點直接連接MySQL的配置如下:
在服務配置界面將javax.jdo.option.ConnectionURL項配置任一MySQL節(jié)點作為默認MySQL節(jié)點,如下圖所示:
?
?
SparkSQL節(jié)點可以在自定義HIVE_SITE_CUSTOM_CONFIG中配置其他MySQL節(jié)點作為其對應的MySQL節(jié)點,配置格式為:
?
?
javax.jdo.option.ConnectionURL
${{mysql_url}}
?
?
${{mysql_url}}為MySQL服務的URL。
如下圖所示:
?
?
評論
查看更多