Hive原理及Hive的搭建与部署
一、Hive的原理
1)Hive简介
hive是基于Hadoop的一个数据仓库工具,底层封装得的是HDFS和MapReduce可以将结构化的数据文件映射为一张数据库表,并提供sql查询功能,可以将sql语句转换为MapReduce任务进行运行。 其优点是学习成本低,可以通过类SQL语句快速实现简单的MapReduce统计,不必开发专门的MapReduce应用,十分适合数据仓库的统计分析。其本质还是在HDFS上执行MapReduce,虽然简化了操作,但是执行效率会相对减弱。
Hive数据仓库中包含着解释器、编译器、优化器等,这些是其独有的部分,用于将sql语句变成MapReduce去执行,后续的工作就自动交给了Hadoop、Yarn和MapReduce,Hive在运行时,实际的源数据存在与HFDS上,而描述数据的元数据存放在关系型数据库中。
补充点: ① Hive数据仓库完成解析SQL、优化SQL、策略选择、模型消耗;客户端将sql语句交给Hive,Hive负责值使相对应的MapReduce执行。
②存在于关系型数据库中的元数据包含着行的分隔符、字段的分隔符、字段的类型、字段的名称等信息。
2)Hive的架构
(1)用户接口主要有三个:CLI,Client 和 WUI。
其中最常用的是CLI,Cli启动的时候,会同时启动一个Hive副本。Client是Hive的客户端,用户连接至Hive Server。在启动 Client模式的时候,需要指出Hive Server所在节点,并且在该节点启动Hive Server。 WUI是通过浏览器访问Hive。
(2)Hive将元数据存储在数据库中,如mysql、derby。Hive中的元数据包括表的名字,表的列和分区及其属性,表的属性(是否为外部表等),表的数据所在目录等。
(3)解释器、编译器、优化器完成HQL查询语句从词法分析、语法分析、编译、优化以及查询计划的生成。生成的查询计划存储在HDFS中,并在随后有MapReduce调用执行。
(4)Hive的数据存储在HDFS中,大部分的查询、计算由MapReduce完成(包含*的查询,比如select * from tbl不会生成MapRedcue任务)。
3)Hive的搭建
hive三种方式区别和搭建
按照Hive中metastore(元数据存储)不同位置分为三种方式:
a)内嵌Derby方式
b)Local方式
c)Remote方式
a)内嵌Derby方式
此方式是将元数据存在本地的Derby数据库,一般用于单元测试。
步骤:
①首先将Hive的压缩包在指定的位置解压,并修改内部的hive-site.xml(需要自己创建或修改模板的xml)
<configuration>
<property>
<name>javax.jdo.option.ConnectionURL</name>
<value>jdbc:derby:;databaseName=metastore_db;create=true</value>
</property>
<property>
<name>javax.jdo.option.ConnectionDriverName</name>
<value>org.apache.derby.jdbc.EmbeddedDriver</value>
</property>
<property>
<name>hive.metastore.local</name>
<value>true</value>
</property>
<property>
<name>hive.metastore.warehouse.dir</name>
<value>/user/hive/warehouse</value>
</property>
</configuration>
②在Hive的bin目录下输入 ./hive
启动hive
缺点:使用derby存储方式时,运行hive会在当前目录生成一个derby文件和一个metastore_db目录。
这种存储方式的弊端是在同一个目录下同时只能有一个hive客户端能使用数据库,否则会出错误
注意点: ①搭建Hive之前要先将HDFS、Yarn以及MapRedecu的进程启动好,因为Hive的实习是在上述环境中进行的。
②要注意Hadoop下的Yarn下lib中的jline这个jar包于Hive中的版本相统一,不然会出错。
b)Local方式
这种存储方式需要在本地运行一个mysql服务器,一般运行在client中
①需要将mysql的jar包拷贝到Hive所在目录的lib目录下
②安装mysql yum install mysql-server -y
安装成功后需启动mysql服务 service mysql start
,启动完成后输入mysql进入mysql的操作窗口进行权限的修改修改mysql权限:
GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY '123' WITH GRANT OPTION;
flush privileges;
删除多余会对权限造成影响的数据
刷新权限
添加用户:
CREATE USER 'hive'@'%' IDENTIFIED BY '123';
授权用户:
grant all privileges on hive_meta.* to [email protected]"%" identified by '123';
flush privileges;
删除多余的权限
权限修改完毕后设置开机启动
chkconfig mysqld on
注意一个坑:
权限,虽然hive用户对hive_meta数据库是由操作权限的,但是这个数据库如果不存在,hive用户也是没有权限创建这个数据库,所以需要提前创建好hive_remote数据库;除此之外还要把证jline的jar包在yarn和hive中的版本要统一。
③修改配置文件hive-site.xml
<configuration>
<property>
<name>hive.metastore.warehouse.dir</name>
<value>/user/hive_remote/warehouse</value>
</property>
<property>
<name>hive.metastore.local</name>
<value>true</value>
</property>
<property>
<name>javax.jdo.option.ConnectionURL</name>
<value>jdbc:mysql://localhost/hive_meta?createDatabaseIfNotExist=true</value>
</property>
<property>
<name>javax.jdo.option.ConnectionDriverName</name>
<value>com.mysql.jdbc.Driver</value>
</property>
<property>
<name>javax.jdo.option.ConnectionUserName</name>
<value>hive</value>
</property>
<property>
<name>javax.jdo.option.ConnectionPassword</name>
<value>password</value>
</property>
</configuration>
④去hive目录下的bin目录使用 ./hive
命令启动hive
c)Remote方式
这种方式是基于存放元数据的数据库为mysql类型的方式上实现的,进一步实现了在多个节点上操作同一个hive数据库,实现远程连接,常用的一种方式。
①基于上一种方式,client节点上的配置不需要动,只需更改想要远程连接的节点上的配置文件;在客户端启动远程连接服务 hive --service metastore
即可。
后台启动:
②在远程连接的节点上解压Hive压缩包 ,修改hive-site.xml
<configuration>
<property>
<name>hive.metastore.warehouse.dir</name>
<value>/user/hive/warehouse</value>
</property>
<property>
<name>hive.metastore.local</name>
<value>false</value>
</property>
<property>
<name>hive.metastore.uris</name>
<value>thrift://提供服务的节点的IP:9083</value>
</property>
</configuration>
③在Hive目录下的bin目录启动 ./hive
启动远程连接的hive操作。
注意点要想实现远程连接首先要保证网络的通信通畅,需要关闭客户端防火墙,否则会出现错误:java.net.NoRouteToHostException: No route to host (Host unreachable)
二、Hive的连接方式
由于之前的操作方式是直接对Hive进行操作,通过Hive命令不需要验证即可进入客户端通过Hive进行数据分析及操作,存在安全的问题且不规范。在此问题上我们出现了安全的Hive连接方式 :beeline、jdbc;Hive的连接是通过thriftServer这个通信服务进行连接的,整个过程不需要使用metaStore这个服务;登录所用的用户名、密码是通过编程获得的
a) beeline
1》配置的步骤
①首先在客户端修改Hive中的hive-site.xml(哪一个节点被连接就修改哪一个节点的配置信息,其余节点不用修改),添加如下的配置信息:
<property>
<name>hive.server2.authentication</name>
<value>CUSTOM</value>
</property>
<property>
<name>hive.jdbc_passwd.auth.zhangsan</name> //设置 用户名 密码
<value>123456789</value>
</property>
<property>
<name>hive.server2.custom.authentication.class</name> //自定义类,代码实现验证用户信息
<value>com.hoe.hive.authoriz.UserPasswdAuth</value>
</property>
2》自定义类实现
注意实现自定类的功能需要导入依赖包(hive目录下的lib中的jar包都可导入);编写完成后将类导成jar包,放到客户端hive目录下lib下即可实现
public class UserPasswdAuth implements PasswdAuthenticationProvider {
Logger logger = LoggerFactory.getLogger(UserPasswdAuth.class);
private static final String USER_PASSWD_AUTH_PREFIX = "hive.jdbc_passwd.auth.%s";
private Configuration conf = null;
@Override
public void Authenticate(String userName, String passwd) throws AuthenticationException {
logger.info("user: " + userName + " try login.");
String passwdConf = getConf().get(String.format(USER_PASSWD_AUTH_PREFIX, userName));
if (passwdConf == null) {
String message = "沒有發現密碼 " + userName;
logger.info(message);
throw new AuthenticationException(message);
}
if (!passwd.equals(passwdConf)) {
String message = "用戶名密碼不匹配 " + userName;
throw new AuthenticationException(message);
}
}
public Configuration getConf() {
if (conf == null) {
this.conf = new Configuration(new HiveConf());
}
return conf;
}
public void setConf(Configuration conf) {
this.conf = conf;
}
}
3》启动beeline
进入Hive目录下的bin目录,使用命令 ./hiveserver2
,在客户端启动thriftServer这个服务。
4》其他节点进行连接
进入其他节点,不需要更改配置文件,进入Hive目录下的bin目录,使用 ./beeline
命令启动连接,进入连接状态后输入 命令:./beeline -u jdbc:hive2://客户端节点的IP:10000/test -n zhangsan -p123456789
输入账户密码正确后可以进入test数据库。
注意: ①如何设置多个用户名、密码?可以通过在hive-site.xml配置文件中设置多个配置信息,在代码中全部读过来,在加入具体的判定条件。
②在其他节点操作时要注意权限问题,因为使用账号、密码登录的用户属于其他组的成员。
③当进行连接的操作时,是对客户端本地的数据进行操作,因为在其他节点写的 sql语句会通过thriftServer这个服务传给客户端(被连接节点),在客户端(被连接节点)上执行。
b) jdbc
通过jdbc这种连接方式仍需要连接客户端的thriftServer服务,其具体的实现只需要自定义类,不需修改配置文件。
因为通过JDBC链接hive 也是链接hiveserver2服务,链接成功才能操作hive
所以JDBC链接的时候也是需要用户名 密码的。
public class ConnectHive {
public static String driverName = "org.apache.hive.jdbc.HiveDriver";
public static void main(String[] args) {
try {
Class.forName(driverName);
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
String url = "jdbc:hive2://node01:10000";
String userName = "zhangsan";
String passwd = "123456789";
Connection conn = null;
try {
conn = DriverManager.getConnection(url, userName, passwd);
Statement statement = conn.createStatement();
String sql = "select * from test.logtbl limit 10"; //sql语句可以是其他的dml,但是不能是update,不支持修改。
ResultSet resultSet = statement.executeQuery(sql);
while (resultSet.next()) {
System.out.println(resultSet.getString(1) + "-" + resultSet.getString(2));
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}