一、java操作zookeeper(了解)

有两种操作方式:
1、原生的API
2、对原生的API进行封装Curator
重点说Curator
1) 创建maven

2) 导入curator jar 包

  1. <dependencies>
  2. <dependency>
  3. <groupId>org.apache.curator</groupId>
  4. <artifactId>curator-framework</artifactId>
  5. <version>4.2.0</version>
  6. </dependency>
  7. <dependency>
  8. <groupId>org.apache.curator</groupId>
  9. <artifactId>curator-recipes</artifactId>
  10. <version>4.2.0</version>
  11. </dependency>
  12. <dependency>
  13. <groupId>com.google.collections</groupId>
  14. <artifactId>google-collections</artifactId>
  15. <version>1.0</version>
  16. </dependency>
  17. <dependency>
  18. <groupId>junit</groupId>
  19. <artifactId>junit</artifactId>
  20. <version>RELEASE</version>
  21. </dependency>
  22. <dependency>
  23. <groupId>org.slf4j</groupId>
  24. <artifactId>slf4j-simple</artifactId>
  25. <version>1.7.25</version>
  26. </dependency>
  27. </dependencies>

3)编写代码测试
创建连接以及断开连接

package com.qfedu;

import org.apache.curator.RetryPolicy;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.apache.zookeeper.CreateMode;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

/**
* @Author laoyan
* @Description TODO
* @Date 2022/4/14 9:52
* @Version 1.0
*/
public class ZkTest {

    CuratorFramework client = null;
    @Before
    public void init(){
        //重试策略
        RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 1);
        //获取客户端
        client = CuratorFrameworkFactory.newClient("192.168.32.100:2181,192.168.32.101:2181,192.168.32.102:2181", 1000, 1000, retryPolicy);
        client.start();
    }

    @After
    public void destory(){
        client.close();
    }

    // 创建永久节点
    @Test
    public void testCreateNode() throws Exception {

        // 创建节点
        client.create().creatingParentContainersIfNeeded().withMode(CreateMode.PERSISTENT).forPath("/hello");
        client.create().creatingParentContainersIfNeeded().withMode(CreateMode.PERSISTENT).forPath("/hello/world","bigdata2201".getBytes());
    }

}

创建临时节点:

@Test
public void testCreateNode2() throws Exception {

    // 创建节点
    client.create().creatingParentContainersIfNeeded().withMode(CreateMode.EPHEMERAL).forPath("/hello2","bigdata2202".getBytes());

    // 通过让程序停顿5秒钟,方便我们查看到该节点
    Thread.sleep(5000);

    }
// 修改node数据
@Test
public void testSetNode() throws Exception {

    client.setData().forPath("/hello/world","bigbigdata".getBytes());

}

// 删除数据
@Test
public void testDeleteNode() throws Exception {
    client.delete().deletingChildrenIfNeeded().forPath("/hello3");
}

@Test
public void testGetNode()  throws Exception {
    byte[] value = client.getData().forPath("/hello/world");
    System.out.println(new String(value));
}

@Test
public void testWatch()  throws Exception {
    TreeCache treeCache = new TreeCache(client, "/hello");
    treeCache.getListenable().addListener(new TreeCacheListener() {
        @Override
        public void childEvent(CuratorFramework curatorFramework, TreeCacheEvent treeCacheEvent) throws Exception {
            ChildData data = treeCacheEvent.getData();
            if(data != null){
                switch (treeCacheEvent.getType()){
                    case NODE_ADDED:
                        System.out.println("该节点新增了数据,路径是"+data.getPath()+",这个数据是:"+new String(data.getData()));
                        break;
                    case NODE_REMOVED:
                        System.out.println("删除了节点数据"+new String(data.getData()));
                        break;
                    case NODE_UPDATED:
                        System.out.println("更新了节点数据"+new String(data.getData()));
                        break;
                }
            }
        }
    });

    treeCache.start();

    Thread.sleep(100000000);
    }

二、zk的选举机制

1、新的集群启动的一个选举

先启动第一台: 自己投自己一票 ,没有达到半数的要求
启动第二台:  第二台给自己投一票,第一台看到第二台的myid 比自己大,于是它也投票给第二台。此时还超过半数,投票生效了。
第二台就是Leader ,第一台就是Follower
启动第三台:  因为此时集群已经有leader,后面的只能当随从。

2、当zk群集中的leader宕机了
出现了三个值:myid , zxid, Epoch
Epoch :逻辑时钟
Zxid: 事物ID;
选举规则: 先比较Epoch , 谁越大谁是Leader, 如果相等,会比较 Zxid ,如果也相等,才会去比较myid.
如何查看Epoch 呢?
image.png
Epoch 代表的是选举的次数。
Zxid : 数据的新旧。

三、Zk 能干嘛 —搭建 nameNode 高可用

1、什么是HA (High Availability ) — 高可用。
HDFS中 namenode datanode ,一个集群,不管有多少台服务器,只要一个节点挂掉了,其他都不能用,称之为单点故障。
2、高可用的解决方案
1) 主从模式(冷备)
主要的服务,直接开两台,一台工作,一台闲着啥也不干。干活的那一台挂了,不干活的立即顶上。
2) 双主互备(热备)
用了两个服务员同时工作,万一一个请假了,另一个不耽误。
3) 集群多备
两个服务员还是不保险,这个时候可以请多个服务员。
image.png
image.png
高可用演示:
image.png
image.png
hdfs haadmin -getServiceState nn1
image.png
image.png

四、hadoop的联邦机制

hadoop中的namenode 内存是有限的,不管多大,都是有限。随着集群越来越大,整个集群的瓶颈在namenode所在的内存中。
image.png
联邦机制,解决了namenode 内存不足的情况,但是万一坏一台,又完蛋。
所以比较好的解决方案:联邦机制+HA机制。

五、Hive的概念

Hive 是什么? 本质就是使用HQL语句生成MapReduce代码,进行所谓的数据分析。

4.2.1 优点

  1. 学习成本低:提供了类SQL查询语言HQL,使得熟悉SQL语言的开发人员无需关心细节,可以快速上手.
  2. 海量数据分析:底层是基于海量计算到MapReduce实现.
  3. 可扩展性:为超大数据集设计了计算/扩展能力(MR作为计算引擎,HDFS作为存储系统),Hive可以自由的扩展集群的规模,一般情况下不需要重启服务。
  4. 延展性:Hive支持用户自定义函数,用户可以根据自己的需求来实现自己的函数。
  5. 良好的容错性:某个数据节点出现问题HQL仍可完成执行。
  6. 统计管理:提供了统一的元数据管理

    4.2.2 缺点

  7. Hive的HQL表达能力有限

  8. 迭代式算法无法表达.
  9. Hive的效率比较低.
  10. Hive自动生成的MapReduce作业,通常情况下不够智能化.
  11. Hive调优比较困难,粒度较粗.

    架构设计:

    从这个架构图来看,hive是在hadoop外面包了一层壳儿。
    image.png
    1、ClI   == client
    可以接收shell命令
    WebUI == 通过浏览器访问 Hive
    JDBC/ODBC == 可以通过java代码操作hive
    2、Thrift Server 
     这个服务已开启,别人可以远程访问到hive
    3、Meta Store (FackBook == Meta)  这个数据是要存在数据库中的(Derby,MySQL)
    4、Driver
      解析器,编译器,优化器
    

    Hive和我们的关系型数据库有何区别?

    在企业中: mysql 最少也得两台 一个读 一个写 读写分离。
    也可以搭建mysql集群(MyCat)
    image.png
    Hive 跟数据库没有什么关系,它只是里面会些SQL而已,本质是不存储数据的。它也不是No SQL数据库(HBase).

    Hadoop和Hive的关系

    Hive底层存储使用了HDFS,Hive的计算是基于MapReduce.

    六、Hive的安装

    1、嵌入式的模式(元数据在Derby数据库中,通常用于开发测试时使用)

    1) 解压
    tar -xf apache-hive-3.1.2-bin.tar.gz -C /usr/local
    
    2) 改名字
    mv apache-hive-3.1.2-bin hive
    
    3)环境变量 /etc/profile
    export JAVA_HOME=/usr/local/jdk
    export HADOOP_HOME=/usr/local/hadoop
    export ZOOKEEPER_HOME=/usr/local/zookeeper
    export HIVE_HOME=/usr/local/hive
    export PATH=$PATH:$JAVA_HOME/bin:$HADOOP_HOME/sbin:$HADOOP_HOME/bin:$ZOOKEEPER_HOME/bin:$HIVE_HOME/bin
    
    4) 刷新一下
    source /etc/profile
    
    5) 配置各种配置文件
    hive-env.sh 系统是没有这个文件的, 使用hive-env.sh.template
    cp hive-env.sh.template hive-env.sh
    chmod 777 hive-env.sh
    
    修改这个文件内容:
    export HIVE_CONF_DIR=/usr/local/hive/conf
    export JAVA_HOME=/usr/local/jdk
    export HADOOP_HOME=/usr/local/hadoop
    export HIVE_AUX_JARS_PATH=/usr/local/hive/lib
    
    配置hive-site.xml
    1、从hive-default.xml.template 拷贝一份过来
    删除3215行的特殊字符  &#8;
    
    image.png
    6) 检查 hdfs以及yarn是否启动,如果没有启动,手动启一下。
    7)修改dir
    在这个文件hive-site.xml中替换两个重要的东西
    image.png
    创建这个配置文件中没有的路径,并且赋权限。
    hdfs dfs -mkdir -p /user/hive/warehouse
    hdfs dfs -mkdir -p /tmp/hive
    hdfs dfs -chmod 777 /user/hive/warehouse
    hdfs dfs -chmod 777 /tmp/hive
    
    8) 创建本地的临时目录 io.tmpdir
    在hive 安装路径下  hive_home 下,创建文件夹
    mkdir iotmp
    chmod 777 iotmp
    
    9) 替换hive-site.xml 中的内容
    把hive-site.xml 中所有包含 ${system:Java.io.tmpdir}替换成/usr/local/hive/iotmp
    如果系统默认没有指定系统用户名,那么要把配置${system:user.name}替换成当前用户名root
    image.png
    10)初始化hive
    在hive 的家路径下,执行该命令
    schematool -initSchema -dbType derby
    
    11) 简单的操作
    show databases;
    show talbes;
    create table stu(id int,name string);
    insert into stu values(1,"zhangsan");
    select * from stu;
    退出使用quit;
    
    image.png
    以上就是我们的Derby模式,有缺点,缺点就是这个hive 只能一个人操作,多一个都不行。
    image.png

    2、使用本地模式

    元数据是存储在mysql中,而不是derby中,支持多用户访问。
    1) 安装mysql
    mysql的安装有两种方式:使用yum源安装 ,第二种使用rpm安装包安装。
    第一步:检查是否安装过同类的软件
    rpm -qa | grep mariadb
    rpm -e mariadb-libs-5.5.64-1.el7.x86_64 --nodeps
    rpm -qa | grep mysql
    
    第二步:上传rpm安装包解压
    tar -xvf mysql-8.0.26-1.el7.x86_64.rpm-bundle.tar
    
    第三步:安装
    rpm -ivh mysql-community-common-8.0.26-1.el7.x86_64.rpm
    rpm -ivh mysql-community-client-plugins-8.0.26-1.el7.x86_64.rpm
    rpm -ivh mysql-community-libs-8.0.26-1.el7.x86_64.rpm
    rpm -ivh mysql-community-client-8.0.26-1.el7.x86_64.rpm
    yum install -y net-tools
    yum install -y perl
    rpm -ivh mysql-community-server-8.0.26-1.el7.x86_64.rpm
    
    第四步:修改密码
    启动mysql
    systemctl start mysqld
    查看mysql是否启动成功
    systemctl status mysqld
    查看mysql的原始密码
    grep password /var/log/mysqld.log
    
    image.png ```java 通过原始密码进入mysql . mysql -uroot -p 输入原始密码 修改密码(必须设置一个复杂的密码,得还有特殊符号): alter user root@localhost identified by ‘h1n2c3ctonG!’;

查看密码策略: show variables like ‘%validate_password%’; 修改密码设置策略,便于我们设置一个比较好记的密码: set global validate_password.policy=LOW; # 修改密码策略等级为LOW set global validate_password.length=4; # 密码的最小长度 set global validate_password.mixed_case_count=0; # 设置密码中至少要包含0个大写字母和小写字母 set global validate_password.number_count=0; # 设置密码中至少要包含0个数字 set global validate_password.special_char_count=0; # 设置密码中至少要包含0个特殊字符

设置简易密码: alter user root@localhost identified by ‘123456’;

qfedu 123456<br />Q1f2e3d456!

第五步:修改mysql的远程连接
```java
create user 'root'@'%' identified by  '123456';
grant all privileges on *.* to 'root'@'%' with grant option;
flush privileges;