1.当用户请求删除一条记录时,hbase为什么不直接删除,而是打上一个删除的标记?
因为hbase的数据通常是保存在HDFS上,而hdfs只允许新增或者追加数据文件,
如果要删除的话要对整个文件进行替换,所以删除操作主要是对删除的数据打上标记.
具体操作:
当多个storefile进行major_compact全局合并时,就会真正对那些打标记的数据进行删除。
并生成对应的hfile文件。
2. spark执行过程中的stage是如何划分的?
**stage是根据宽窄依赖将一个spark根据宽窄依赖将一个spark job划分为不同的stage。而宽依赖就是划分的标准,**
宽依赖:rdd中的partition中的数据依赖父rdd中的所有的partition.(多对一)遇到一个宽依赖就会从中一切为二,划分为两个stage。
stage分为两种:resultstage和shufflemapstage两种,sparkjob 最后产生的stage为resultstage,中间阶段产生的stage为shufflemapstage。
过程:
dag scheduler 实现spark作业分解成多个stage,每个stage根据partition的个数划分task的个数,
Task scheduler 主要是将dag scheduler划分的stage(以task形式)分发到Executor执行,通过多个task实现并行运行的功能
3, sparkstreaming数据写入mysql用的什么算子?为什么不用mappartition?
使用foreachpartition
因为map操作不会进行数据计算,只有在actions算子的操作才会进行真正的计算。
代码:
wordcounts.foreachRDD(rdd => rdd.foreachPartition(line => {
Class.forName("com.mysql.jdbc.Driver")
//获取mysql连接
val conn = DriverManager.getConnection("jdbc:mysql://master:3306/test", "root", "123456")
//把数据写入mysql
try {
for (row <- line) {
val sql = "insert into wordcount(titleName,count)values('" + row._1 + "','" + row._2 + "')"
conn.prepareStatement(sql).executeUpdate()
}
} finally {
conn.close()
}
}))
ssc.start()
ssc.awaitTermination()
}
4, spark如何和kafka对接 ?
spark-steaming-kafka-0.8版本
有两种连接方式:
Receiver 和 Direct方法
Receiver创建:
kafkautils.createstream(ssc,zookeeper,groupId,topics);
需要单独一个线程来接受数据,上面的方式只会从最新的位置开始消费;
Driver创建:
kafkautils.createDirectstream(ssc,kafkaparams,topics)
val kafkaparams = map(string,string){键值对类型的参数}
Receiver方式
该方式只能为0-8版本到之后可以使用,到0-10版本就不好使了
构造函数中的numThreads参数,对应提高sparkstreaming的并行度并没有关系,提高只有kafka的分区数才能提高并行度,增加读写速度
这种情况可能会出现数据丢失问题,在driver端挂掉,Executor重启的时候必然会丢数据,在1.2时增加了一个Write Ahead Logs的机制(在写到Receiver时,写到一个日志中,通常为HDFS),这个机制可以避免数据丢失,但是写到HDFS或者文件系统必然会降低吞吐量。同时启动Write Ahead Logs时,存储结构设置为StorageLevel.MEMORY_AND_DISK_SER,不需要多副本,因为HDFS就是多副本机制
由于应用WAL,所以语义为至少一次
Direct Approach方式
1.没有Recevie