3-26
Hbase查询性能优化
hive和hbase分别适用于分析查询和实时查询
hbase查询优化网址:https://www.cnblogs.com/xjh713/p/7750134.html
hbase万亿性能优化总结:https://blog.csdn.net/odailidong/article/details/41794403
file.block.cache.size:RS的blockcache的内存大小限制,默认值0.25,在偏向读的业务中,可以适当调大该值,具体配置时需试hbase集群服务的业务特征,结合memstore的内存占比进行综合考虑。
hbase.regionserver.global.memstore.upperLimit:默认值0.4,RS所有memstore占用内存在总内存中的upper比例,当达到该值,则会从整个RS中找出最需要flush的region进行flush,直到总内存比例降至该数限制以下,并且在降至限制比例以下前将阻塞所有的写memstore的操作,在以写为主的集群中,可以调大该配置项,不建议太大,因为block cache和memstore cache的总大小不会超过0.8,而且不建议这两个cache的大小总和达到或者接近0.8,避免OOM,在偏向写的业务时,可配置为0.45,memstore.lowerLimit保持0.35不变,在偏向读的业务中,可调低为0.35,同时memstore.lowerLimit调低为0.3,或者再向下0.05个点,不能太低,除非只有很小的写入操作,如果是兼顾读写,则采用默认值即可。
hbase.regionserver.global.memstore.lowerLimit:默认值0.35,RS的所有memstore占用内存在总内存中的lower比例,当达到该值,则会从整个RS中找出最需要flush的region进行flush,配置时需结合memstore.upperLimit和block cache的配置。
Hbase调优:
-
1.hbase.regionserver.handler.count:rpc请求的线程数量,默认值是10,生产环境建议使用100,也不是越大越好,特别是当请求内容很大的时候,比如scan/put几M的数据,会占用过多的内存,有可能导致频繁的GC,甚至出现内存溢出。
-
2.hbase.regionserver.hlog.splitlog.writer.threads:默认值是3,建议设为10,日志切割所用的线程数。
-
3.hbase.hregion.majorcompaction:hbase的region主合并的间隔时间,默认为1天,建议设置为0,禁止自动的major主合并,major合并会把一个store下所有的storefile重写为一个storefile文件,在合并过程中还会把有删除标识的数据删除,在生产集群中,主合并能持续数小时之久,为减少对业务的影响,建议在业务低峰期进行手动或者通过脚本或者api定期进行major合并。
-
4.hbase.hregion.memstore.flush.size:默认值128M,单位字节,一旦有memstore超过该值将被flush,如果regionserver的jvm内存比较充足(16G以上),可以调整为256M。
-
5.hbase.regionserver.global.memstore.upperLimit:(0.35)默认值0.4,regionserver所有memstore占用内存在总内存中的upper比例,当达到该值,则会从整个regionserver中找出最需要flush的region进行flush,直到总内存比例降到该数以下,采用默认值即可。memstore.lowerLimit0.3
-
6.hbase.regionserver.global.memstore.lowerLimit:默认值0.35,采用默认值即可。
-
7.hfile.block.cache.size:(0.4)默认值0.25,regionserver的block cache的内存大小限制,在偏向读的业务中,可以适当调大该值,需要注意的是hbase.regionserver.global.memstore.upperLimit的值和hfile.block.cache.size的值之和必须小于0.8。
-
8.hbase.client.scanner.caching:scan缓存,默认为1,避免占用过多的client和rs的内存,一般1000以内合理,如果一条数据太大,则应该设置一个较小的值,通常是设置业务需求的一次查询的数据条数,如果是扫描数据对下次查询没有帮助,则可以设置scan的setCacheBlocks为false,避免使用缓存
-
9.建表注意事项:开启压缩 合理的设计rowkey 进行预分区 开启bloomfilter
-
10.hbase.hregion.max.filesize配置region大小,0.94.12版本默认是10G,region的大小与集群支持的总数据量有关系,如果总数据量小,则单个region太大,不利于并行的数据处理,如果集群需支持的总数据量比较大,region太小,则会导致region的个数过多,导致region的管理等成本过高,如果一个RS配置的磁盘总量为3T*12=36T数据量,数据复制3份,则一台RS服务器可以存储10T的数据,如果每个region最大为10G,则最多1000个region,如此看,94.12的这个默认配置还是比较合适的,不过如果要自己管理split,则应该调大该值,并且在建表时规划好region数量和rowkey设计,进行region预建,做到一定时间内,每个region的数据大小在一定的数据量之下,当发现有大的region,或者需要对整个表进行region扩充时再进行split操作,一般提供在线服务的hbase集群均会弃用hbase的自动split,转而自己管理split。
-
11.hbase.ipc.client.tcpnodelay:默认是false,建议设为true,关闭消息缓冲
3-28
-
直接建表 PARAM_KEY:transient_lastDdTime
-
建表之后load操作 PARAM_KEY:transient_lastDdTime,numFiles,totalSize=hdfs上文件大小
-
建表之后Insert操作,数据源来自load表,PARAM_KEY:transient_lastDdTime,numFiles,totalSize=hive目录下文件大小,numRows(准确),rawDataSize(准确)
-
建表之后load之后insert PARAM_KEY:transient_lastDdTime,numFiles,totalSize=hive表目录下文件总大小,numRows=insert文件行数(不准确),rawDataSize=insert文件大小
-
建表之后insert再load PARAM_KEY:transient_lastDdTime,numFiles,totalSize=hive表目录下文件总大小,numRows=0,rawDataSize=0
-
建表之后insert、load、insert PARAM_KEY:transient_lastDdTime,numFiles,totalSize=hive表目录下文件总大小,numRows=当前insert文件行数,rawDataSize=当前insert文件rawDataSize
ANALYZE TABLE xzxx COMPUTE STATISTICS;进行统计信息的处理
load数据通过Mysql无法访问到列信息(统计信息)
经测试,NumRows行数信息可以通过mysql与hive方法获得,mysql获取时间较快,但是load与insert载入数据方式不同,通过Insert操作可以在mysql中获得准确信息,通过load操作会使得numRows行数信息不准确,建议执行、ANALYZE TABLE xxx COMPUTE STATISTICS后,再通过mysql查询列信息
此外,两种操作均可以在mysql获得准确的totalsize文件大小参数
IO:同步异步和阻塞非阻塞区别:同步和异步指用户和内核交互方式,阻塞和非阻塞指IO调用的方式。
- IO多路复用是异步阻塞的,因为select相当于同时阻塞多个socket轮询来查看时候数据准备完毕,但是异步是指用户线程不必阻塞,通过reactor设计模式,只要注册事件之后,轮询操作由enventhandler来完成。
select\poll\epoll区别:
从区别来看,poll和select类似,只不过poll没有文件描述符限制,因为是一种类似于链表的结构,缺点就是每次调用二者都需要将fdset从用户空间拷贝到内核空间这样做是无意义的,并且每次调用select都需要轮询所有的fdset,以便查看数据是否准备就绪,而在epoll中便很好的解决了这个问题,因为每个需要挂一遍这个是必不可少的,之后给每个注册一个回掉函数,当有数据就绪的时候,便把可读取的挂到一个队列当中,因此仅查看就绪队列时候有可读取的socket就可以了。
面经总结贴:https://www.nowcoder.com/discuss/167046
3-29
面经汇总地址:https://www.nowcoder.com/discuss/167046?type=0&order=4&pos=23&page=1
反射和代理
-
反射:运行时知道类的方法和属性,运行时调用对象的方法和属性
-
正射:编译器在编译时打开和检查.class文件
-
反射:运行时打开和检查.class文件
-
mapreduce的join操作优化
-
reduce join(网络传输效率最低)
-
map join(大表对小表:小表加载到内存当中)
-
semi join(大表对大表:筛选key)
hive中的join操作
尽量小表join大表,会将小表缓存
/*
线程池模型模型:使用{java.util.concurrent.Executors}实现
*/
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
class MyRunnable implements Runnable {
@Override
public void run() {
for (int x = 0; x < 100; x++) {
System.out.println(Thread.currentThread().getName() + ":" + x);
}
}
}
public class ExecutorServiceDemo {
public static void main(String[] args) {
// 创建一个线程池对象,控制要创建几个线程对象。
// public static ExecutorService newFixedThreadPool(int nThreads)
ExecutorService pool = Executors.newFixedThreadPool(2);
// 可以执行Runnable对象或者Callable对象代表的线程
pool.submit(new MyRunnable());
pool.submit(new MyRunnable());
//结束线程池
pool.shutdown();
}
}
/*
生产者消费者模型:使用{java.util.concurrent.BlockingQueue}实现
*/
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.logging.Level;
import java.util.logging.Logger;
public class ProducerConsumerPattern {
public static void main(String args[]){
//Creating shared object
BlockingQueue sharedQueue = new LinkedBlockingQueue();
//Creating Producer and Consumer Thread
Thread prodThread = new Thread(new Producer(sharedQueue));
Thread consThread = new Thread(new Consumer(sharedQueue));
//Starting producer and Consumer thread
prodThread.start();
consThread.start();
}
}
//Producer Class in java
class Producer implements Runnable {
private final BlockingQueue sharedQueue;
public Producer(BlockingQueue sharedQueue) {
this.sharedQueue = sharedQueue;
}
@Override
public void run() {
for(int i=0; i<10; i++){
try {
System.out.println("Produced: " + i);
sharedQueue.put(i);
} catch (InterruptedException ex) {
Logger.getLogger(Producer.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
}
//Consumer Class in Java
class Consumer implements Runnable{
private final BlockingQueue sharedQueue;
public Consumer (BlockingQueue sharedQueue) {
this.sharedQueue = sharedQueue;
}
@Override
public void run() {
while(true){
try {
System.out.println("Consumed: "+ sharedQueue.take());
} catch (InterruptedException ex) {
Logger.getLogger(Consumer.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
}
4-16
关于hadoop ha,当namenode写editlog时,NameNode会同时向所有JournalNode并行写文件,只要有N/2+1结点写成功则认为此次写操作成功,遵循paxos协议。
NameNode会把edit。
为了保持备用节点和活动节点的同步,需要两个节点来共同访问一个共享存储设备到一个目录。
为了提供快速的故障转移,必须保证备用节点有最新的集群的块的位置信息,为了达到这一点,datanode节点需要配置两个namenode的位置,同时发送块的位置信息和心跳信息到两个nameNode。(即心跳和块报告)
hbase regionsever向zookeeper注册,提供hbase regionsever状态信息(是否在线),hmaster启动时候会将habse系统表-Root-加载到zookeeper cluster,通过zookeeper cluster可以获取当前系统表.META.存储对应的regionserver信息。HMaster主要作用在于,通过HMASTER维护系统表-Root-,META,记录regionsever所对应region变化信息。此外还负责监控处理当前hbase cluster中regionsever状态变化信息。
总结三点(zookeeper在hbase中):
1.HRegion的寻址入口(即root表的地址的)
2.实时监控HRegion的上线下线信息
3.HBase中几乎所有的元数据存储都是放在ZooKeeper上
我们使用spark-submit提交一个Spark作业之后,这个作业就会启动一个对应的Driver进程。根据你使用的部署模式(deploy-mode)不同,Driver进程可能在本地启动,也可能在集群中某个工作节点上启动。Driver进程本身会根据我们设置的参数,占有一定数量的内存和CPU core。而Driver进程要做的第一件事情,就是向集群管理器(可以是Spark Standalone集群,也可以是其他的资源管理集群,美团•大众点评使用的是YARN作为资源管理集群)申请运行Spark作业需要使用的资源,这里的资源指的就是Executor进程。YARN集群管理器会根据我们为Spark作业设置的资源参数,在各个工作节点上,启动一定数量的Executor进程,每个Executor进程都占有一定数量的内存和CPU core。
在申请到了作业执行所需的资源之后,Driver进程就会开始调度和执行我们编写的作业代码了。Driver进程会将我们编写的Spark作业代码分拆为多个stage,每个stage执行一部分代码片段,并为每个stage创建一批task,然后将这些task分配到各个Executor进程中执行。task是最小的计算单元,负责执行一模一样的计算逻辑(也就是我们自己编写的某个代码片段),只是每个task处理的数据不同而已。一个stage的所有task都执行完毕之后,会在各个节点本地的磁盘文件中写入计算中间结果,然后Driver就会调度运行下一个stage。下一个stage的task的输入数据就是上一个stage输出的中间结果。如此循环往复,直到将我们自己编写的代码逻辑全部执行完,并且计算完所有的数据,得到我们想要的结果为止。
4-17
spark运行流程:
1.Client运行时向Master发送驱动申请(发送RequestSubmitDriver指令)
2.Master调度可用Worker资源进行驱动安装(发送LaunchDriver)
3.Worker运行DriverRunner进行驱动加载,并向Master发送应用注册请求(发送RegisterApplication指令)
4.Master调度可用Worker资源进行应用的Executor安装(发送LaunchExecutor指令)
5.Executor安装完毕后向Driver注册驱动可用Excutor资源(发送RegisterExecutor指令)
6.最后是运行用户代码时,通过DAGScheduler,TaskScheduler封装为可以执行的TaskSetManager对象
7.TaskSetManager对象与Driver中的Executor资源进行匹配,在队形的Exxcutor中发布任务(发送LaunchTaskz指令)
8.TaskRunner执行完毕后,调用DriverRunner提交给DAGScheduler,循环7直到完成
4-19
public class Singleton {
volitale private static Singleton instance;
private Singleton (){
}
public static Singleton getInstance(){ //对获取实例的方法进行同步
if (instance == null){
synchronized(Singleton.class){
if (instance == null)
instance = new Singleton();
}
}
return instance;
}
}