学习内容:Scala,Hadoop,Zookeeper,Kafka的配置和使用
11月6日 黑马Scala
视频链接:
070尚硅谷Scala面向对象(一)包(一)声明和访问哔哩哔哩_bilibili
摘要
列表
创建列表(可变或不可变)
// 1. 创建不可变列表 val list1 = List(1, 2, 3) // 1. 创建可变列表 val list1 = new ListBuffer[Int]() val list2 = ListBuffer(12, 53, 75)
添加元素
添加元素的时候可以使用+: 或者是使用:: 创建列表,但是如果是两个列表只会将列表直接加在前面.
Nil的意思相当于一个空列表.
val list2 = 10 +: list1 val list3 = list1 :+ 23 val list4 = list2.::(51) val list5 = Nil.::(13) val list6 = 89 :: 32 :: Nil val list7 = 17 :: 28 :: 48 :: 39 :: 98 :: Nil
合并列表
将两个列表拼接在一起,两种写法的意思是一样的.
val list9 = list6 ::: list7 val list10 = list6 ++ list7
Map集合
创建Map
因为Map是有键值对的,所以书写的格式跟java中有一些区别,是使用 -> 的方式,同样还是使用伴生对象创建集合的方式进行创建这种方式比new出来更加的简单.如果是可变Map就是在Map前面加上mutable导入这个可变集合类
// 1. 创建Map val map1 = Map("a" -> 13,"b"->25,"hello"-> 3)
获取key或value的值
获取map中所有的key或value的值可以使用for循环然后,使用get(key).get的方式进行获取.但是这种方式在获取单个值的时候不是很好,有一个缺陷就是如果没有对应的key值就会直接throw的异常,所以更推荐使用getOrElse或者是直接使用map(key)的方式进行获取.
// 4. 访问某一个key的value println(map1.get("a").get) // 获取当前c的值如果c没有值就把后面参数设为它默认的初始值 println(map1.getOrElse("c", 0)) println(map1("a"))
添加元素(可变Map)
可以使用put方式进行添加,也可以使用+=的方式进行添加元素,但是使用+=的时候里面的键值对需要使用()进行包裹.
// 2. 添加元素 map1.put("c", 5) map1.put("d", 9) map1 += (("e", 7))
合并Map(可变Map)
合并两个Map可以使用++=的方式或者是使用++然后将值复制给一个新的map中.
// 5. 合并两个Map,相同的值会进行覆盖,没有的值就进行添加. val map2 = mutable.Map("aaa" -> 19, "b" -> 85, "hello" -> 3) map1 ++= map2
遇到的问题
无
总结
今天学习了列表,Set,Map,元组,跟java中的定义其实是差不多的,就是多了可变和不可变的区别,在添加和合并的时候可以使用符号的方式,会让这些更加的简便,感觉在处理上Scala更加喜欢使用符号的方式进行拼接或者是添加减少元素,今天的内容来说不难,就是学习一下集合的一些书写的格式或者是添加和删除的方法.
11月7日 黑马Scala
视频链接:
117尚硅谷Scala集合(七)集合常用函数(四)高级计算函数(二)集合转换操作(Map类)哔哩哔哩bilibili
摘要
集合常用函数
获取集合的头或尾,最后一个元素,初始数据
头就是集合的第一个元素,尾的话就是不是头就是尾,获取尾的底层原理就是将第一个元素也就是头去掉,剩下的就是尾,然后重新构成一个集合.最后一个元素的话就使用last.初始数据就是不包括最后一个数据其他数据都是初始数据.
println(list1.head) println(list1.tail) println(list1.last) println(list2.init)
取前(后)n个元素,去掉前(后)n个元素
// 6.取前(后)n个元素 println(list1.take(3)) println(list1.takeRight(4)) // 7. 去掉前(后)n个元素 println(list1.drop(3)) println(list1.dropRight(4))
拉链
拉链的意思就是将两个集合关联起来并排的元素构成一个二元的元组
// 拉链 println("zip: " + list1.zip(list2)) println("zip: " + list2.zip(list1))
滑窗
sliding里面的参数就是将多少个成为一组,然后默认的每次滑动的间距是1,当每个组数跟间距数相同的话,就相当于滚动输出.即使最后的元素不够组数,也要将最后那些元素构成一组进行输出.
参数: 窗口的大小,滑动步长
for (elem <- list1.sliding(3)) { println(elem) } for (elem <- list2.sliding(4,2)){ println(elem) }
排序
正常的sorted的方式是从小到大进行排序,如果需要从大到小排序可以使用reverse将集合进行反转或者是传入隐式参数.
sortBy(): 需要指定根据哪一个项进行排序,因为前后的参数只出现过一次,所以直接使用_进行代替,如果需要从大到小排序就可以使用柯里化的方式然后传入隐式参数就可以进行反转.
sortWith: 通过comparator函数,实现自定义排序,因为前后都只出现一次a和b所以我们直接使用_方式进行代替.这种方式最简洁.
// sorted val sortedList = list.sorted // sortBy println(list2.sortBy(_._2)) println(list2.sortBy(_._2)(Ordering[Int].reverse)) // sortWith println(list.sortWith((a: Int, b: Int) => {a < b})) // 从小到大 println(list.sortWith(_ < _)) // 从大到小 println(list.sortWith(_ > _))
映射map
这里不仅仅是可以对数进行计算,可以对于数值类型进行改变.
注意: 这里的平方不能使用_ * _ 的形式 因为这种形式两个_ 表示的是同一个参数,但是出现了两次,就无法识别是否是同一个.
// 2. 映射map // 把集合中每个数都乘2 println(list.map(_ * 2)) list.map(elem => elem * elem)
flatmap 扁平化映射
常规的操作实现扁平化需要吸纳将列表中的元素进行分词,然后在进行扁平化,打散所有元素.
Scala中使用flatMap可以直接分词并进行扁平化.
// 4.扁平映射 // 将一组字符串进行分词,并保存成单词的列表 val strings = List("hello world", "hello scala", "hello java", "we study") val splitList = strings.map(_.split(" ")) // 分词 val flattenList = splitList.flatten // 打散扁平化 println(flattenList) println(strings.flatMap(_.split(" ")))
GroupBy分组
我们如果需要将数据进行分组统计,就需要用到GroupBy方法,按照函数将列表分成不同的组.
// 5. 分组groupBy // 分成奇偶两组 val groupMap = list.groupBy(_ % 2) val groupMap2 = list.groupBy(data => if (data % 2 == 0) "偶数" else "奇数") println(groupMap) println(groupMap2) // 给定一组词汇,按照单词的首字母进行分组 val wordList = List("china", "america", "alice", "canada", "cary", "bob", "japan") println(wordList.groupBy(_.charAt(0)))
fold 折叠
将上一步返回的值作为函数的第一个参数继续传递参与运算,知道list中的所有元素被遍历.
就是将集合外部元素和集合内部元素进行合并.
// 2. fold println(list.fold(10)(_ + _)) // 10 + 1 + 2 + 3 + 4 println(list.foldLeft(10)(_ - _)) // 10 - 1 - 2 - 3 - 4 println(list.foldRight(10)(_ - _)) // 3 - (4 - (5 - (8 - (10 - 11))) = -5
合并Map
这里的合并Map指的是将两个Map中的value值进行相加,所以不能简单的使用++操作,因为++ 操作后一个Map会将前一个Map的value值进行覆盖.
所以需要使用foldLeft方法(这里不使用fold方法是因为fold方法需要参数的类型是相同的),而foldLeft的类型是不同的,所以只能使用foldLeft,然后初始值是map2,然后将第一个参数设置为key,跌停个参数设置为value,加上map1的值赋值给mergeMap对应的key,最后返回mergeMap.
val map1 = Map("a" -> 1, "b" -> 3, "c" -> 6) val map2 = mutable.Map("a" -> 6, "b" -> 2, "c" -> 9, "d" -> 3) val map3: mutable.Map[String, Int] = map1.foldLeft(map2)( (mergeMap, kv) => { val key = kv._1 val value = kv._2 mergeMap(key) = mergeMap.getOrElse(key, 0) + value mergeMap } )
复杂的二维数组
需求: 统计出现的单词数,并数量前三的.
首先我们可以将数组进行打散和进行分组操作,然后按照二元组按照单词进行分组,然后叠加每一个单词的个数,最后转换成List集合然后使用匿名函数的方式对个数进行比较,最后使用take函数进行截取前三的数据.
val tupleList = List( ("hello", 1), ("hello world", 2), ("hello scala", 3), ("hello spark from scala", 1), ("hello flink from scala", 2) ) // 思路二: 直接基于预统计的结果进行转换 // 1.将字符串打散为单词,并结合对应的个数包装成二元组 val preCountList = tupleList.flatMap( tuple => { val strings = tuple._1.split(" ") strings.map(word => (word, tuple._2)) } ) // 2. 对二元组按照单词进行分组 val groupList = preCountList.groupBy(word => word._1) // 3. 叠加每个单词预统计的个数值 val countMap = groupList.mapValues( tupleList => tupleList.map(_._2).sum ) // 4.转换成List,排序取前三 println(countMap.toList.sortWith(_._2 > _._2).take(3))
遇到的问题
无
总结
今天学习了一些新的概念比如像拉链和滑窗,这两个操作是java中没有的,拉链就是将两个集合进行关联将一列上的元素组一个二元组,而滑窗就是按照参数将多少个元素组成一组,然后间隔默认为1.滚动进行输出.扁平化的话就是把一个集合打散,Group分组的概念跟sql中分组有点像,fold的话就是将集合中的元素合并起来.最后做了几个例题,感觉在例题中的操作还是比较复杂的,对于我来说有一定的难度.这部分的内容需要进行强化.
11月8日 黑马Scala
视频链接:
070尚硅谷Scala面向对象(一)包(一)声明和访问哔哩哔哩_bilibili
摘要
模式匹配
在java中有Switch…case的用法,但是在Scala中没有,但是Scala中的match表达式类似于Switch语法,在多个备选项中做选择,跟Switch语法有所不同的是不需要使用break进行中断,而且必须设置默认值否则会抛出异常.
// 示例: 用模式匹配实现简单二元运算 val a = 25 val b = 13 def matchDualOp(op: Char) = op match { case '+' => a + b case '-' => a - b case '*' => a * b case '/' => a / b case '%' => a % b case _ => -1 } println(matchDualOp('*'))
类型匹配
在match中不仅仅能匹配常量同样可以匹配类型
但是需要注意的是List里面写参数的类型,但是匹配的时候是会进行类型的擦除的,里面是Int还是String什么类型都能匹配上,所以如果需要匹配规定的类型的话还是需要使用Array,因为它的底层是不会进行类型擦除的.
// 2. 匹配类型 def describeType(x : Any):String = x match { case i : Int => "Int " + i case s: String => "String " + s case list: List[String] => "List " + list case array: Array[Int] => "Array[Int] " + array.mkString(",") case a => "Something else: " + a }
变量声明时匹配
这样匹配可以对对应位置进行值的设置,如果是像多个参数的话,先设置前面的值然后使用多形参的方式设置或者可以使用::的方式进行连接.
val (x, y) = (10, "hello") println(s"x: $x, y: $y") val List(first, second, _*) = List(23, 15, 9, 78) println(s"first: $first, second: $second") val fir :: sec :: rest = List(23, 15, 9, 78) println(s"first: $fir, second: $sec, rest: $rest")
对象实例匹配
第一种方式就是定义一个伴生对象Student,然后重写里面的unapply方法,判断如果是Null的时候就返回None,如果是有值的话就设置student然后返回.对应对象实例的匹配也跟集合数组匹配差不多也是把参数进行设置匹配.
object Test04_MatchObject { def main(args: Array[String]): Unit = { val student = new Student("bob", 18) // 针对对象实例的内容进行匹配 val result = student match { case Student("alice", 18) => "Alice, 18" case _ => "Else" } println(result) } } // 定义类 class Student(val name: String, val age: Int) object Student { def apply(name: String, age: Int): Student = new Student(name, age) // 必须实现一个unapply方法,用来对对象属性进行拆解 def unapply(student: Student): Option[(String, Int)] = { if (student == null) { None } else { Some((student.name, student.age)) } } }
样例类
当然上面这种方式显然不符合Scala简洁的方式,所以引出了另外一个概念就是样例类.
只需要在定义类的时候在前面加上一个case,在内部他就会自己重写unapply方法,并且参数都是形参就不需要使用val进行定义了.
object Test05_MatchCaseClass { def main(args: Array[String]): Unit = { val student = Student("alice", 18) // 针对对象实例的内容进行匹配 val result = student match { case Student("alice", 18) => "Alice, 18" case _ => "Else" } println(result) } } // 定义样例类 case class Student1(name: String, age: Int)
遇到的问题
无
总结
今天学习了使用模式匹配,模式匹配跟java中的Switch…case很像,但他不仅仅能判断数值,也能判断类型,甚至能判断对象实例,当然在对象实例的匹配中重写unapply方法还是过于复杂,所以需要使用样例类,这样就不需要自己手动的进行重写.感觉这一部分的内容还是不难理解的,今天状态不是很好,因为今天一直出现肚子疼的情况,希望明天能调整好状态.
11月9日 黑马Scala
视频链接:
070尚硅谷Scala面向对象(一)包(一)声明和访问哔哩哔哩_bilibili
摘要
偏函数
顾名思义就是一个残缺的函数,有时候需要多个偏函数进行组合才能完成一个需求,orElse是将多个偏函数组合起来使用效果跟case语句差不多,类型为PartialFunction[A,B],其中接收一个类型为A的参数,返回一个类型为B的结果。
// 偏函数的应用,求绝对值 // 对输入数据分为不同的情形: 正,负,0 val positiveAbs: PartialFunction[Int, Int] = { case x if x > 0 => x } val negativeAbs: PartialFunction[Int, Int] = { case x if x < 0 => -x } val zeroAbs: PartialFunction[Int, Int] = { case 0 => 0 } def abs(x: Int): Int =(positiveAbs orElse negativeAbs orElse zeroAbs) (x)
隐式转换
就是如果找不到合适的类型,会通过隐式转换让编译器在作用范围内自动推到出合适的类型.
隐式类
使用implicit关键字进行修饰的类,在作用域内,带有这个关键字的类主函数用于隐式转换.
implicit class MyRichInt2(val self: Int) { // 自定义比较大小的方法 def myMax2(n: Int): Int = if (n < self) self else n def myMin2(n: Int): Int = if (n < self) n else self } println(35.myMax2(59))
隐式参数
定义一个变量使用implicit关键字修饰,定义一个函数调用这个变量当参数时,这个参数就是隐式参数.就可以作为下面函数的默认值.减少了函数参数的数量.
但是多个隐式参数类型不能相同,不同了Scala就不知道该使用哪个参数了,
隐式参数的优先级高于默认值,scala中函数的传参级别: 函数列表传参 > 隐式参数 > 默认值
// 3. 隐式参数 // 相同类型的隐式值只能有一个, implicit val str: String = "alice" implicit val num: Int = 18 def sayHello(implicit name: String): Unit = { println("hello, " + name) } // 隐式值会覆盖掉默认值 def sayHi(implicit name: String = "bob"): Unit = { println("hi, " + name) } sayHello sayHi
化简后
上面定义了隐式参数之后,下面调用的时候直接使用implicit然后加上参数类型就可以直接调用.
implicit val str: String = "alice" implicit val num: Int = 18 // 简便写法 def hiAge(): Unit = { println("hi, " + implicitly[Int]) } hiAge()
泛型
泛型用于指定方法或类可以接受任何类型参数,参数在实际使用的时候才被确定.
逆变和协变
当类型 B 是类型 A 的子类型时,则 List[B]也可以认为是 List[A}的子类型,即 List[B]可以泛化 为 List[A]。
也就是参数类型的泛化方向与参数类型的方向是一致的,成为协变.逆变就是参数化类型的泛化方向与参数类型的方向是相反的.
// 1.协变和逆变 val child = new Child // val childList: MyCollection[Parent] = new MyCollection[Child] val childList: MyCollection[SubChild] = new MyCollection[Child] // 定义带泛型的集合类型 class MyCollection[-T] {}
上下限
有时需要界定泛型类型的范围,而不是接收任意类型。可以要求某个泛型类型,必须是某个类的子类,这样在程序中就能放心的调用父类的方法.
1、U >: T 这是类型下界的定义,也就是 U 必须是类型 T 的父类(或本身,自己也可以认为是自己的父类)。 2、S <: T 这是类型上界的定义,也就是 S 必须是类型 T 的子类(或本身,自己也可以认为是自己的子类)。
// 2. 上下限 def test[A <: Child](a: A):Unit ={ println(a.getClass.getName) } test[Child](new SubChild)
遇到的问题
无
总结
今天学习了Scala中的偏函数的概念,这是一个残缺的函数,可能满足一个需求,需要多个偏函数组合才能组成一个完整的函数.对于一个隐式转换来说就是如果找不到合适的类型,会通过隐式转换让编译器在作用范围内自动推到出合适的类型.类的话就相当于完成了unapply方法,而隐式参数的作用是让参数有默认值,可以有多个隐式参数,但是隐式参数不能类型相同.最后学习了泛型,对于泛型,java中也有这个概念,但是多出来逆变和协变还有上下限的概念,总体来说还是可以接受的不难理解,然后学习完了Scala的部分开始学习hadoop.
11月13日 黑马Hadoop
视频链接:
13尚硅谷Hadoop入门HDFS概述哔哩哔哩bilibili
摘要
卸载虚拟机自带的JDK
意思是将含有java的一个个列出来然后一个个的进行删除.
rpm -qa | grep -i java | xargs -n1 rpm -e --nodeps
使用以下命令检查是否删除干净.
rpm -qa | grep -i java
安装JDK
先把JDK放在/opt/software下,然后执行下面的代码,将jdk解压缩到/opt/moudle中
tar -zxvf jdk-8u212-linux-x64.tar.gz -C /opt/moudle/
切换到/etc/profile.d目录下
cd /etc/profile.d/
在/etc/profile.d/的目录下使用vim创建my_env.sh文件
在这里创建这个文件的原因是因为 /etc/profile 这个文件中有这么一段 shell, 会在每次启动时自动加载 profile.d 下的每个配置
#JAVA_HOME export JAVA_HOME=/opt/moudle/jdk1.8.0_212 export PATH=$PATH:$JAVA_HOME/bin
重新加载/etc/profile,重新加载环境变量,然后输入java就可以使用了.
source /etc/profile
Hadoop安装
前置的步骤跟安装JDK是一样的只不过是是修改一下压缩文件的名称,
在/etc/profile.d/的目录下使用vim修改my_env.sh文件,在前面的JDK基础上再添加HADOOP_HOME的配置.
#HADOOP_HOME export HADOOP_HOME=/opt/moudle/hadoop-3.1.3 export PATH=$PATH:$HADOOP_HOME/bin export PATH=$PATH:$HADOOP_HOME/sbin
重新加载/etc/profile,重新加载环境变量,然后输入hadoop就可以使用了.
source /etc/profile
编写集群分发脚本xsync
scp(安全拷贝)
scp 定义 scp 可以实现服务器与服务器之间的数据拷贝。
基本语法:
scp -r $pdir/$fname $user@$host:$pdir/$fname 命令 递归 要拷贝的文件路径/名称 目的地用户@主机:目的地路径/名称
将hadoop102的/opt/module文件夹的jdk拷贝到hadoop103的/opt/module目录下.
scp -r jdk1.8.0_212/ hcq@hadoop103:/opt/moudle/
不仅能推送本地的文件到其他的虚拟机中,还可以从其他虚拟机中拉取文件到本地.
scp -r hcq@hadoop102:/opt/moudle/hadoop-3.1.3 ./
甚至还能在hadoop103上将hadoop102的文件拷贝到hadoop104上
scp -r hcq@hadoop102:/opt/moudle/* hcq@hadoop104:/opt/moudle/
rsync 远程同步工具
rsync 和 scp 区别:用 rsync 做文件的复制要比 scp 的速度快,rsync 只对差异文件做更新。scp 是把所有文件都复制过去。
rsync -av $pdir/$fname $user@$host:$pdir/$fname 命令 选项参数 要拷贝的文件路径/名称 目的地用户@主机:目的地路径/名称
-a 归档拷贝 -v 显示复制过程
rsync和scp区别
-
1 .用rsync做文件的复制要比scp的速度快,rsync只对差异文件做更新。
-
2 .scp是把所有文件都复制过去
xsync 集群分发脚本
使用xsync集群分发脚本之后,就可以循环复制文件到所有的节点的相同目录下.就不像前面的rsync和scp只能单向的推送文件.
先在cd目录下创建xsync文件
[chq@hadoop102 opt]$ cd [hcq@hadoop102 ~]$ mkdir bin [hcq@hadoop102 ~]$ cd bin [hcq@hadoop102 bin]$ vim xsync
在文件中写入shell指令代码.
并需要修改脚本的执行权限
hcq@hadoop102 bin]$ chmod 777 xsync
同步环境配置
如果使用了sudo,那么xsync一定要给它补全路径.
sudo ./bin/xsync /etc/profile.d/my_env.sh
最后,需要环境变量生效还需要再另外两台虚拟机上source /etc/profile.
ssh免密登录
1.生成公钥和私钥
这一步先生成公钥和私钥,但是如果如果没有.ssh文件,需要先ssh 其他虚拟机然后在cd 目录下就会出现.ssh文件.然后再执行这个命令.
中间会出现选项,全部按回车键进行使用默认选择.
[hcq@hadoop102 ~]$ ssh-keygen -t rsa
2.将公钥拷贝到要免密登录的目标机器上
[hcq@hadoop102 .ssh]$ ssh-copy-id hadoop102 [hcq@hadoop102 .ssh]$ ssh-copy-id hadoop103 [hcq@hadoop102 .ssh]$ ssh-copy-id hadoop104
然后使用ssh 主机名就可以直接进行登录,不需要输入密码.
遇到的问题
这里是因为缺少了.pub文件夹,也就是缺少了公钥.
解决方法:输入ssh-keygen -t -rsa #用来生成秘钥
总结
今天学习了配置了hadoop的一些基本的软件和安装配置.也学习了一个新的内容就是书写sxync脚本进行集群分发,这样速度更快,在分发的时候,第一次的话就是进行复制,如果是第二次就是进行一些更新,在配置环境变量等的时候就非常的方便.最后就是ssh免密登录,在之前学习ssh的时候有了一些经验,所以在这次进行ssh免密登录的时候就比较的顺利,没有出现什么大问题.
11月14日 黑马Hadoop
视频链接:
070尚硅谷Scala面向对象(一)包(一)声明和访问哔哩哔哩_bilibili
摘要
集群配置
因为如果将所有的进程都安装在同一台服务器上就会很消耗内存,很吃配置,所以可以配置在几台服务器上就可以分摊这些进程带来的内存压力.
需要修改四个配置文件,分别是core-site.xml、hdfs-site.xml、yarn-site.xml、mapred-site.xml.
配置core-site.xml
配置hdfs-site.xml
配置yarn-site.xm
配置 mapred-site.xml
在后面群起服务器测试的时候发现在yarn-site.xml和mapred-site.xml中都要加入
具体的hadoop四个配置文件我写在了自己的博客里.
在集群上分发配置好的 Hadoop 配置文件
[hcq@hadoop102 hadoop]$ xsync /opt/module/hadoop3.1.3/etc/hadoop/
群起集群
配置 workers
[hcq@hadoop102 hadoop]$ vim /opt/moudle/hadoop3.1.3/etc/hadoop/workers
同步到所有节点
[hcq@hadoop102 hadoop]$ xsync /opt/module/hadoop-3.1.3/etc
启动集群
这里需要使用root权限执行,因为root权限才可以创建这里的文件夹.
这里的启动Yarn只能在hadoop103节点上启动,因为只有这个节点才能启动ResourceManger.
[hcq@hadoop102 hadoop-3.1.3]$ hdfs namenode -format 启动 HDFS [hcq@hadoop102 hadoop-3.1.3]$ sbin/start-dfs.sh 在配置了 ResourceManager 的节点(hadoop103)启动 YARN [hcq@hadoop103 hadoop-3.1.3]$ sbin/start-yarn.sh
遇到的问题
在进行dhfs初始化的时候出现了问题
Hadoop格式化namenode错误:java.io.IOException: Cannot create directory-CSDN博客
发现是因为权限不够而导致无法在目录中新建文件,所以导致了错误.
所以我切换到root用户下,然后重新执行发现就可以正常的运行了.但是依旧没有解决没有出现data文件夹的问题.
然后我查看了弹幕说老师的module文件夹名字写错了.然后需要修改配置文件core-site.xml
最后重新进行格式化就出现了data文件夹.
计算wordcount出错
提示说要检查mapred-site.xml文件
1.先输入命令hadoop classpath
获取hadoop的安装路径,然后将路径返回值以下这种格式.
然后在yarn-site.xml,mapred-site.xml中加入
<property> <name>yarn.application.classpath</name> <value> /opt/moudle/hadoop-3.1.3/etc/hadoop, /opt/moudle/hadoop-3.1.3/share/hadoop/common/lib/*, /opt/moudle/hadoop-3.1.3/share/hadoop/common/*, /opt/moudle/hadoop-3.1.3/share/hadoop/hdfs, /opt/moudle/hadoop-3.1.3/share/hadoop/hdfs/lib/*, /opt/moudle/hadoop-3.1.3/share/hadoop/hdfs/*, /opt/moudle/hadoop-3.1.3/share/hadoop/mapreduce/lib/*, /opt/moudle/hadoop-3.1.3/share/hadoop/mapreduce/*, /opt/moudle/hadoop-3.1.3/share/hadoop/yarn, /opt/moudle/hadoop-3.1.3/share/hadoop/yarn/lib/*, /opt/moudle/hadoop-3.1.3/share/hadoop/yarn/*, </value> </property>
然后将这两个修改的文件分发到其他两台机子中
[hcq@hadoop102 hadoop-3.1.3]$ xsync hadoop
然后重新进行计算就可以了
总结
今天学习了集群服务器的配置,主要是对这四个配置文件进行配置,但是如果仅仅是配置了老师的说的那些配置还有点不够,在使用yarn的时候也会出现问题,所以需要加入我后面添加的一些代码,最后不能忘记需要将配置分发到其他的集群的机子上.然后就是启动集群,启动集群的时候需要注意的就是要使用root权限,否则在创建文件夹的时候会出现权限不足的情况.总体来说配置集群是不难的,但是也会出现一些毛病.
11月15日 黑马Hadoop
视频链接:
32尚硅谷Hadoop入门集群崩溃处理办法哔哩哔哩bilibili
摘要
集群崩溃处理
集群崩溃就是集群上缺少了一些文件或者是进程,导致整个集群启动不了.
但是不管集群怎么坏,只要不是bin目录和etc目录坏了就可以使用下面的操作.
1 .首先是将每台机子上的hadoop进程全部关掉
[hcq@hadoop103 hadoop-3.1.3]$ sbin/stop-yarn.sh
[hcq@hadoop102 hadoop-3.1.3]$ sbin/stop-dfs.sh
1 .将每个机子上的data/ 和logs/的文件夹全部删掉.
[hcq@hadoop102 hadoop-3.1.3]$ rm -rf data/ logs/
2.每个机子上的文件夹都删除后然后进行hdfs格式化.
[hcq@hadoop102 hadoop-3.1.3]$ hdfs namenode -format
最后就是启动集群
[hcq@hadoop102 hadoop-3.1.3]$ sbin/start-dfs.sh
配置历史服务器
可以查看程序的历史运行情况,需要配置一下历史服务器.
1 .首先需要配置mapred-site.xml加入下面的两个参数,历史服务器地址和历史服务器的Web地址段
[hcq@hadoop102 hadoop]$ vim mapred-site.xml
这里不能忘记要将这个mapred-site.xml配置文件分发到另外两台机子.
[hcq@hadoop102 hadoop]$ xsync mapred-site.xml
2 .需要重新启动yarn,然后启动历史服务器,并使用jps查看是否启动JobHistoryServer进程
[hcq@hadoop103 hadoop-3.1.3]$ sbin/start-yarn.sh
[hcq@hadoop102 hadoop-3.1.3]$ mapred --daemon start historyserver
3 .最后进行一下测试
最后访问一下hadoop103:8088,看能否访问History功能.查看是不是测试产生的结果.
[hcq@hadoop102 hadoop-3.1.3]$ hadoop fs -mkdir /input [hcq@hadoop102 hadoop-3.1.3]$ hadoop fs -put wcinput/word.txt /input [hcq@hadoop102 hadoop-3.1.3]$ hadoop jar share/hadoop/mapreduce/hadoop-mapreduce-examples-3.1.3.jar wordcount /input output
配置日志聚集
配置日志聚集功能,方便后期的时候发现问题,更好的找到问题.可以方便的查看到程序运行详情,方便开发调试.
程序运行完之后会将程序执行日志信息上传到HDFS系统上.我们可以通过访问hadoop102:8088的History中的logs进行查看.
配置yarn-site.xml,并加入开启日志聚集功能,最后分发到其他机子上
[hcq@hadoop102 hadoop]$ vim yarn-site.xml
[hcq@hadoop102 hadoop]$ xsync yarn-site.xml
测试日志功能
注意: 如果在此之前yarn和HistoryServer是开启的,需要先进行关闭后重启,然后再重新访问hadoop102:8088端口.
[hcq@hadoop102 hadoop-3.1.3]$ hadoop jar share/hadoop/mapreduce/hadoop-mapreduce-examples-3.1.3.jar wordcount /input output2
编写Hadoop集群常用脚本
1.集群启停脚本
把myhadoop.sh 在cd /bin/ 使用vim书写myhadoop.sh,只要使用hadoop start 或者使用Hadoop stop就可以进行集群的启动和停止.
将myhadoop.sh权限修改成777.
[hcq@hadoop102 bin]$ chmod 777 myhadoop.sh
2.jpsall
查看三台服务器Java进程脚本,这样就不需要在每台服务器上都使用jps进行检查,只需要在一台机子上进行一次jpsall操作就可以了.
#!/bin/bash for host in hadoop102 hadoop103 hadoop104 do echo =============== $host =============== ssh $host jps done
将权限修改成777
[hcq@hadoop102 bin]$ chmod 777 jpsall
最后将两个脚本同步到另外两台机子上,保证自定义脚本在三台机子上都可以使用.
[hcq@hadoop102 ~]$ xsync bin/
遇到的问题
解决“VMware另一个程序锁定文件的一部分,进程无法访问“的问题
出现这种情况的原因是:虚拟机在运行的过程中,如果突然断电,则会锁定文件,生成*.lck结尾的文件和文件夹,避免系统崩溃。
解决方法如下: 删除当前虚拟机文件里的*.lck文件和文件夹,就可以解除锁定,再启动虚拟机即可
总结
今天学习了如果集群崩溃了如何去处理,主要是围绕先将集群关闭然后将每台机子都删除data和logs文件夹,最后在进行hdfs格式化.然后学习配置了历史服务器和开启了日志聚集功能,更好的去查看程序运行的结果,在发现问题后也能更好的解决问题,发现问题的所在,然后学习编写了hadoop集群常用的脚本,主要方便了集群的启动需要转到Hadoop103去启动yarn,直接在任意一台机子上就可以启动,还可以直接在一台机子上直接查看所以机子的java程序进程.大大方便了操作.其实还学习了一个时间同步,但是没有什么用,因为我们的电脑都是与外网联通的,而且另外的机子一直向时间同步服务器同步时间也会消耗大量的资源,所以不建议进行配置.今天的内容总体来说还好,问题其实也有,但是只要重启了Hadoop集群后都能解决,或者是shell脚本中多了回车或者空格等.
11月16日 黑马Zookeeper
视频链接:
摘要
本地模式安装
解压安装
在 hadoop102 解压 Zookeeper 安装包到/opt/module/目录下,并使用mv改名为zookeeper-3.5.7
[hcq@hadoop102 software]$ tar -zxvf apache-zookeeper-3.5.7-bin.tar.gz -C /opt/moudle/
配置修改
将/opt/module/zookeeper-3.5.7/conf 这个路径下的 zoo_sample.cfg 修改为 zoo.cfg;
并且需要修改zoo.cfg中dataDir的位置,因为原本的位置是在tmp下也就是临时目录下,但是在系统中每隔一段时间就会删除这个文件夹,所以需要修改成自己的data目录.
而且还需要修改server.Properties文件中的broke.id对应的Hadoop102改成0,Hadoop103改成1,Hadoop104改成2.
[hcq@hadoop102 conf]$ mv zoo_sample.cfg zoo.cfg
在/opt/module/zookeeper-3.5.7/这个目录下创建 zkData
[hcq@hadoop102 zookeeper-3.5.7]$ mkdir zkData
还需要再配置/etc/profile.d/my_env.sh
配置kafka的环境变量
集群安装
配置服务器编号
在/opt/module/zookeeper-3.5.7/zkData创建myid文件.
然后在每台服务器上设置对应的数字,Hadoop102上是2,Hadoop103是3,Hadoop104上是4.
[hcq@hadoop102 zkData]$ vi myid
拷贝配置好的 zookeeper 到其他机器上
[hcq@hadoop102 module ]$ xsync zookeeper-3.5.7
配置zoo.cfg文件
在zoo.cfg文件中最后加上图片中的配置,是为了让Zookeeper能够识别其他的机子或者是崩溃后能有其他端口能够访问.
同步 zoo.cfg 配置文件
[hcq@hadoop102 conf]$ xsync zoo.cf
最后需要启动Zookeeper
这里要记住只有超过半数的机子启动Zookeeper的时候Zookeeper才能启动.
[hcq@hadoop102 zookeeper-3.5.7]$ bin/zkServer.sh start
ZK 集群启动停止脚本
在 hadoop102 的/home/atguigu/bin 目录下创建脚本
[hcq@hadoop102 bin]$ vim zk.sh
在脚本中编写如下内容
#!/bin/bash case $1 in "start"){ for i in hadoop102 hadoop103 hadoop104 do echo ---------- zookeeper $i 启动 ------------ ssh $i "/opt/moudle/zookeeper-3.5.7/bin/zkServer.sh start" done };; "stop"){ for i in hadoop102 hadoop103 hadoop104 do echo ---------- zookeeper $i 停止 ------------ ssh $i "/opt/moudle/zookeeper-3.5.7/bin/zkServer.sh stop" done };; "status"){ for i in hadoop102 hadoop103 hadoop104 do echo ---------- zookeeper $i 状态 ------------ ssh $i "/opt/moudle/zookeeper-3.5.7/bin/zkServer.sh status" done };; esac
增加脚本执行权限
[hcq@hadoop102 bin]$ chmod 777 zk.sh
节点
zk像一个文件系统,每个子目录被称为目录节点,允许我们自由的添加删除目录节点,或者修改节点中的值.
但是我感觉这个跟Map数据类型也很像,就是对应的key有value值,就跟目录后写节点值.
查看根节点信息
语法: ls [-s] [-w] [-R] path
-s
表示查看详细信息,可省略-w
表示只看节点名称,可省略-R
表示查看根路径的所有节点及子节点,可省略path
表示节点路径,可以是根节点/,也可以是子节点路径如/a,或者/a/b/c
[zk: localhost:2181(CONNECTED) 1] ls -s /
创建节点
-s: 顺序节点- :顺序节点也就是有自己的编号顺序. -e: 临时节点 : 也就是说如果关闭了zk,再次启动的时候这个节点就会消失. -c: 容器节点 :当删除掉container节点下的所有子节点后, container节点本身也会被清除掉,默认被清除的时间是60s。 -t: 可以给节点添加过期时间,默认禁用,需要通过系统参数启用
[zk: localhost:2181(CONNECTED) 24] create -s /seq/Allen- "hello" [zk: localhost:2181(CONNECTED) 31] create -e /ephemeral "hello ephemeral" [zk: localhost:2181(CONNECTED) 37] create -e -s /seq-eph [zk: localhost:2181(CONNECTED) 4] create /container/sub1
获取节点信息
用于获取节点中的值.
语法: get [-s] [-w] path
[zk: localhost:2181(CONNECTED) 9] get -s /sanguo/shuguo/liubei
监听器
监听器就是用来监听目录节点的变化,zk就会通知客户端,监听保证zk保存任何数据的变化都能快速的响应到该节点的应用程序.
注意: 当多次进行修改监听目录节点的值时,客户端就不再会收到监听,因为注册一次,只能监听一次,想要再次监听就需要再次注册.
1.在hadoop104 主机上注册监听/sanguo 节点数据变化
[zk: localhost:2181(CONNECTED) 26] get -w /sanguo
2.在hadoop103 主机上修改/sanguo 节点的数据
[zk: localhost:2181(CONNECTED) 1] set /sanguo "xisi"
3.观察 hadoop104 主机收到数据变化的监听
WATCHER:: WatchedEvent state:SyncConnected type:NodeDataChanged path:/sanguo
遇到的问题
Zookeeper服务器启动失败
解决方案:上面这种情况是因为仅仅启动了一个Hadoop102导致的,需要启动Hadoop103和Hadoop104因为只有启动了半数以上的服务器才能让Zookeeper正常的启动.
总结
今天本来准备开始学习Kafka但是发现Kafka是基于Zookeeper的环境,所以我修改的自己的计划修改成学习Zookeeper的内容,学习了本地模式和集群安装,感觉我对于安装和配置方面的内容越来越熟练了,大致的步骤都已经了解.每个软件就是需要改的地方不同,基本就是修改conf目录或者是etc目录,然后添加环境变量,然后将修改的内容分发给集群的其他机子,并让其他机子的环境变量生效.然后学习了zk的集群启停,发现这个shell脚本在集群方面真的很方便,直接可以对多台机子进行操作最后就是对于节点和监听器,感觉这个部分的节点跟Map类型中的key和value很像,就是对应的key有value值没有写就是null.
11月20日 黑马Zookeeper
视频链接:
摘要
创建ZK对象
创建一个ZK对象,连接的zk集群,设置连接的响应超时事件,然后创建一个监听器,就可以启动.
监听节点变化
视频中老师是这样写的,在初始化的new Watcher方法中加入getChildren指令获取到根目录下的值,然后最后打印出来.
但我发现老师这么写其实是有问题的,老师下面的getChildren方法其实根本没有实现,只有上面的new Watcher中的process方法回调有用到.
而且在输出的时候会输出两遍获取到的根目录节点,所以感觉不是很好.
所以这里我简化了一下,我决定直接在init中直接进行getChildren一直监听节点的变化.直接删除了下面的getChildren方法.
但要注意的是如果需要执行其他命令的时候,这里的延时睡眠部分需要关闭.
服务器动态上下线
DistributeServer
这里是连接zk,然后让集群的服务器登录的时候都会发出提示,哪个一个服务器上线了.
注意这里需要再edit process中设置实例参数因为这里create的时候需要加上hostanme.
分布式锁
分布式锁可以就是在Client客户机都要创建节点,所以我们需要保证顺序,所以我们把这里指令都放入到locks中也就是锁中,锁里面有顺序,如果是最小的节点,那就直接进行执行,如果是后面的,先判断自己是不是最小的节点,如果不是就进行监听前一个节点,前一个节点结束之后,自己就执行.
注意: 这里每个节点都是只监听它的上一个节点即可,而不是监听序号最小的节点。因为临时节点都是带序号的,而且序号不会回退,所以只需要 监听比其小1的节点。只要比它小1的节点被清除,则它就可以 拿到资源去操作
使用原生的JAVA代码太过繁琐,而且一些多次监听的操作也不能实现,直接使用CuratorFrame框架的方法.
遇到的问题
创建zk索引出现问题
原因分析:是因为仅仅使用了创建的指令,但是创建索引的指令前提是需要zk启动,但是zk没有启动所以会出现空指针异常.
解决方法:
只需要将上面init初始化的方法改成@Before就可以,因为如果是@Before就会在create之前先执行完inti初始化,然后再执行create这样的话,就避免了zk没有启动的问题.
org.apache.zookeeper.KeeperExceptionSNoNodeException
这里显示的是没有这个目录/serversHadoop1010000000这个目录,但是其实我需要create创建的是servers目录下的Hadoop节点.
说明是因为目录写错了而导致的.
解决方法:
上面没有这个目录的原因是因为,我在拼接这个数据的时候,这里的目录后没有加上/,加上/之后才是一个完整的路径,否则就是路径就是上面的报错的路径了.
总结
今天主要学习了使用Idea如何使用API创建ZK,创建节点,而且可以多次的监控节点的变化,只有有变化就会同步到服务器上,最后就是了解了什么是分布锁,分布锁就是有多个client需要处理的时候,把所有的指令放入到锁中,并排列起来一个个进行处理,如果是最小的节点就直接进行执行,如果不是最小节点就监听前一个节点,然后如果前一个节点结束了,就可以执行自己,以此类推.今天的内容总体来说不是特别难,还是可以理解的.
11月21日 黑马Kafka
视频链接:
摘要
Topic 命令
Topic是kafka数据写入操作的基本单元.一个topic包含了多个Partition.Ka fka保证给定Topic的Partition的任何使用者都将始终以与写入时完全相同的顺序读取该分区的事件。
Replication为了使数据具有容错性和高可用性,每个Topic都可以有多个Replication,以便始终有多个Kafka节点具有数据副本,以防出现问题。
注意: 在后面想要重新修改分区的数量的时候,可以将分区的数量增加,但是不能减少.
命令行操作
使用Linux命令行的方式进行消息的生产和消费,从productor的消息从从Hadoop102中生产后,然后Hadoop103连接上Hadoop102的端口消费数据.
异步发送
异步就是批量发送。如果设置异步模式,生产者就可以一次以batch的形式push数据.大大提高了broke的性能.
普通异步发送
操作步骤:
创建 kafka 生产者的配置对象
给 kafka 配置对象添加配置信息:bootstrap.servers
key,value 序列化
创建 kafka 生产者对象
调用 send 方法,发送消息
关闭资源
带回调函数的异步发送
带回调函数与普通的异步发送的区别就是在异步的基础上加入了回调,当发送完成后,我们设置了回调函数的内容,就会执行回调方法.
注意:消息发送失败会自动重试,不需要我们在回调函数中手动重试。
同步发送
实际的操作只是在普通的异步发送的基础上加上了一个get方法.
但实际上同步发送是逐条的进行发送,一条一条的发送,第一条发送完毕收到响应之后,第二条才会进行发送.
遇到的问题
SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder". SLF4J: Defaulting to no-operation (NOP) logger implementation’
运行程序时控制台出现3行红色的字,虽然不影响运行,但是一般来说红色字体就是有错误.
错误原因是少了slf4j-nop.jar slf4j-simple.jar, slf4j-log4j12.jar,slf4j-jdk14.jar或 logback-classic.jar中的其中一个jar包,加上去就行(只能是一个,多了就会有冲突)
解决方法: 在Maven工程的pom文件中,新增一个上述的包文件之一的依赖配置,项目就可以正常编译运行了。
<dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-simple</artifactId> <version>1.7.25</version> <scope>compile</scope> </dependency>
然后就可以正常的看到log日志了
总结
今天学习Topic命令,学会了使用命令行的方式使用生产者和消费者去生产和消费数据.也学习了什么是异步发送和同步发送,而且也了解了他们之间的区别,异步发送是直接一堆发送过去,而同步发送就是一个应答之后才会发送第二个数据以此类推.而且异步发送还可以设置回调.总体来说还好.
11月22日 黑马Kafka
视频链接:
摘要
自定义分区
Kafka默认使用的是sticky的方式,有时候我们需要过滤数据或者是自己想要设置分区规则就可以进行设置,有些内容需要发送到不同的分区中.让分区规则更加的合理,将消息发送到指定的分区中.
提高生产者吞吐量
吞吐量相当于拉货,原本一次只能拉一个但是通过提高吞吐量,设置批次大小,缓冲区大小这些就可以让吞吐量变大,也相当于一次拉更多的货物.
数据重复
Producer 在使用事务功能前,必须先自定义一个唯一的 transactional.id。有 了 transactional.id,即使客户端挂掉了, 它重启后也能继续处理未完成的事务.
遇到的问题
没有配置对应的事务ID
这里的提示信息的意思是需要配置事务的id
在配置中配置
// 指定事务id properties.put(ProducerConfig.TRANSACTIONAL_ID_CONFIG,"tranactional_id_01");
总结
今天学习了自定义分区,提高生产者吞吐量,数据重复和数据有序与无序.主要就是配置Properties中的内容,加入一些其他的配置,增加吞吐量,压缩大小等让拉取数据量更多,后面的数据重复是以事务来防止出现错误的时候会有数据重复,而导致数据的不统一.总体来说都是对Producer的配置文件进行设置.总体来说还是比较简单的.
11月23日 黑马Kafka
视频链接:
摘要
服役新节点
克隆一台新的虚拟机Hadoop105
需要修改ip地址与hostname
将ip地址修改成192.168.10.105
把hostname修改成Hadoop105
删除kafka目录下的logs和datas
这一步很重要因为这里面的logs和datas是属于被克隆的机子的,如果不删除的话,就是只能上线一个,上线一个另外一个就会下线.因为里面有这个集群的唯一标识.
[root@hadoop105 kafka]# rm -rf datas/ logs/
修改broker.id
[root@hadoop105 config]# vim server.properties
修改里面的broker.id设置为3
执行负载均衡的操作
创建一个要均衡的主题.
[hcq@hadoop102 kafka]$ vim topics-to-move.json
文件中写入
{ "topics": [ {"topic": "first"} ], "version": 1 }
生成一个负载均衡的计划
这里生成一个负载均衡的计划,节点有0,1,2,3组成,让系统自动生成计划.然后把系统生成的计划放入到increase-replication-factor.json文件中.
[hcq@hadoop102 kafka]$ bin/kafka-reassign-partitions.sh -- bootstrap-server hadoop102:9092 --topics-to-move-json-file topics-to-move.json --broker-list "0,1,2,3" --generate
vim increase-replication-factor.json
执行副本存储计划
[hcq@hadoop102 kafka]$ bin/kafka-reassign-partitions.sh --bootstrap-server hadoop102:9092 --reassignment-json-file increase-replication-factor.json --execute
验证副本存储计划
[hcq@hadoop102 kafka]$ bin/kafka-reassign-partitions.sh --bootstrap-server hadoop102:9092 --reassignment-json-file increase-replication-factor.json --verify
退役旧节点
先按照退役一台节点,生成执行计划,然后按照服役时操作流程执行负载均衡。
第一步是跟服役新节点一样,需要创建一个均衡的主题,但是我们在服役新节点的时候已经创建过了,所以这一步就省去了.
创建执行计划
这里创建的方式与新节点的方式差不多就是将节点改成只有0,1,2
[hcq@hadoop102 kafka]$ bin/kafka-reassign-partitions.sh -- bootstrap-server hadoop102:9092 --topics-to-move-json-file topics-to-move.json --broker-list "0,1,2" --generate
执行副本存储计划并验证副本存储计划
执行停止命令 在 hadoop105 上执行停止命令即可
最后就是停止Hadoop105上的kafka服务就可以了
[hcq@hadoop105 kafka]$ bin/kafka-server-stop.sh
遇到的问题
无
总结
今天学习的内容是认识到Kafka的Broker存储还有对应的工作原理,开始获取的时候我还发现自己的brokerid没有,但是发现是没有启动对应的kafka,而且学会使用prettyzoo软件去查看kafka中的目录节点.然后学会如何服役新的节点和退役旧的节点.其实主要就是把id写入然后生成对应的负载均衡的计划,然后进行执行副本的存储计划.
11月27日 黑马Kafka
视频链接:
30尚硅谷Kafka_Broker副本基本信息哔哩哔哩_bilibili
摘要
Leader 选举流程
Kafka 集群中有一个 broker 的 Controller 会被选举为 Controller Leader,负责管理集群 broker 的上下线,所有 topic 的分区副本分配和 Leader 选举等工作。
1.创建一个新的 topic,4 个分区,4 个副本
[hcq@hadoop102 kafka]$ bin/kafka-topics.sh --bootstrap-server hadoop102:9092 --create --topic atguigu1 --partitions 4 --replication-factor 4
2.查看 Leader 分布情况
[hcq@hadoop102 kafka]$ bin/kafka-topics.sh --bootstrap-server hadoop102:9092 --describe --topic atguigu1
3.停止掉 hadoop105 的 kafka 进程,并查看 Leader 分区情况
[hcq@hadoop105 kafka]$ bin/kafka-server-stop.sh [atguigu@hadoop102 kafka]$ bin/kafka-topics.sh --bootstrap-server hadoop102:9092 --describe --topic atguigu1
手动调整分区副本存储
应用场景: 每台服务器的配置和性能不一致,但是Kafka只会根据自己的代码规则创建对应的分区副本,就会导致个别服务器存储压力较大。所有需要手动调整分区副本的存储。
手动调整分区副本存储的步骤如下:
1.创建一个新的 topic,名称为 three。
[hcq@hadoop102 kafka]$ bin/kafka-topics.sh --bootstrap-server hadoop102:9092 --create --partitions 4 --replication-factor 2 -- topic three
2.查看分区副本存储情况。
[hcq@hadoop102 kafka]$ bin/kafka-topics.sh --bootstrap-server hadoop102:9092 --describe --topic three
3.创建副本存储计划(所有副本都指定存储在 broker0、broker1 中)。
[hcq@hadoop102 kafka]$ vim increase-replication-factor.json
写入
{ "version":1, "partitions":[{"topic":"three","partition":0,"replicas":[0,1]}, {"topic":"three","partition":1,"replicas":[0,1]}, {"topic":"three","partition":2,"replicas":[1,0]}, {"topic":"three","partition":3,"replicas":[1,0]}] }
4.执行副本存储计划。
[hcq@hadoop102 kafka]$ bin/kafka-reassign-partitions.sh -- bootstrap-server hadoop102:9092 --reassignment-json-file increase-replication-factor.json --execute
5.验证副本存储计划。
[hcq@hadoop102 kafka]$ bin/kafka-reassign-partitions.sh -- bootstrap-server hadoop102:9092 --reassignment-json-file increase-replication-factor.json --verify
6.查看分区副本存储情况。
[hcq@hadoop102 kafka]$ bin/kafka-topics.sh --bootstrap-server hadoop102:9092 --describe --topic three
Leader Partition 负载平衡
Kafka把本身自动把Leader Partition均匀分配到各个机子上,然后保证每个机子的读写吞吐量都是均匀的.但是如果某些broker坏了,会导致Leader Partition过于集中在其他少部分几台broker上,这会导致少数几台broker的读写请求压力过高,其他坏了的broker重启之后都是follower partition,读写请求很低,造成集群负载不均衡。
增加副本因子
1.创建 topic
[hcq@hadoop102 kafka]$ bin/kafka-topics.sh --bootstrap-server hadoop102:9092 --create --partitions 3 --replication-factor 1 -- topic four
2.手动增加副本存储
(1).创建副本存储计划(所有副本都指定存储在 broker0、broker1、broker2 中)
[hcq@hadoop102 kafka]$ vim increase-replication-factor.json
输入如下内容:
{"version":1,"partitions":[{"topic":"four","partition":0,"replica s":[0,1,2]},{"topic":"four","partition":1,"replicas":[0,1,2]},{"t opic":"four","partition":2,"replicas":[0,1,2]}]}
(2).执行副本存储计划。
[hcq@hadoop102 kafka]$ bin/kafka-reassign-partitions.sh -- bootstrap-server hadoop102:9092 --reassignment-json-file increase-replication-factor.json --execute
遇到的问题
Kafka 创建topic 时抛出 replication factor: 3 larger than available brokers: 0
这里是因为我创建topic副本数不能大于集群中存活的broker数,否则就会抛出这个错误.
我将副本数和分区数改成3就可以正常的创建topic了.
总结
今天学习了Leader如何进行选举,还有Follower或者是Leader出现故障的时候会怎么处理,然后学习了分区副本的分配,并且自己进行手动调整分区,然后就是进行Leader Partition进行负载均衡,平摊这些内存的压力,让这些压力平摊给这些集群里的机子.
11月28日 黑马Kafka
视频链接:
摘要
消费者API
注意:在消费者API 代码中必须配置消费者组 id。命令行启动消费者不填写消费者组 id 会被自动填写随机的消费者组 id.
实现步骤:
-
创建消费者的配置对象
-
给消费者配置对象添加参数
-
对消费者设置反序列化
-
配置消费者组起组名,这一步是必须的
-
创建消费者对象
-
注册消费者主题(这里可以消费多个主题)
-
拉取数据进行打印
订阅分区
对特定的topic只接收设置的Partition的消息.
操作步骤:
-
创建配置文件,添加连接信息,反序列化,组id等信息
-
创建消费者
-
设置订阅的主题和接受哪个分区的消息
-
消费数据,对数据进行拉取
按照时间消费
当我们遇到最近的几个小时的数据异常的时候,想要按照时间进行消费,我们就可以使用按照时间消费的方式重新消费一遍数据,检查数据的异常.
大体的操作步骤都是相同的只不过在订阅主题后进行消费进行设置,设置消费者分区信息,再创建一个HashMap去装前一天的时间,然后将前一天的时间修改成对应的时间offset集合,最后遍历每个分区中的数据进行消费.
遇到的问题
无
总结
今天学习的内容是如何去使用消费者API,其实跟生产者API的方式差不多,也就是进行配置,配置后创建消费者,订阅消费者队列,最后就是循环拉取数据,进行消费数据.还学会了如何去设置读取某一个分区的数据,甚至可以设置设置哪个分区的数据,而且还是限定的topic.还学会如何手动或者自动还有使用时间的方式按照时间消费数据.
11月29日 黑马Kafka
视频链接:
摘要
MySQL环境准备
操作步骤:
1.上传安装包和 JDBC上传到/opt/module/software
2.安装MySQL
卸载自带的MySQL
[hcq@hadoop102 software]$ rpm -qa | grep -i -E mysql\|mariadb |xargs -n1 sudo rpm -e --nodeps
安装MySQL依赖,安装MySQL-client,安装MySQL-server.
[hcq@hadoop102 software]$ sudo rpm -ivh 01_mysql-community-common-5.7.16-1.el7.x86_64.rpm [hcq@hadoop102 software]$ sudo rpm -ivh 02_mysql-community-libs-5.7.16-1.el7.x86_64.rpm [hcq@hadoop102 software]$ sudo rpm -ivh 03_mysql-community-libs-compat-5.7.16-1.el7.x86_64.rpm [hcq@hadoop102 software]$ sudo rpm -ivh 04_mysql-community-client-5.7.16-1.el7.x86_64.rpm [hcq@hadoop102 software]$ sudo rpm -ivh 05_mysql-community-server-5.7.16-1.el7.x86_64.rpm
3.启动MySQL
[hcq@hadoop102 software]$ sudo systemctl start mysqld
查看MySQL原始的密码
[hcq@hadoop102 software]$ sudo cat /var/log/mysqld.log | grep password
配置MySQL
将刚查到的原始密码进行MySQL(如果报错就给密码加上单引号)
[hcq@hadoop102 software]$ mysql -uroot -p'y3wo=X<R1w5e';
修改MySQL密码策略,修改成密码长度最少为4位,策略的复杂程度为0.也就是最简单的.
mysql> set global validate_password_length=4; mysql> set global validate_password_policy=0;
设置简单的密码,我这里设置密码为123456
mysql> set password=password("123456");
进入mysql数据库
查询user和host字段在user表中
修改user表中的host的root权限修改成%
刷新
mysql> use mysql; mysql> selecty use, host from user; mysql> update user set host="%" where user="root"; mysql> flush privileges
Kafka环境配置
操作步骤:
-
关闭Kafka集群
-
修改/opt/moudle/kafka/bin/kafka-server-start.sh
3.分发到其他节点
[hcq@hadoop102 bin]$ xsync kafka-server-start.sh
Kafka-Eagle监控安装
操作步骤:
1.上传压缩包 kafka-eagle-bin-2.0.8.tar.gz 到集群/opt/software 目录
2.将efak解压到/opt/module目录下
第一步先解压到当前文件夹,因为在压缩包中还包了一层,里面的才是真正的efak.
[hcq@hadoop102 software]$ tar -zxvf kafka-eagle-bin2.0.8.tar.gz
将 efak-web-2.0.8-bin.tar.gz 解压至/opt/module
[hcq@hadoop102 kafka-eagle-bin-2.0.8]$ tar -zxvf efak-web2.0.8-bin.tar.gz -C /opt/module/
修改名称为efak
[hcq@hadoop102 module]$ mv efak-web-2.0.8/ efak
修改配置文件 /opt/module/efak/conf/system-config.properties
添加环境变量
配置完环境变量后要进行source /etc/profile
[hcq@hadoop102 conf]$ sudo vim /etc/profile.d/my_env.sh # kafkaEFAK export KE_HOME=/opt/module/efak export PATH=$PATH:$KE_HOME/bin
Kraft 集群部署
再次解压一份 kafka 安装包
[hcq@hadoop102 software]$ tar -zxvf kafka_2.12-3.0.0.tgz -C /opt/module/
重命名为 kafka2
[hcq@hadoop102 module]$ mv kafka_2.12-3.0.0/ kafka2
在 hadoop102 上修改/opt/module/kafka2/config/kraft/server.properties 配置文件
[hcq@hadoop102 kraft]$ vim server.properties
修改的内容为
#节点 ID node.id=2 #全 Controller 列表 controller.quorum.voters=2@hadoop102:9093,3@hadoop103:9093,4@hadoop104:9093 #broker 对外暴露的地址 advertised.Listeners=PLAINTEXT://hadoop102:9092 #kafka 数据存储目录 log.dirs=/opt/module/kafka2/data
分发 kafka2
分发完之后,也要跟Hadoop102一样修改对应的node.id和broker暴露的地址修改对应的主机名
[hcq@hadoop102 module]$ xsync kafka2/
初始化集群数据目录
首先生成存储目录唯一 ID,然后将生成的uuid对Kafka存储目录进行格式化.
最后就是启动Kafka集群和停止Kafka集群进行测试.
遇到的问题
无法访问efak
启动ek.sh start后,按照对应的http网站进行访问但是发现一直在转圈圈,一开始以为是因为不同网段的原因,然后使用虚拟机中的curl命令,进行访问后直接卡死.
kafka-eagle监控界面登录不进去的解决方法_kafka eagle登录不了-CSDN博客
查看了博客但是修改成对应的版本之后就可以正常的进行启动了.
总结
今天学习的内容是学习了如何配置MySQL,这一部分的内容感觉在前面的时候自己有,所以学习起来还是比较容易的.然后就是安装的Kafka-Eagle监控,这个监控安装之后,就可以在web端,查看到对应的生产和消费的情况以图形化的方式展示出来.最后就是构建了一个Kraft集群,总体的步骤跟Kafka差不多就是需要修改的是Kraft文件的配置文件.总体来说还是比较简单没有很难的地方.
11月30日 黑马Kafka
视频链接:
摘要
Kafka集成Flume
安装Flume
1.先上传Flume然后将Flume解压到/opt/module目录下,然后把名字修改成flume
[hcq@hadoop102 software]$ tar -zxvf apache-flume-1.9.0-bin.tar.gz -C /opt/moudle/
[hcq@hadoop102 software]$ mv apache-flume-1.9.0-bin/ flume
将lib文件夹下的guava-11.0.2.jar 删除掉以兼容Hadoop
删除guava-11.0.2.jar服务器节点,一定要配置Hadoop环境变量,否则会出现异常.
[hcq@hadoop102 software]$ rm /opt/module/flume/lib/guava-11.0.2.jar
配置 Flume
在 hadoop102 节点的 Flume 的 job 目录下创建 file_to_kafka.conf
[hcq@hadoop102 flume]$ mkdir jobs [hcq@hadoop102 flume]$ vim jobs/file_to_kafka.conf
配置文件中写入
Flume 消费者
配置 Flume
在 hadoop102 节点的 Flume 的/opt/module/flume/jobs 目录下创建 kafka_to_file.conf
[hcq@hadoop102 jobs]$ vim kafka_to_file.conf
配置文件内容:
启动Flume
[hcq@hadoop102 flume]$ bin/flume-ng agent -c conf/ -n a1 -f jobs/kafka_to_file.conf -Dflume.root.logger=INFO,console
启动 kafka 生产者
[hcq@hadoop103 kafka]$ bin/kafka-console-producer.sh -- bootstrap-server hadoop102:9092 --topic first
查看控制台输出的日志.
Kafka集成Flink
操作步骤:
-
初始化flink环境,设置三个队列进行消费数据
-
准备数据源, 使用ArrayList类型去存储数据,创建出数据流.
-
创建一个Kafka生产者,配置一下连接的信息,然后topic为first.
-
添加数据源,让生产者和flink流关联.
-
执行
总体来说,生产者差不多,就是消费者需要设置groupid其他都差不多.
Kafka集成Springboot
其实主要的代码还是比较简单的,注意的是比如连接信息这些都是配置在application.properties中.其实就是跟使用命令行的方式一样进行生产和消费,就是使用网页的方式将数据放置在访问的参数上,消费者就是监听first主题,然后进行消费数据.
Kafka集成Spark
这里要注意要配置一下Hadoop不然会报错,其他的都差不多都是,放入参数然后定义消费者配置,打印然后执行就可以了.
遇到的问题
Scala类型识别出现问题
具体我也不知道是什么原因,查看了这个博客之后,发现他是修改了一下类d型然后我将ConsumerStrategies.Subscribe加上了[String,String]就可以正常了.
scala+spark: 创建RDD时,显示类型不匹配,Type mismatch。_scala row type mismatch_runing_an_min的博客-CSDN博客
让后就出现了第二个问题
spark运行缺少本地Hadoop环境,您缺少winutils.exe
先是下载了博主的winutils.exe文件.
在程序的开头加上.就可以正常的运行了.但是我发现这样只能解决当下的问题,并不能完全解决这个问题,还是需要配置环境变量.
//在程序中添加如下代码,快速解决当前类问题,彻底解决解决办法二操作 System.setProperty("hadoop.home.dir", "D:\\study\\Java_Tools\\Hadoop")
总结
今天学习了Kafka集成Flume,Flink,Springboot,Spark,其实这几个集成都比较像,都是需要配置连接信息,还有序列化或者反序列化,还有如果是消费者还需要配置groupid,然后就是然后就是定义生产者或者消费者与某些东西进行关联,然后进行消费和发送数据,今天遇到一个问题就是需要winutils的问题还是比较麻烦的,因为仅仅只使用System进行进行设置Hadoop的地址是可以使用的,但是直接配置之后是不能使用的不知道是什么原因,但是后面又解决了,总体来说这一部分的内容是差不多的,大差不差只不过有一些集成又一些区别.