推荐算法的调优内容主要有什么?


        培养良好的工程习惯相当重要,前期可能须要一些学习成本,但到后期你会发现养成了好习惯反而能省不少时间,尤为是当任务量比较大或者是须要开展持续的工做的时候,你会发现以前的付出真的颇有意义。
        举个简单的例子,你若是研究目标检测,这是当前很热的领域哇,不少人都在作。要想突破可能须要更多的实验去尝试,在实验过程会用到COCO和Pascal VOC数据集,评价标准也相对复杂;同时目标检测的代码量又相对较大,为了提升运行效率部分代码甚至会用C++实现,目前google还提出了swift for TensorFlow,运行速度达到C语言级别。拿到这么冗杂的一套系统,不管是用来作研究仍是作工程,都须要一套科学严谨的准则,不然到最后发现会乱成一锅粥,不知道对错。
        本文就是做者总结的一些在深度学习领域一些好的规则和习惯,都是本身的踩坑心路历程。记住,播种一个行为,收获一种习惯,日积月累,必有回响。

一般我会使用一个简单的CNN模型(CV领域作5个卷积层,NLP领域作1个卷积层)将数据扔进去训练跑出一个baseline,这一步工做主要是为了验证数据集的质量。若是这个模型训练结果不好就不要先调试模型,须要检查一下你的训练集数据,看看图像的质量,图像标签是否正确,模型的代码是否正确等等,不然就是在作无用功。而后逐渐添加模型的复杂性,同时检验模型结构的每一个层面(附加层、参数等)是否有效。

        其次,在单个数据节点上训练模型:可使用一两个训练数据点(data point)以确认模型是否过分拟合。神经网络应当即过分拟合,训练准确率为 100%,这代表模型符合;若是模型没法过分拟合这些数据点,就证实过小或存在 bug。

模型损失是评估模型性能的主要方式,也是模型设置重要参数以进行评估的依据,所以须要确保:

        正确衡量损失函数的重要性。若是你使用多种类型的损失函数,如 MSE、对抗性、L一、feature loss,,那么请确保全部损失以正确的方式排序。

      为了调试神经网络,你须要理解神经网络内部的动态、不一样中间层所起的做用,以及层与层之间是如何链接起来的。不过,你可能遇到如下问题:

        若是梯度值为 0,则意味着优化器中的学习率可能过小,且梯度更新的表达式不正确。除了关注梯度的绝对值以外,还要确保监视每一个层匹配的激活、权重的大小。例如,参数更新的大小(权重和误差)应为 1-e3。须要指出的是,一种称为 “Dying ReLU” 或“梯度消失”的现象中,ReLU 神经元在学习其权重的负误差项后将输出为 0。这些神经元不会在任何数据点上获得激活。你能够采用梯度检验(gradient checking)经过数值方法逼近梯度以检验这些错误。若是它接近计算梯度,则正确实施反向传播。

        初始方法:展示训练模型的总体结构,这些方法包括展现神经网络各个层的形状或过滤器(filters)以及每一个层中的参数;

        基于梯度的方法:在训练模型时,操做由前向或后向通道造成的梯度。

还有有许多可用的工具可用于可视化各个层的激活和链接,例如 ConX 和 Tensorboard。

用16或者32不会过拟合,optimizer用Adam(学习率建议用论文中默认的,我试过调整Adam的学习率,效果或都没有默认的好),激活函数用relu这个应该是你们的共识吧。还有就是先跑几百个epoch看loss的变化趋势。

size:对于小数据量的模型,能够全量训练,这样能更准确的朝着极值所在的方向更新。可是对于大数据,全量训练将会致使内存溢出,所以须要选择一个较小的batch_size。若是这时选择batch_size为1,则此时为在线学习,每次修正方向为各自样本的梯度方向修正,难以达到收敛。batch_size增大,处理相同数据量的时间减小,可是达到相同精度的轮数增多。实际中能够逐步增大batch_size,随着batch_size增大,模型达到收敛,而且训练时间最为合适。

学习率(Learning rate):过低会致使收敛缓慢或陷入局部最小值的风险,过高则会致使优化发散。学习速率的设置第一次能够设置大一点的学习率加快收敛,后续慢慢调整;也能够采用动态变化学习速率的方式(好比,每一轮乘以一个衰减系数或者根据损失的变化动态调整学习速率)。

机器学习框架,如 Keras、Tensorflow、PyTorch、MXNet 如今都有关于使用学习率收敛缓慢文档或示例:

固然,全部这些算法——尽管它们都很好——并不老是在实践中起做用。在训练神经网络时还有许多其余因素须要考虑,例如你将如何预处理数据,定义模型,你还须要真的搞定足够跑这一整个流程的计算力。Nanonets提供易于使用的API来训练和部署自定义深度学习模型。它能负责全部的繁重工做,包括数据扩充,转移学习,以及超参数优化!Nanonets在其庞大的GPU集群上使用贝叶斯搜索来找到正确的超参数集,你压根不用担忧得在最新的显卡上再大花一笔钱啦。一旦找到最佳模型,Nanonets就会把它放在云端,以便你使用其Web界面测试模型,或使用两行代码将其集成到你的程序中。

        图像预处理的时候通常我会抽出部分图像观察,对图像中的噪声进行滤波,图像标签要验证一下,其余的预处理就结合实际状况来看了。通常来讲,数据清洗的工做占比是多于写模型的工做(一般是7:3)。

        经常使用的数据加强方法包括:图像缩放图像翻转图像裁剪图像色彩的饱和度、亮度和对比度变换
        海康威视在ImageNet上曾经用过PCA Jittering方的法,可是因为这个方法的计算量过大,我没有在本身的训练中使用过。他们还使用了有监督的数据加强的方法,有兴趣的同窗能够研究一下。

过采样:一种是增长样本少的类别的图像数目,能够用上述数据加强的方法。
欠采样:将样本多的类别图像数目减小,能够说是很是简单粗暴了。
权重法:增长少样本在训练时的权重,间接地加强了图像数目。

        当任务变得复杂,数据规模变大时,框架提供的接口不能知足你的需求,这时你须要有本身的data generation function。例如,我使用keras时须要对输入图片进行多标签任务的训练,而keras自己不包含这样的接口,因此须要本身实现一个data generation function。经过查看官方文档和相关接口实现了一个多标签数据生成器(写这个数据生成器的时候被官方文档坑了一次,暂且不表,下次另起一文详说),代码以下:

# 须要在函数体内进行初始化, # 不然会在上次的结果后继续使用list

        手动记录信息可能很难作到且进行屡次实验,像 comet.ml 这样的工具能够帮助自动追踪数据集、更改代码、实验历史和生产模型,包括关于模型的关键信息,如超参数、模型性能指标和环境细节。

        神经网络对数据、参数,甚至 packages 的微小变化都很是敏感,这致使了模型的性能降低。工做跟踪是标准化环境和建模工做流程的第一步。

第一层境界:放心大胆的使用百度或Google吧,看看有没有前人作过相似的工做;其次去知乎,CSDN,简书上搜搜看,可能会有文章带给咱们启发;若是是找一些学习资料或视频直接B站或者YouTube搜索;还有就是关注一些DL技术公众号,PaperWeekly,CVer,量子位,机器之心等等..(我不是打广告,这些公众号你们可能都已经关注过)

        第二层境界:等有一些基本的概念和了解以后就要去查阅相关领域的论文,去Google学术、百度学术或arxiv检索相关的文献,看论文是很是有必要和有用的,由于Paper也算是可信度高内容丰富的技术文档,必定要跳出温馨区,我几乎天天看一篇,短暂的时间看不懂很正常,可是氛围得养起来。

        进阶:去github搜索相关论文的代码,论文和代码搭配使用效果更佳;大佬们的Github.io隐藏着不少干货;Kaggle或天池上面不少优秀的Kernel或许可以提供新的思路;一些大佬本身的网站上面也会有不少干货,说不定就能淘到咱们想要的东西

首先固然是百度和google,github的issue,StackOverflow都是查找解决方案的好地方;若是身边有大牛的话也要虚心请教;一些技术交流QQ或微信群也是咱们获取答案的好地方。好比我加了Pytorch交流群,里面很活跃,大佬们也不吝赐教,群里可能有人发一些最新资料,这对新手来说是很好学习途径。多水一水群既能够开阔视野,同时又能够摸鱼闲聊。

在训练以前要合理规划文件夹的命名以及层级结构,使用简洁的英文单词命名文件。不要觉得这是一个小事情,前期没有一个好的组织结构,没有规范的管理方式,等后期代码文件多了再想起重构是一件很是麻烦的事情。你们能够看一下Mask-RCNN仓库的组织结构,虽然项目工程很大,但总体结构层次分明。这和初高中时成绩好的同窗做业本写得工整,成绩差的同窗写得潦草一个道理。(我也是看到大佬们的工做才认识到自身的不足,多看牛人的代码真的是一种洗礼)

你的工程中应该包含以下模块:

训练Loss日志:建议使用Tensorboard,由于如今tf和pytorch都支持这个工具,用起来也很简单,所以强烈推荐使用,我看到以前一些人的代码中可能写了log的方法,但如今官方提供了更强大的工具建议就不要用本身造的轮子了。注意,日志文件夹命名最好要有区别,建议使用时间戳命名,不然全部的日志混杂在一块儿将会乱成一锅粥。

模型存储:用一个文件夹来专门存放训练的模型,每一个模型的命名建议花点心思,最好要包含有用的信息,方便查找使用

参数配置文件config:将训练网络的超参数和配置文件参数都放在专门的文件中统一管理,不要在训练主程序中东一坨西一坨,改来改去到最后很容易出现疏忽

数据集文件夹:此处建议全部的数据使用软链接的方式链接到工程文件夹,对原始数据加一些权限防止误删或更改;工程中的数据路径建议使用相对路径而非绝对路径!!绝对路径会致使你的工程文件夹换个地方就报错

函数工具包:把本身自定义的类和方法统一放到一个地方,增长模块的复用性。

训练和推断的程序:如今流行的作法就是把网络封装成一个训练器,在指定文件中配置好路径参数,直接运行程序就开始训练了,模型设计好了就专心训练和调参,能够看到keras训练和Detecron中都是这种设计模式,把数据灌进去就OK了。若是本身从新开始搭工程能够借鉴一下这种思路。

网络模型结构:当网络比较复杂的话,专门建一个包来存放网络结构

训练快照:也就是你当前训练出来模型对应的参数配置,我的以为这点挺实用,防止最后训练了半天不知道用的啥参数啥数据集。

可视化:有一种方法可能会致使深度学习模式的训练出错。当模型被训练几个小时或几天,而且只有在训练结束后,咱们才意识到出了问题。在这种状况下(这多是很是合理的))  - 始终可视化训练过程。你能够采起最明显的一步是打印/保存日志的loss值,train error或test error等。除此以外,另外一个良好的作法是使用一个可视化库来绘制几个训练样例或时代之间的权重直方图。这可能有助于跟踪深度学习模型中的一些常见问题,如梯度消失、梯度爆炸等。

总之:清爽的工程令人愉悦,杂乱的工程令人爆炸

        咱们开展一个任务,上手的第一个环节多是clone别人的代码而后准备复现,Wait.第一步不要猴急猴急地去run人家的代码,我建议走下面的流程:

        1.理清任务和评价标准,对算法精度有一个宏观的理解,也就是知道人家差很少能作到啥程度

        2.先去看一下训练的数据,若是是图片的话先用肉眼随机抽样看一看,人类是一种很是高级和敏感的动物,说不定就会有意想不到的发现;看完了以后若是有代码基础就作一下数据统计分布,数据探索分析。

        3.看一下原做者写的Readme文件,里面会概述本工程的一些组织结构和使用方法,这是很重要的一个环节。根据做者的提示能够去Run程序,训练推断都玩一玩,这样很容易让本身有成就感。

4.代码跑起来了不表明这个工程就是对的,必定要仔细地检查原做者的代码细节和实现思路,防止代码有坑,这点很关键(不要认为人家是大佬还发过论文,放出来的代码就没毛病了!)。我我的喜欢边看边注释原代码核心算法,若是搞清楚了能够先给身边的同事讲一讲,讲懂了说明本身也会了。完全核实清楚以后才能把这份Solution做为本身的Baseline,不要等到效果迟迟不见提高回过头来才发现,哦,原来这个代码有问题啊(也不必定是人家代码有误,极可能是本身没搞懂就用和本身的任务冲突),悔恨当时怎么没注意呢>_<。

        稍微了解一下框架的原理和实现,不管是对写代码仍是理解DL基础知识都是颇有帮助的。举个例子,你知道BN是咋实现的?反向传播是怎么搞的?看一下框架中的代码实现会帮助咱们理解其中的原理,在调用函数的时候也不会犯错。
如今DL框架基本上分两大阵营(Mxnet和PP用户勿喷)——Pytorch和TF。建议看官方Document和Tutorial,这是极好的入坑指南,有精力的同窗能够看一下源码的实现代码,太底层C实现的东西不建议新手玩家体验,仍是先攻关主要矛盾(逃),若是修炼到必定境界仍是要普遍涉猎一些的。

        前期能够在baseline上作一些改动,而后看一下效果如何,分析问题出在哪里。譬如来一个连环问,是哪些类分很差?为何分很差?是由于这个类特征难学吗?加一些什么模块或者机制可以更好的学特征?

        而后多去看一些论文,汲取其中的精华,而后回来接着作实验,这是一种问题驱动型的思路。总之要养成多看论文的习惯,不论作检测、分割仍是跟踪重识别,一些经典的DL论文是必定要看的,经典论文中有不少普适性的insight,多看论文才能拓宽思路有所启发。

        肯定好了思路开始跑实验验证,记住首先要小样本(少许的数据)测试本身的算法是否work,看一下有没有初步的效果。切忌一股脑成千上万开始训练,训了半天发现那个地方有疏忽又从头开始训练。

调参也是很重要的过程。深度学习训练说白了是一个数学优化过程,不要忽视了超参数对最终效果的影响,至于如何调参网上文章不少,好比过拟合怎么办,学习率怎么调,梯度爆炸咋处理?看再多理论没有亲身经历过永远是外行,我建议仍是要亲自动手训练感觉才深入。结合数学理论宏观地分析缘由,举个例子,mini-batch中的样本不平衡会如何影响优化方向?梯度爆炸的数学缘由从何而来?若是Loss非凸会对优化带来什么影响?two-stage模型像不像是个条件几率?这样对本身的总体能力提高颇有帮助。我我的认为,深度学习底层虽然不可知,可是从宏观上来说仍是服从统计学、优化理论的一些规则,善于从数学角度去分析模型很重要。

良好的代码风格以及版本控制

看大佬的代码你会发现人家不光是学术搞得好,代码敲得也贼666啊。多去看看名家的代码对本身是颇有裨益的,甚至没事的时候能够跟着敲一敲练手。那么总结一下大佬的代码会发现人家的代码风格基本上遵循Google代码规范,并且有命名优雅、注释详细、函数之间耦合性低、逻辑清晰等优势。这些东西一时半会培养不来,可是平时注意培养代码风格习惯,日积月累确定会有提升的。

        不要在同一个坑里面摔倒三次(容许多摔一次)!!遇到问题及时解决和并记录,不作重复性工做。这是我屡次失败的一个教训,我以前也没有作笔记的习惯,但其实人脑很容易遗忘,作笔记是一件颇有必要的事情。

        推荐一个适合程序员作笔记的工具Leanote,若是使用官方提供的服务器须要每个月交五块钱。若是不想花钱能够将Leanote开源的的代码部署到本地服务器上

        使用Wiki系统进行知识库管理。天天作完工做都要有必定的收获。我使用的是confluence,天天坚持写一写,对本身既是督促也是提高。

由于是批量发送,数据并非真正的实时;

对于mqtt协议不支持;

不支持物联网传感数据直接接入;

仅支持统一分区内消息有序,无法实现全局消息有序;

监控不完善,需要安装插件;

依赖zookeeper进行元数据管理;

旧的 Kafka 消费者 API 主要包括:SimpleConsumer(简单消费者) 和 ZookeeperConsumerConnectir(高级消费者)。SimpleConsumer 名字看起来是简单消费者,但是其实用起来很不简单,可以使用它从特定的分区和偏移量开始读取消息。高级消费者和现在新的消费者有点像,有消费者群组,有分区再均衡,不过它使用 ZK 来管理消费者群组,并不具备偏移量和再均衡的可操控性。

现在的消费者同时支持以上两种行为,所以为啥还用旧消费者 API 呢?

54.Kafka 分区数可以增加或减少吗?为什么?

我们可以使用 bin/kafka-topics.sh 命令对 Kafka 增加 Kafka 的分区数据,但是 Kafka 不支持减少分区数。Kafka 分区数据不支持减少是由很多原因的,比如减少的分区其数据放到哪里去?是删除,还是保留?删除的话,那么这些没消费的消息不就丢了。如果保留这些消息如何放到其他分区里面?追加到其他分区后面的话那么就破坏了 Kafka 单个分区的有序性。如果要保证删除分区数据插入到其他分区保证有序性,那么实现起来逻辑就会非常复杂。

 kafka通过 topic来分主题存放数据,主题内有分区,分区可以有多个副本,分区的内部还细分为若干个 segment。都是持久化到磁盘,采用零拷贝技术。

分区下面,会进行分段操作,每个分段都会有对应的素引,这样就可以根据 offset二分查找定位到消息在哪一段,根据段的索引文件,定位具体的 mle ssage

2、分区副本可用性(1 eader选举,zk来协调

如果1eader宕机,选出了新的1eader,而新的 leader并不能保证已经完全同步了之前1eader的所有数据,只能保证HW(高水位设置)之前的数据是同步过的,此时所有的 follower都要将数据截断到W的位置,再和新的 leader同步数据,来保证数据一致。

当宕机的 leader恢复,发现新的1eader中的数据和自己持有的数据不一致,此时宕机的1 eader会将自己的数据截断到宕机之前的hw位置,然后同步新1 eader的数据。宕机的1eader活过来也像 follower一样同步数据,来保证数据的一致性。

56.相比较于传统消息队列,kafka的区别

1、分区性:存储不会受单一服务器存储空间的限制

3、消息有序性:一个分区内是有序的。

4、负载均衡性:分区内的一条消息,只会被消费组中的一个消费者消费,主题中的消息,会均衡的发送给消费者组中的所有消费者进行消费。

57.消息丢失和消息重复

同步:这个生产者写一条消息的时候,它就立马发送到某个分区去。

异步:这个生产者写一条消息的时候,先是写到某个缓冲区,这个缓冲区里的数据还没写到 broker集群里的某个分区的时候,它就返回到 client去了

针对消息丢失:同步模式下,确认机制设置为-1,即让消息写入 Leader和 Fol lower之后再确认消息发送成功:

异步模式下,为防止缓冲区满,可以在配置文件设置不限制阻塞超时时间,当缓冲区满时让生产者一直处于阻塞状态

针对消息重复,将消息的唯一标识保存到外部介质中,每次消费时判断是否处理过即可

在HBase中Hmaster负责监控RegionServer的生命周期,均衡RegionServer的负载,如果Hmaster挂掉了,那么整个HBase集群将陷入不健康的状态,并且此时的工作状态并不会维持太久。所以HBase支持对Hmaster的高可用配置。

HBase操作过程中需要大量的内存开销,毕竟Table是可以缓存在内存中的,一般会分配整个可用内存的70%给HBase的Java堆。但是不建议分配非常大的堆内存,因为GC过程持续太久会导致RegionServer处于长期不可用状态,一般16~48G内存就可以了,如果因为框架占用内存过高导致系统内存不足,框架一样会被系统服务拖死。

2.hbase的rowkey怎么创建好?列族怎么创建比较好?

hbase存储时,数据按照Row key的字典序(byte order)排序存储。设计key时,要充分排序存储这个特性,将经常一起读取的行存储放到一起。(位置相关性)

一个列族在数据底层是一个文件,所以将经常一起查询的列放到一个列族中,列族尽量少,减少文件的寻址时间。

1)生成随机数、hash、散列值

增强hbase查询数据的功能

减少服务端返回给客户端的数据量

答:宕机分为HMaster宕机和HRegisoner宕机,如果是HRegisoner宕机,HMaster会将其所管理的region重新分布到其他活动的RegionServer上,由于数据和日志都持久在HDFS中,该操作不会导致数据丢失。所以数据的一致性和安全性是有保障的。

2.Hive是建立在Hadoop之上为了减少MapReduce jobs编写工作的批处理系统,HBase是为了支持弥补Hadoop对实时操作的缺陷的项目 。

5.Hive本身不存储和计算数据,它完全依赖于HDFS和MapReduce,Hive中的表纯逻辑。

7.hbase是物理表,不是逻辑表,提供一个超大的内存hash表,搜索引擎通过它来存储索引,方便查询操作。

9.hdfs作为底层存储,hdfs是存放文件的系统,而Hbase负责组织文件。

5/ regionserver接收到客户端发来的请求之后,就会将数据写入到region中

如果是从StoreFile里面读取的数据,不是直接返回给客户端,而是先写入BlockCache,再返回给客户端。)

1)当MemStore数据达到阈值(默认是128M,老版本是64M),将数据刷到硬盘,将内存中的数据删除,同时删除HLog中的历史数据;

2)并将数据存储到HDFS中;

3)在HLog中做标记点。

当数据块达到4块,hmaster将数据块加载到本地,进行合并

当合并的数据超过256M,进行拆分,将拆分后的region分配给不同的hregionserver管理

1、管理用户对Table的增、删、改、查操作;

HRegion Server主要负责响应用户I/O请求,向HDFS文件系统中读写数据,是HBASE中最核心的模块。

HBase有多个RegionServer,每个RegionServer里有多个Region,一个Region中存放着若干行的行键以及所对应的数据,一个列族是一个文件夹,如果经常要搜索整个一条数据,列族越少越好,如果只有一部分的数据需要经常被搜索,那么将经常搜索的建立一个列族,其他不常搜索的建立列族检索较快。

12.请简述Hbase的物理模型是什么

13.请问如果使用Hbase做即席查询,如何设计二级索引

14.如何避免读、写HBaes时访问热点问题?

这里所说的加盐不是密码学中的加盐,而是在rowkey的前面增加随机数,具体就是给rowkey分配一个随机前缀以使得它和之前的rowkey的开头不同。给多少个前缀?这个数量应该和我们想要分散数据到不同的region的数量一致(类似hive里面的分桶)。

( 自己理解:即region数量是一个范围,我们给rowkey分配一个随机数,前缀(随机数)的范围是region的数量)

加盐之后的rowkey就会根据随机生成的前缀分散到各个region上,以避免热点。

哈希会使同一行永远用一个前缀加盐。哈希也可以使负载分散到整个集群,但是读却是可以预测的。使用确定的哈希可以让客户端重构完整的rowkey,可以使用get操作准确获取某一个行数据。

第三种防止热点的方法是反转固定长度或者数字格式的rowkey。这样可以使得rowkey中经常改变的部分(最没有意义的部分)放在前面。这样可以有效的随机rowkey,但是牺牲了rowkey的有序性。反转rowkey的例子:以手机号为rowkey,可以将手机号反转后的字符串作为rowkey,从而避免诸如139、158之类的固定号码开头导 致的热点问题。

一个常见的数据处理问题是快速获取数据的最近版本,使用反转的时间戳作为rowkey的一部分对这个问题十分有用,可以用Long.Max_Value – timestamp追加到key的末尾,例如[key][reverse_timestamp] ,[key] 的最新值可以通过scan [key]获得[key]的第一条记录,因为HBase中rowkey是有序的,第一条记录是最后录入的数据。

(5)尽量减少行和列的大小

在HBase中,value永远和它的key一起传输的。当具体的值在系统间传输时,它的rowkey,列名,时间戳也会一起传输。如果你的rowkey和列名很大,HBase storefiles中的索引(有助于随机访问)会占据HBase分配的大量内存,因为具体的值和它的key很大。可以增加block大小使得storefiles索引再更大的时间间隔增加,或者修改表的模式以减小rowkey和列名的大小。压缩也有助于更大的索引。

列族名的长度尽可能小,最好是只有一个字符。冗长的属性名虽然可读性好,但是更短的属性名存储在HBase中会更好。也可以在建表时预估数据规模,预留region数量,例如create ‘myspace:mytable’, SPLITS => [01,02,03,,…99]

15.布隆过滤器在HBASE中的应用

16.Hbase是用来干嘛的?什么样的数据会放到hbase

18.Hbase在建表时的设计原则(注意事项)

 Hbase默认建表时有一个 region,这个 region的 rowkey是没有边界的,即没有 startkey和 endkey在数据写入时,所有数据都会写入这个默认的 region,随着数据量的不断增加,会进行 split,分成2个 region在此过程中,会产生两个问题:

1.数据往一个 region写,会有写热点问题。2. region split会消耗宝贵的集群I/0资源。我们可以控制在建表的时候,创建多个空 region,并确定每个 region的 startkey和 endkey,这样只要我们的 rowkey设计能均匀的命中各个 region,就不会存在写热点问题。自然 split的几率也会大大降低。

(1) rowkey长度越短越好。数据的持久化文件 Hfile中是按照 Keyvalue存储的,如果 rowkey过长会极大影响File的存储效率; Memstore将缓存部分数据到内存,如果 rowk-ey字段过长,内存的有效利用率就会降低,系统不能缓存更多的数据,这样会降低检索效率。

2) rowkey尽量散列。建议将 rowkey的高位作为散列字段,将提高数据均衡分布在每个 Regionserver以实现负载均衡的几率。(哈希、反转等也可以避免热点问题

(1)建表至少指定一个列族,但一般不超过三个,一般一个,因为 flush和 compact是以 region为单位,所以,某个 column family在 flush的时候,它邻近的 column family也会因关联效应被触发f1ush,最终导致系统产生更多的1/0

2)列族名字不宜过长,会冗余存储。

3)不同列族的记录的数量级不易相差太大,比如A,B两个列族,A为100万条,B为100亿条,则A会被分散到多个 region(可能会跨 reglon server),导致对A的扫描效率低下

根据你的 Rowkey设计来进行预建分区,减少 region的动态分裂。

2)给HFi1设定合适大小

 Hfile是数据底层存储文件,在每个 memstore进行刷新时会生成一 Hfile,当 Hfile增加到一定程度时,会将属于一个 region的HFi1e进行合并,这个步骤会带来开销但不可避免,但是合并后 reglon大小如果大于设定的值,那么 region会进行分裂。为了减少这样的无谓的1/0开销,建议估计项目数据量大小,给 Hfile设定一个合适的值

 Hbase中也存在频繁开启关闭帯来的问题。

(1)开启过滤,提高查询速度,可以减少网络102)使用压缩:一般推荐使用 Snappy和LZ0压缩。

4、合理设计(建表注意事项)

分区、 Rowkey设计、列族的设计

Region进行分组,切分到每个 regionserver中,因此在回放之前首先需要将og按照 Region进行分组,每个 Region的日志数据放在一起,方便后面按照 Region进行回放。这个分组的过程就称为HLog切分。然后再对 region重新分配,并对其中的Hog进行回放将数据写入 memstore刷写到磁盘,完成最终数据恢复。

1.维表和宽表的考查(主要考察维表的使用及维度退化手法)

维表数据一般根据ods层数据加工生成,在设计宽表的时候,可以适当的用一些维度退化手法,将维度退化到事实表中,减少事实表和维表的关联

4.一亿条数据查的很慢,怎么查快一点

时间维表,用户维表,医院维表等

日志数据:ng日志,埋点日志

7.你们最大的表是什么表,数据量多少

ng日志表,三端(app,web,h5)中app端日志量最大,清洗入库后的数据一天大概xxxxW

9.数据平台是怎样的,用到了阿里的那一套吗?

没用到阿里那一套,数据平台为自研产品

10.你了解的调度系统有那些?,你们公司用的是哪种调度系统

11.你们公司数仓底层是怎么抽数据的?

业务数据用的是datax

13.埋点数据你们是怎样接入的

14.如果你们业务库的表有更新,你们数仓怎么处理的?

15.能独立搭建数仓吗

17.说一下你们公司的大数据平台架构?你有参与吗?

18.介绍一下你自己的项目和所用的技术

19.对目前的流和批处理的认识?就是谈谈自己的感受

20.你了解那些OLAP 引擎,MPP 知道一些吗?clickHouse 了解一些吗?你自己做过测试性能吗?

21.Kylin 有了解吗?介绍一下原理

23.你们数仓的APP 层是怎么对外提供服务的?

1.直接存入mysql业务库,业务方直接读取

2.数据存入mysql,以接口的形式提供数据

3.数据存入kylin,需求方通过jdbc读取数据

24.数据接入进来,你们是怎样规划的,有考虑数据的膨胀问题吗

25.简述拉链表,流水表以及快照表的含义和特点

27.你们公司的数仓分层,每一层是怎么处理数据的

28.什么是事实表,什么是维表

29.星型模型和雪花模型

30.缓慢变化维如何处理,几种方式

33.工作中碰到什么困难,怎么解决的

34.如何用数据给公司带来收益

35.需求驱动和业务驱动,数据开发和ETL开发,实战型和博客型

36.如何用数据实现业务增长,黑客增长?

37.什么是大数据?千万级别的数据完全可以用传统的关系型数据库集群解决,为什么要用到大数据平台。

38.数据质量,元数据管理,指标体系建设,数据驱动

39.什么是数仓,建设数仓时碰到过什么问题

41.维度建模和范式建模的区别;

42.埋点的码表如何设计;

43.集市层和公共层的区别;

44.缓慢变化维的处理方式

46.说说你从0-1搭建数仓都做了什么?你觉得最有挑战的是什么?

47.数据模型如何构建,星型、雪花、星座的区别和工作中如何使用;

48.如何优化整个数仓的执行时长,比如7点所有任务跑完,如何优化到5点;

49.数据倾斜,遇到哪些倾斜,怎么发现的?怎么处理的?;

50.如何保证数据质量;

51.如何保证指标一致性;

52.了解onedata吗,说说你的理解;

53.数据漂移如何解决;

54.实时场景如何解决的;

55.拉链表如何设计,拉链表出现数据回滚的需求怎么解决。

57.数仓分层、模型、每层都是做什么的?为什么这么做?

58.交叉维度的解决方案?

59.数据质量如何保证(DQC)?

60.任务延迟如何优化(SLA)?

61.聊一下数据资产。

62.如果让你设计实时数仓你会如何设计,为什么?

64.sql问题:连续活跃n天用户的获取;

65.数据倾斜的sql如何优化;数据量大的sql如何优化?

66.数据仓库主题的划分,参考Teradata的LDM模型;

68.数据质量管理、数据治理有什么好的方案?知识库管理有什么好的思路?血缘关系图。

69.元数据管理相关问题,集群存储不够了,需要清理不需要的任务和数据该怎么做?

70.业务库2亿数据入仓的策略,一次全量,之后每次增量;

73.聊一下技术架构,整个项目每个环节用的什么技术这个样子;

74.hive、hbase、spark。。。。这些大数据组件,熟悉哪个或者哪些?我说hive和hbase,对方就问hive和hbase的原理,差异等问题;

75.有没有实时数仓的经验,数据实时入仓思路,canal;

76.你对当前的项目组有没有什么自己的看法、意见或者需要改进的地方,这个改进对你有没有什么影响

77.ods的增量能否做成通用的?

78.公共层和数据集市层的区别和特点?

79.从原理上说一下mpp和mr的区别

80.对了中间还有问数仓数据的输出主要是哪些还有数仓的分层;

82.数据库和数据仓库有什么区别

1、数据库是面向事务的,数据是由日常的业务产生的,常更新:

     数据仓库是面向主题的,数据来源于数据库或文件,经过一定的规则转换得到,用来分析的。

2、数据库一般是用来存储当前交易数据,

3、数据库的设计一般是符合三范式的,有最大的精确度和最小的冗余度,有利于数据的插入;

1.Flink实时计算时落磁盘吗

2.日活DAU的统计需要注意什么

4.Flink的容错是怎么做的

5.Parquet格式的好处?什么时候读的快什么时候读的慢

开启checkpoint可以容错,程序自动重启的时候可以从checkpoint中恢复数据

3.sink支持事务,可以分2次提交,如kafka;或者sink支持幂等,可以覆盖之前写入的数据,如redis

8.flink的时间形式和窗口形式有几种?有什么区别,你们用在什么场景下的?

10.flink的watermark机制说下,以及怎么解决数据乱序的问题?

2.写出你用过的设计模式,并举例说明解决的实际问题

3.Java创建线程的几种方式

4.请简述操作系统的线程和进程的区别

6.采用java或自己熟悉的任何语言分别实现简单版本的线性表和链表,只需实现add,remove方法即可

8.JVM 内存分哪几个区,每个区的作用是什么?

9.Java中迭代器和集合的区别?

集合是将所有数据加载到内存,然后通过集合的方法去内存中获取,而迭代器是一个对象,实现了Iterator接口,实现了接口的hasNext和Next方法。

在多线程并发的情况下,可以直接使用 HashTabl,但是使用 HashMap 时必须自己增加同步

样的键只有一个;可以有一个或多个键所对应的值为 null。

4) 数组初始化和扩容机制

要求底层数组的容量一定要为 2 的整数次幂,而 HashMap 则要求一定为 2 的整数次幂。

Hashtable 扩容时,将容量变为原来的 2 倍加 1,而 HashMap 扩容时,将容量变为原

11.线程池使用注意哪些方面?

线程池分为单线程线程池,固定大小线程池,可缓冲的线程池

14.使用递归算法求n的阶乘:n! ,语言不限

TreeSet 是采用树结构实现(红黑树算法)。元素是按顺序进行排列,但是 add()、

安全的,而 StringBuilder 没有这个修饰,可以被认为是线程不安全的。

3、在单线程程序下,StringBuilder 效率更快,因为它不需要加锁,不具备多线程安全

而 StringBuffer 则每次都需要判断锁,效率相对更低

final:修饰符(关键字)有三种用法:修饰类、变量和方法。修饰类时,意味着它不

能再派生出新的子类,即不能被继承,因此它和 abstract 是反义词。修饰变量时,该变量

使用中不被改变,必须在声明时给定初值,在引用中只能读取不可修改,即为常量。修饰

方法时,也同样只能使用,不能在子类中被重写。

finally:通常放在 try…catch 的后面构造最终执行代码块,这就意味着程序无论正常执

行还是发生异常,这里的代码只要 JVM 不关闭都能执行,可以将释放外部资源的代码写在

从内存中清除出去之前做必要的清理工作。这个方法是由垃圾收集器在销毁对象时调用

的,通过重写 finalize() 方法可以整理系统资源或者执行其他清理工作。

== : 如果比较的是基本数据类型,那么比较的是变量的值

如果比较的是引用数据类型,那么比较的是地址值(两个对象是否指向同一块内

equals:如果没重写 equals 方法比较的是两个对象的地址值。

如果重写了 equals 方法后我们往往比较的是对象中的属性的内容

equals 方法是从 Object 类中继承的,默认的实现就是使用==

Java类加载需要经历一下几个过程:

加载时类加载的第一个过程,在这个阶段,将完成一下三件事情:

通过一个类的全限定名获取该类的二进制流。

将该二进制流中的静态存储结构转化为方法去运行时数据结构。 

在内存中生成该类的Class对象,作为该类的数据访问入口。

验证的目的是为了确保Class文件的字节流中的信息不回危害到虚拟机.在该阶段主要完成以下四钟验证: 

文件格式验证:验证字节流是否符合Class文件的规范,如主次版本号是否在当前虚拟机范围内,常量池中的常量是否有不被支持的类型.

元数据验证:对字节码描述的信息进行语义分析,如这个类是否有父类,是否集成了不被继承的类等。

字节码验证:是整个验证过程中最复杂的一个阶段,通过验证数据流和控制流的分析,确定程序语义是否正确,主要针对方法体的验证。如:方法中的类型转换是否正确,跳转指令是否正确等。

符号引用验证:这个动作在后面的解析过程中发生,主要是为了确保解析动作能正确执行。

准备阶段是为类的静态变量分配内存并将其初始化为默认值,这些内存都将在方法区中进行分配。准备阶段不分配类中的实例变量的内存,实例变量将会在对象实例化时随着对象一起分配在Java堆中。

该阶段主要完成符号引用到直接引用的转换动作。解析动作并不一定在初始化动作完成之前,也有可能在初始化之后。

初始化时类加载的最后一步,前面的类加载过程,除了在加载阶段用户应用程序可以通过自定义类加载器参与之外,其余动作完全由虚拟机主导和控制。到了初始化阶段,才真正开始执行类中定义的Java程序代码。

22.java中垃圾收集的方法有哪些?

23.如何判断一个对象是否存活?(或者GC对象的判定方法)

判断一个对象是否存活有两种方法: 

可达性算法(引用链法)

1.为什么要用es?存进es的数据是什么格式的,怎么查询

a.Flume是一个分布式、可靠、和高可用的海量日志采集、聚合和传输的系统。

b.Flume可以采集文件,socket数据包等各种形式源数据,又可以将采集到的数据输出到HDFS、hbase、hive、kafka等众多外部存储系统中

c.一般的采集需求,通过对flume的简单配置即可实现

d.ume针对特殊场景也具备良好的自定义扩展能力,因此,flume可以适用于大部分的日常数据采集场景

Flume分布式系统中最核心的角色是agent,flume采集系统就是由一个个agent所连接起来形成

每一个agent相当于一个数据传递员,内部有三个组件:

Source:采集源,用于跟数据源对接,以获取数据

Sink:下沉地,采集数据的传送目的,用于往下一级agent传递数据或者往最终存储系统传递数据

1.Sqoop底层运行的任务是什么

只有Map阶段,没有Reduce阶段的任务。

2.sqoop的迁移数据的原理

5.Sqoop数据导出一致性问题

1)场景1:如Sqoop在导出到Mysql时,使用4个Map任务,过程中有2个任务失败,那此时MySQL中存储了另外两个Map任务导入的数据,此时老板正好看到了这个报表数据。而开发工程师发现任务失败后,会调试问题并最终将全部数据正确的导入MySQL,那后面老板再次看报表数据,发现本次看到的数据与之前的不一致,这在生产环境是不允许的。

2)场景2:设置map数量为1个(不推荐,面试官想要的答案不只这个)

多个Map任务时,采用–staging-table方式,仍然可以解决数据一致性问题。

6.通过sqoop把数据加载到mysql中,如何设置主键?

1.缓存穿透、缓存雪崩、缓存击穿

1)缓存穿透是指查询一个一定不存在的数据。由于缓存命不中时会去查询数据库,查不到

数据则不写入缓存,这将导致这个不存在的数据每次请求都要到数据库去查询,造成缓存穿

① 是将空对象也缓存起来,并给它设置一个很短的过期时间,最长不超过 5 分钟

② 采用布隆过滤器,将所有可能存在的数据哈希到一个足够大的 bitmap 中,一个一定

不存在的数据会被这个 bitmap 拦截掉,从而避免了对底层存储系统的查询压力

2)如果缓存集中在一段时间内失效,发生大量的缓存穿透,所有的查询都落在数据库上,

尽量让失效的时间点不分布在同一个时间点

3)缓存击穿,是指一个 key 非常热点,在不停的扛着大并发,当这个 key 在失效的瞬间,

持续的大并发就穿破缓存,直接请求数据库,就像在一个屏障上凿开了一个洞。

可以设置 key 永不过期

① 在指定的时间间隔内持久化

2)AOF : 以日志形式记录每个更新操作

Redis 重新启动时读取这个文件,重新执行新建、修改数据的命令恢复数据。

推荐(并且也是默认)的措施为每秒持久化一次,这种策略可以兼顾速度和安全性。

1 比起 RDB 占用更多的磁盘空间

3 每次读写都同步的话,有一定的性能压力

4 存在个别 Bug,造成恢复不能

如果对数据不敏感,可以选单独用 RDB;不建议单独用 AOF,因为可能出现 Bug;如果只是做纯内存缓存,可以都不用

悲观锁:执行操作前假设当前的操作肯定(或有很大几率)会被打断(悲观)。基于这个假设,我们在做操作前就会把相关资源锁定,不允许自己执行期间有其他操作干扰。

乐观锁:执行操作前假设当前操作不会被打断(乐观)。基于这个假设,我们在做操作前不会锁定资源,万一发生了其他操作的干扰,那么本次操作将被放弃。Redis 使用的就是乐观锁。

5.redis 是单线程的,为什么那么快

1)完全基于内存,绝大部分请求是纯粹的内存操作,非常快速。

2)数据结构简单,对数据操作也简单,Redis 中的数据结构是专门进行设计的

3)采用单线程,避免了不必要的上下文切换和竞争条件,也不存在多进程或者多线程导致的切换而消耗 CPU,不用去考虑各种锁的问题,不存在加锁释放锁操作,没有因为可能出现死锁而导致的性能消耗

4)使用多路 I/O 复用模型,非阻塞 IO

5)使用底层模型不同,它们之间底层实现方式以及与客户端之间通信的应用协议不一样,

Redis 直接自己构建了 VM 机制 ,因为一般的系统调用系统函数的话,会浪费一定的时间去移动和请求

6.redis的热键问题?怎么解决?

2.为什么MySQL的索引要使用B+树而不是其它树形结构?比如B树?

       B树不管叶子节点还是非叶子节点,都会保存数据,这样导致在非叶子节点中能保存的指针数量变少(有些资料也称为扇出)

指针少的情况下要保存大量数据,只能增加树的高度,导致IO操作变多,查询性能变低;

1.单一节点存储更多的元素,使得查询的IO次数更少。

2.所有查询都要查找到叶子节点,查询性能稳定。

3.所有叶子节点形成有序链表,便于范围查询,远远高于B-树

B树(B-树)是一种适合外查找的搜索树,是一种平衡的多叉树 

B树的每个结点包含着结点的值和结点所处的位置

7.动态规划 最大连续子序列和

8.二叉树概念,特点及代码实现

二叉树是n(n>=0)个结点的有限集合,该集合或者为空集(称为空二叉树),或者由一个根结点和两棵互不相交的、分别称为根结点的左子树和右子树组成。

每个结点最多有两颗子树,所以二叉树中不存在度大于2的结点。

左子树和右子树是有顺序的,次序不能任意颠倒。

即使树中某结点只有一棵子树,也要区分它是左子树还是右子树。

4.怎么修改文本文件第一行字符

8.直接查看比较高的磁盘读写程序

10.查看报告系统运行时长及平均负载

个人公众号 yk 坤帝
后台回复 项目十 获取整理资源



我要回帖

更多关于 四种调度算法的优缺点 的文章

 

随机推荐