马上注册,结交更多数据大咖,获取更多知识干货,轻松玩转大数据
您需要 登录 才可以下载或查看,没有帐号?立即注册
x
文 | 刘少麟 来源:中兴大数据
“ 开源的Spark SQL并不支持高可用,但实际应用中高可用对于用户意义重大。中兴大数据平台DAP在对应的ZDH中实现了Spark SQL的高可用。 ”Spark SQL的高可用,是两个Spark SQL服务上线的时候向SQL进行注册,用户连接的JDBC URL指定为Zookeeper的列表,连接的时候会通过Zookeeper集群获取Spark SQL节点信息,然后连接到Spark SQL服务节点。 Spark SQL元数据双主主要是用MySQL实现,MySQL支持单向、异步复制,复制过程中一个服务器充当主服务器,而一个或多个其它服务器充当从服务器。主服务器将更新写入二进制日志文件,并维护日志文件的索引以跟踪日志循环。从服务器接收从那时起发生的任何更新,然后封锁并等待主服务器通知下一次更新。 在实际项目中,两台分布于异地的主机上安装有MySQL数据库,两台服务器互为主备,当其中一台机器出现故障时,另外一台能够接管服务器上的应用,这就需要两台数据库的数据要实时保持一致,在这里使用MySQL的同步功能实现双机的同步复制。 实现方案 目前SparkSQL节点访问双主的元数据库主要考虑两种方案: 下图中SparkSQL节点分别连接单个MySQL节点,不同SparkSQL节点对元数据库的更改会在MySQL节点之间进行同步。 下图中SparkSQL节点分别连接多个MetaStore节点,每个MetaStore节点连接对应的MySQL节点,不同SparkSQL节点对元数据库的更改会在MySQL节点之间进行同步。
上面两种SparkSQL节点访问双主的元数据库方案下,客户端获取SparkSQL服务的方式是相同的,主要通过如下方式: Beeline方式首先通过Zookeeper集群获取SparkSQL节点信息,然后连接到SparkSQL服务节点。当连接的SparkSQL节点异常时,可以通过重试几次获取SparkSQL服务。 程序通过JDBC端口连接到对应的SparkSQL节点的方式下,如果正在连接的SparkSQL节点出现异常,可以通过在代码中进行异常捕获的方式重新获取SparkSQL服务。 下面主要对两种方案的功能可行性以及异常情况进行验证。 测试环境 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节点直接连接MySQL高可用验证
每个SparkSQL节点直接连接一个MySQL节点。验证元数据能否成功同步以及MySQL节点失效能否自动切换。 测试步骤如下:
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节点的SparkSQL。 3. 创建表test,分别查找两个MySQL的hiveomm数据库的tbls表,可以看到test记录。表明元数据同步成功。 4. 将SparkSQL当前连接的MySQL停掉。 5. Beeline 界面执行“show tables”命令,查询异常。 6. 断开Beeline连接并多次重新连接10.43.183.121节点的SparkSQL,连接异常。 7. 用SQL URL连接SparkSQL服务!connectjdbc:hive2://10.43.183.121:2181/;serviceDiscoveryMode=zooKeeper;zooKeeperNamespace=sparkThriftServer重试若干次可以连接上SparkSQL服务,通过“show tables”命令可以查到test表。 8. 启动MySQL节点,Beeline重新连接10.43.183.121节点,可以连接到SparkSQL节点。执行“show tables”命令,可以查询到test表信息。 测试结论:
MetaStoreServer节点主要用于MySQL节点失效时的容错,每个MetaStoreServer节点对应一个MySQL节点,每个SparkSQL节点配置多个MetaStoreServer节点。验证元数据能否成功同步以及MySQL节点失效能否自动切换。 测试步骤如下: 1. 修改配置 MetaStoreServer节点配置修改如下: 10.43.183.121节点的MetaStoreServer配置10.43.183.121节点上的MySQL 10.43.183.122节点的MetaStoreServer配置10.43.183.122节点上的MySQL SparkSQL添加对应配置: 2. Beeline连接10.43.183.121节点的SparkSQL。
3. 创建表test,分别查找两个MySQL的hiveomm数据库的tbls表,可以看到test记录,表明元数据同步成功。 4. 将SparkSQL当前连接的MetaStoreServer(通过日志看到)对应的MySQL停掉。 5. Beeline 界面执行“show tables”命令,查询异常。 6. 断开Beeline连接并多次重新连接10.43.183.121节点的SparkSQL,连接出现异常。 7. 用SQL url连接SparkSQL服务!connectjdbc:hive2://10.43.183.121:2181/;serviceDiscoveryMode=zooKeeper;zooKeeperNamespace=sparkThriftServer始终无法连接上SparkSQL服务,通过“show tables”命令可以查到test表。 8. 重新启动MySQL节点,Beeline重新连接10.43.183.121节点,可以连接到SparkSQL节点。执行“show tables”命令,可以查询到test表信息。 测试结论:
服务配置同场景一中的方式,通过JDBC连接到SparkSQL节点,示例代码如下: 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();
}
}
}
} 测试结论: 测试结论 SparkSQL访问元数据服务的两种方案都可以正常访问元数据库并且实现元数据库的同步,而且元数据库异常的情况下,两种方案的处理是一样的。 但是SparkSQL连接MetaStore节点需要连接到Hive的MetaStore节点,对比直接连接MySQL会有多余的MetaStore进程需要维护、更加复杂的元数据库管理方式以及版本问题。 因此,建议用MySQL双主的方式实现SparkSQL的双主高可用,不同的SparkSQL节点直接连接到不同的MySQL。 访问SparkSQL服务的方式可以采用两种方式: 配置方式 SparkSQL节点直接连接MySQL的配置如下: 在服务配置界面将javax.jdo.option.ConnectionURL项配置任一MySQL节点作为默认MySQL节点,如下图所示: SparkSQL节点可以在自定义HIVE_SITE_CUSTOM_CONFIG中配置其他MySQL节点作为其对应的MySQL节点,配置格式为: <property> <name>javax.jdo.option.ConnectionURL</name> <value>${{mysql_url}}</value> </property> ${{mysql_url}}为MySQL服务的URL。 如下图所示:
|