数据库文档生成工具——screw

在企业级开发中、我们经常会有编写数据库表结构文档的时间付出,如果数据库表结构更新了还得手动更新维护到文档中,很是繁琐。 无意之间发现了github上面有个人写了一个小工具专门来做这个事情,名字叫screw(螺丝刀),用了下很不错。这里特意记录一下。

工具的github地址:https://github.com/pingfangushi/screw

特点

  • 简洁、轻量、设计良好
  • 多数据库支持,目前已支持MySQL、MariaDB、TIDB、Oracle、SqlServer、PostgreSQL、Cache DB
  • 多种格式文档,目前已至此HTML、Word、MarkDown格式
  • 灵活扩展
  • 支持自定义模板

使用

有两种使用方式,一种是通过maven插件引入后执行命令生成,一种是直接写代码来生成文档。 下面我通过MySQL数据库的使用例子来说明。

引入依赖

代码方式

maven插件方式

配置完以后在 maven project -> screw -> screw:run 双击执行ok。

效果图

数据库文档生成工具——screw

0

分布式时序数据库的存储架构设计及实现方案

前言

伴随着工业4.0的持续推进,工业设备的智能化以及企业的信息化改造将快速推进,由此也带来了数据的爆发式増长,对传统的时序数据库在点数规模、数据分布、可靠性、扩展性等多个方面提出了巨大的挑战。对比研究目前国际领先的时序数据库产品PI、PHD,发现这些产品在面对工业时序大数据时都具有如下的局限性:

(1)数据存储服务未能实现分布式架构,当单机服务异常时将导致服务不可用,无法提供检索和存储功能;

(2)数据存储无多副本机制,数据的安全性需要用户自己备份,无法保证在磁盘损坏时所有的数据拥有可靠的备份;

(3)缺乏灵活的动态扩展能力,当存储性能或者存储容量达到瓶颈时难以做到动态的水平扩展;

(4)数据检索能力有限,仅仅支持按照时间戳的检索条件,对于按值范围或者模糊检索不支持;

(5)计算能力有限,仅仅能够根据其提供的有限的计算方法进行计算,无法有效地利用大数据分布式计算技术实现对海量数据的计算分析。

当前互联网大数据技术正在蓬勃发展,在存储领域,以Hadoop生态系统为基础构件的大数据存储平台在企业中不断地得到大规模应用;在实时计算领域,Storm、Flink、Spark-Streaming等分布式实时流处理引擎俨然成为实时计算的利剑,弥补了传统的定周期计算在实时性方面的不足;在大数据计算领域,MapReduce、Spark为离线批处理计算和内存计算提供了有效的计算分析手段,有效地解决了海量数据的计算问题,为数据价值的重塑奠定了坚实的基础。大数据平台正在不断成长为企业的基础设施,发挥着越来越大甚至无法替代的作用。

基于现有的大数据开放架构,充分利用企业大数据基础设施,设计并实现可融入用户现有大数据平台生态圈的时序数据库成为技术发展的主流趋势,可有效减少多个平台的系统运维工作,节约用户成本。本文依托Storm、Hbase和Redis等分布式计算和处理技术,设计并实现了时序数据的开放式存储架构,不仅可有效应对高频时序数据的存储,而且可有效对接Spark等主流计算引擎,实现对时序数据的计算分析,挖掘潜在的数据价值。

1整体架构设计

本文所描述的分布式时序数据库由分布式数据网关、分布式消息队列、分布式实时流计算服务、分布式缓存和分布式存储服务5个部分组成,其系统架构下图所示。

分布式时序数据库架构
分布式时序数据库架构

各功能模块组件功能介绍如下。

(1)分布式数据网关:分布式数据网关由负载均衡服务(LB)和多个数据网关构成(GW),通过分布式数据网关实现数据的接收与查询代理,该网关完全采用无状态设计模式,从而任何一台网关的异常都不会导致整个系统的异常;

(2)分布式消息队列:分布式消息队列采用开源的Kafka消息队列,由多个Broker节点组成,通过分布式消息队列实现数据的发布与订阅功能,该消息队列必须满足高吞吐量、高可靠性和持久化能力,从而实现数据的可靠传输;

(3)分布式实时流计算服务:基于分布式实时流处理框架Storm,实现了消息订阅(Notify Bolt)、内存快照存储(Memstore Bolt)和持久化存储(Persistent Bolt)3个服务,通过实时流计算服务,对于上传的数据进行计算、变化订阅通知、内存快照存储与持久化存储,该框架必须满足动态可扩展,高可用和实时性,任何一台节点的宕机不会影响数据的处理,确保数据可以被流式框架中的所有数据处理任务执行,同时可以动态地在流计算服务中新增任务,满足对实时流处理的动态需求;

(4)分布式缓存:基于NoSQL数据库Redis进行设计,通过分布式缓存存储数据快照,也就是数据的最新值,确保数据的实时检索性能;

(5)分布式存储服务:分布式存储服务是通过NoSQL数据库Hbase进行存储,通过分布式搜索引擎Solr实现数据的检索,分布式存储服务是用来做工业数据的持久化存储,其必须满足大容量、高可靠、高性能、数据副本安全、动态扩展和对基于
其上的分布式计算框架的支持,是整个分布式时序数据库的核心。

2数据存储架构设计

时序数据通常是由点名、值、时间戳、数据质量4个部分组成,其在分布式缓存服务和分布式存储服务中存储结构分别如下图所示。

分布式数据缓存服务数据存储格式
分布式数据缓存服务数据存储格式
分布式存储服务数据存储格式
分布式存储服务数据存储格式

缓存数据存储架构:分布式缓存服务采用Redis的hmset数据结构,存储Tag点对应的数据项。通过该设计,用户可以快速地查询一个点的实时值,无需迭代;

分布式存储架构:采用Hbase的无模式稀疏设计,将不同的Tag点数据放在同一行,通过时间作为主键,可快速地基于时间范围迭代查询历史记录,并且满足基于时间的数据分析的需求。

3数据处理流程设计

3.1时序数据存储流程

分布式时序数据库数据存储流程设计如下。

(1)系统初始化,分布式数据网关在分布式消息队列中创建数据存储Topic和数据变化订阅Topic,通过数据存储Topic实现数据的上传,通过数据变化订阅Topic接收数据变化,从而实现数据变化通知客户端的功能;
(2)第3方数据采集客户端调用分布式时序数据库客户端SDK传输数据;
(3)分布式数据网关的LB服务器接收到数据,将数据发送到负荷较小的数据网关节点,数据网关节点将数据发送到分布式消息队列中的数据存储Topic;
(4)分布式流式计算服务Spout从数据存储Topic中接收到订阅消息,传送给Notify Bolt;
(5)Notify Bolt判断数据是否变化以及该数据是否被客户端订阅,如果满足变化和被订阅的条件,将该数据通过数据变化订阅Topic发布出去,并同时将数据路由到Memstore Bolt;
(6)分布式流式计算服务Memstore Bolt将数据发送到分布式缓存服务进行快照的存储,并同时将数据路由到Persistent Bolt;
(7)分布式流式计算服务Persistent Bolt将数据发送到分布式存储服务进行数据的持久化存储;
(8)分布式存储服务接收数据,一方面通过Hbase的SEP处理器将数据传输到分布式搜索引擎Solr进行数据的异步索引,另一方面通过其Hbase自身机制将数据序列化存储到Hadoop的HDFS系统中。

通过该流程,可有效保证系统的可扩展处理能力,当数据量增加时,只需要增加节点即可实现弹性扩展。

3.2时序数据检索流程

分布式时序数据库数据检索流程如下。

(1)第3方服务通过SDK提交数据查询命令到分布式数据网关;
(2)分布式数据网关根据查询类型进行分类查询,具体如下:对于内存快照查询,其直接查询分布式缓存服务;对于时间查询,直接通过Hbase的行键查询;对于按值查询,直接提交给Solr查询。
(3)分布式网关返回查询结果。

4整体架构特性分析

(1)可靠性与扩展性。整个系统采用纯分布式架构无单点故障,分布式数据网关采用Haproxy加多个数据节点的分布式部署方式,分布式消息队列基于分布式消息队列Kafka,分布式流式计算框架采用Storm,分布式存储采用Hbase,对应的数据索引采用Solr分布式搜索引擎,采用这种分布式架构系统可方便地进行节点动态扩展。
(2)数据安全性。数据传输的安全性由Kafka消息序列化机制和副本机制保证,数据处理的安全性由Storm分布式框架的容错机制和数据被处理且仅被处理一次的机制保证,数据存储的安全性则由Hbase的数据存储副本机制保证,整个系统从数据的传输、处理到最后存储均安全可靠。
(3)性能。分布式数据网关采用Netty的纯异步RPC通信框架,采用分布式的部署方式,可实现性能的任意扩展,所采用的消息队列服务、流式计算服务、分布式内存服务和分布式存储服务均具有高性能和弹性扩展的能力,整个系统的性能可通过增加节点数得到快速的提升。
(4)支持分布式计算。对于实时计算我们采用了Storm流式计算框架,仅仅需要在Storm中增加对应的数据计算Bolt即可,对于并行分布式计算,由于我们采用了Hbase+HDFS的存储方式,可方便地采用Spark分布式计算框架对历史数据进行计算分析。
(5)支持多维度查询。采用HBase的行键索引和Solr索引相集合,可实现对于数值的多种复杂条件组合查询,例如正则表达式查询。

5总结

本设计方案给出了一种纯分布式时序数据库的架构设计和实现方法,可有效地解决传统的时序数据库在应对工业大数据在可靠性、扩展性、检索和其上的计算支撑能力的不足,能够有效提升企业的智能化和信息化水平,并利用大数据技术挖掘潜在的数据价值,为企业的转型发展提供坚实的数据基础。
目前该设计方案在普通的4台x86服务器(内存配置为128 GB,CPU 为 Intel Xeon E5-2660 v3,硬盘:SATA 7200RPM x 10)进行测试,实现了每秒400万条时序数据的存储能力,并且整个系统运行稳定,可有效节约用户成本,系统采用CDH作为基础Hadoop管理平台,可独立部署也可使用用户现有的Hadoop平台,有效减少多套平台运维工作。

0

为什么select count(*)在myisam比innodb里效率高,innodb里如何优化?

因为MySQL的MyISAM引擎在内部维护了一个计数器,当select count(*)其实就是拿到这个计数器的最新数值返回即可,而innodb却是要实时统计的。

那么,为什么innodb存储引擎不也维护一个计数器呢?

那是因为对于InnoDB这样的事务性存储引擎,存储准确的行数是不太现实的,因为多个事务可能同时发生,每个事务都有可能影响计数。 InnoDB不保留表中的行数,因为并发事务可能同时“看到”不同的行数。因此,SELECT COUNT(*)语句只计算当前事务可见的行。

为了处理SELECT COUNT(*)语句,InnoDB扫描表的索引,如果索引不是完全在缓冲池中,那么这将花费一些时间。

经过实践发现,不同的服务器配置下,当innodb表的行数达到数百万、数十万甚至数万的情况下,select count(*) 就会非常慢(需要十几秒甚至几分钟!),那么如何优化呢?

建议采用二级索引速度会比用主键索引更快。

在InnoDB引擎中,当我们通过二级索引统计数据的时候,无需扫描数据文件(二级索引存储指定字段的索引,实际的指向位置是主键索引。);而通过主键索引统计数据时,由于主键索引与数据文件存放在一起,所以每次都会扫描数据文件,所以主键索引统计没有二级索引效率高。

innodb表中除了主键ID之外,再找一个字段进行索引,然后在查询的时候使用select count(第二索引的字段),查询效率会大大提高。

0

MySQL里查看某张表的建表语句

0

Elasticsearch教程(四):安装和使用Elasticsearch-Head插件

虽然我们可以使用curl等客户端工具访问Restful API对Elasticsearch进行操作,但也有一些客户端工具提供对于ElasticSearch更加友好的可视化操作支持,比如elasticsearch-head。所以这篇文章介绍如何安装和使用Elasticsearch-Head。

Elasticsearch-Head概要信息

项目说明
开源/闭源开源
源码管理地址https://github.com/mobz/elasticsearch-head
License类别Apache License 2.0
开发语言Javascript
当前稳定版本5.0.0(2018/4/10)
下载地址:github releasehttps://github.com/mobz/elasticsearch-head/releases

使用方式

早期版本的elasticsearch-head可以直接以插件的方式在Elasticsearch中进行安装,在Elasticsearch 5之后则需要将elasticsearch-head服务单独运行(依赖于Node.js),并且支持Chrome的插件方式或者Docker容器运行方式。

Chrome插件方式

安装地址:https://chrome.google.com/webstore/detail/elasticsearch-head/ffmkiejjmecolpfloofpjologoblkegm/

点击上述Add to Chrome按钮完成安装,然后点击ElasticSearch Head按钮即可在Chrome中使用了

可以看到此时状态显示为:cluster health: not connected(未连接的状态),这是因为我们还没配置ElasticSearch的服务连接,只要把我们之前安装好的ElasticSearch服务地址http://192.168.0.123:9200/填到connect按钮前面的框内,然后点击connect。

因为我是单点的,所以健康度是yellow,黄色不影响使用,红色就要解决。

Node服务方式

准备node环境

Elasticsearch-head插件要求Node.js环境,并且Node.js的版本大于等于6.0。所以需要先看下自己系统里是否已安装node.js,可以使用命令 npm -v 查看,我这边显示是 6.13.4。如果没有安装,需要先行安装。

下载 head插件

接下来,咱们先在GitHub上找到head插件,地址:https://github.com/mobz/elasticsearch-head。咱们将其下载/克隆到服务器上。

需要说明的是,因为前面已经说过elasticsearch 5之后其实elasticsearch-head并不是以插件的方式安装,所以我们不需要把head下载到elasticsearch的/plugins/目录下,自己找个合适的位置存放即可。

下载完成后,进入 elasticsearch-head的目录下,按顺序执行命令:

安装head

这步可能有点慢

启动head

看到Started connect web server on http://localhost:9100,说明head 服务就成功安装,并且正常启动了。

启动后,我们可以通过 http:// localhost :9100 进行访问。

但是,实际安装的过程中可能会遇到问题。

问题

npm ERR! phantomjs-prebuilt@2.1.16 install: node install.js

解决

npm install phantomjs-prebuilt@2.1.16 –ignore-scripts

Elasticsearch简单使用

可以看到我们上一篇文章创建的索引phone也出现了

点击数据浏览,再点击需要查看的索引,就可以查看该索引下的所有记录。

也可以使用它的基本查询和复合查询查询记录

下篇文章介绍复合查询。

0

Elasticsearch教程(三):增删改查初体验

Elasticsearch 是 Lucene 的封装,提供了 REST API 的操作接口,开箱即用。

所以可以使用postman来测试。

增加一个索引

PUT方式请求 http://192.168.0.123:9200/phone,phone是我要建的索引

服务器返回一个 JSON 对象,里面的acknowledged字段表示操作成功。

这就建好了,看起来很简单。

插入一个记录

在索引phone下存放一个文档,它的类型是apple,文档里有一些属性。

POST方式请求 http:// 192.168.0.123 :9200/phone/apple

请求体里加上我们的数据

返回的 JSON 对象,会给出 Index、Type、Id、Version 等信息。

当然,我们也可以以指定id的方式插入数据, 就像这样http:// 192.168.0.123 :9200/phone/apple/1,这样该条记录的id就是1,但是正常的使用场景中,不指定id会比较好。

注意,如果我们没有创建 Index phone,就直接执行上面的命令插入数据也不会报错,ElasticSearch会直接生成指定的 Index。所以我们在插入数据时要注意 Index 的名称不要写错。

查看记录

根据id查看我们刚刚插入的那条记录,其中 pretty 表示以友好阅读的方式展示结果

GET方式请求 http:// 192.168.0.123 :9200/phone/apple/Q5ci-HABIIllKMiCQFU5?pretty=true

返回结果

更新记录

PUT方式请求 http:// 192.168.0.123 :9200/phone/apple/Q5ci-HABIIllKMiCQFU5

请求体是要更新的内容

返回结果

删除记录

DELETE方式请求 http:// 192.168.0.123 :9200/phone/apple/Q5ci-HABIIllKMiCQFU5

0

Elasticsearch教程(一):Elasticsearch介绍与在Linux CentOS7上使用yum安装

一、简介

Elasticsearch是一个用Java语言编写的开源的搜索引擎,它是建立在全文搜索引擎库 Apache Lucene™ 的基础之上。

Elasticsearch内部使用Lucene做索引与搜索,相比复杂的Lucene,Elasticsearch的全文检索变得非常简单, 因为它提供了一套简单一致的RESTful API。

Elasticsearch作为一个全文搜索引擎。它支持分布式的实时文档存储,每个字段可以被索引与搜索,同时能胜任上百个服务节点的扩展,并支持 PB 级别的结构化或者非结构化数据。

Elasticsearch把所有的功能都打包成一个单独的服务,方便使用者通过程序与其提供的RESTful API进行通信,使用者可以用任何编程语言实现这个web客户端,甚至直接使用命令行调用API。

Elasticsearch的起步很简单。它预设了一些适当的默认值,并隐藏了复杂的搜索理论知识。真正做到了开箱即用。

当然,这不意味着Elasticsearch的功能就很简单,相反随着对它的了解越深入,就越能惊叹于Elasticsearch的更多高级特性。

很多我们遇到的没遇到的业务场景或难题,都可以从Elasticsearch众多的高级特性中,找到合适的解决方案。它的整个引擎是可配置并且灵活的。

Elasticsearch在Github上的地址:http://github.com/elastic/elasticsearch 。

二、安装

系统:Linux CentOS7

2.1 确认是否安装Java,Elasticsearch最低支持java1.7

以下命令可以查看jdk版本

2.2 使用yum安装Elasticsearch

2.2.1 下载并安装ES的yum公钥

2.2.2 配置Elasticsearch的yum源

输入下面的代码

2.2.3 更新yum的缓存

2.2.4 安装Elasticsearch

2.2 测试Elasticsearch是否安装成功

配置服务

测试访问

看到如上响应说明已经启动并运行一个Elasticsearch节点了。 单个节点可以作为一个运行中的Elasticsearch的实例。 而一个集群是一组拥有相同 cluster.name 的节点, 他们能一起工作并共享数据,还提供容错与可伸缩性。

2.3 设置ip访问、外网访问、修改端口

修改完了重启

systemctl restart elasticsearch

浏览器中输入ip地址和端口访问试试,如果访问被拒绝,添加防火墙设置

0

Kafka面试题整理总结大全

1 .什么是kafka?

Kafka是分布式发布-订阅消息系统,它最初是由LinkedIn公司开发的,之后成为Apache项目的一部分,Kafka是一个分布式,可划分的,冗余备份的持久性的日志服务,它主要用于处理流式数据。

2 .为什么要使用 kafka,为什么要使用消息队列?

缓冲和削峰:上游数据时有突发流量,下游可能扛不住,或者下游没有足够多的机器来保证冗余,kafka在中间可以起到一个缓冲的作用,把消息暂存在kafka中,下游服务就可以按照自己的节奏进行慢慢处理。

解耦和扩展性:项目开始的时候,并不能确定具体需求。消息队列可以作为一个接口层,解耦重要的业务流程。只需要遵守约定,针对数据编程即可获取扩展能力。

冗余:可以采用一对多的方式,一个生产者发布消息,可以被多个订阅topic的服务消费到,供多个毫无关联的业务使用。

健壮性:消息队列可以堆积请求,所以消费端业务即使短时间死掉,也不会影响主要业务的正常进行。

异步通信:很多时候,用户不想也不需要立即处理消息。消息队列提供了异步处理机制,允许用户把一个消息放入队列,但并不立即处理它。想向队列中放入多少消息就放多少,然后在需要的时候再去处理它们。

3.Kafka中的ISR、AR又代表什么?ISR的伸缩又指什么?

  • ISR:In-Sync Replicas 副本同步队列
  • AR:Assigned Replicas 所有副本

ISR是由leader维护,follower从leader同步数据有一些延迟(包括延迟时间replica.lag.time.max.ms和延迟条数replica.lag.max.messages两个维度,当前最新的版本0.10.x中只支持replica.lag.time.max.ms这个维度),任意一个超过阈值都会把follower剔除出ISR, 存入OSR(Outof-Sync Replicas)列表,新加入的follower也会先存放在OSR中。AR=ISR+OSR。

4.kafka中的broker 是干什么的?

broker 是消息的代理,Producers往Brokers里面的指定Topic中写消息,Consumers从Brokers里面拉取指定Topic的消息,然后进行业务处理,broker在中间起到一个代理保存消息的中转站。

5.kafka中的 zookeeper 起到什么作用,可以不用zookeeper么?

zookeeper 是一个分布式的协调组件,早期版本的kafka用zk做meta信息存储,consumer的消费状态,group的管理以及 offset的值。考虑到zk本身的一些因素以及整个架构较大概率存在单点问题,新版本中逐渐弱化了zookeeper的作用。新的consumer使用了kafka内部的group coordination协议,也减少了对zookeeper的依赖,

但是broker依然依赖于ZK,zookeeper 在kafka中还用来选举controller 和检测broker是否存活等等。

6.kafka follower如何与leader同步数据?

Kafka的复制机制既不是完全的同步复制,也不是单纯的异步复制。完全同步复制要求All Alive Follower都复制完,这条消息才会被认为commit,这种复制方式极大的影响了吞吐率。而异步复制方式下,Follower异步的从Leader复制数据,数据只要被Leader写入log就被认为已经commit,这种情况下,如果leader挂掉,会丢失数据,kafka使用ISR的方式很好的均衡了确保数据不丢失以及吞吐率。Follower可以批量的从Leader复制数据,而且Leader充分利用磁盘顺序读以及send file(zero copy)机制,这样极大的提高复制性能,内部批量写磁盘,大幅减少了Follower与Leader的消息量差。

7.什么情况下一个 broker 会从 isr中踢出去?

leader会维护一个与其基本保持同步的Replica列表,该列表称为ISR(in-sync Replica),每个Partition都会有一个ISR,而且是由leader动态维护 ,如果一个follower比一个leader落后太多,或者超过一定时间未发起数据复制请求,则leader将其重ISR中移除 。

8.kafka 为什么那么快?

  • Cache:Filesystem Cache PageCache缓存
  • 顺序写:由于现代的操作系统提供了预读和写技术,磁盘的顺序写大多数情况下比随机写内存还要快。
  • Zero-copy:零拷技术减少拷贝次数
  • Batching of Messages:批量消息处理,合并小的请求,然后以流的方式进行交互,直顶网络上限。
  • Pull 拉模式: 使用拉模式进行消息的获取消费,与消费端处理能力相符。

9.kafka producer如何优化push速度

  • 增加线程
  • 提高 batch.size
  • 增加更多 producer 实例
  • 增加 partition 数
  • 设置 acks=-1 时,如果延迟增大:可以增大 num.replica.fetchers(follower 同步数据的线程数)来调解
  • 跨数据中心的传输,增加 socket 缓冲区设置以及 OS tcp 缓冲区设置

10.kafka producer push数据,ack  为 0, 1, -1 的时候代表啥, 设置 -1 的时候,什么情况下,leader 会认为一条消息 commit了?

  • 1(默认)  数据发送到Kafka后,经过leader成功接收消息的的确认,就算是发送成功了。在这种情况下,如果leader宕机了,则会丢失数据。
  • 0 生产者将数据发送出去就不管了,不去等待任何返回。这种情况下数据传输效率最高,但是数据可靠性确是最低的。
  • -1 producer需要等待ISR中的所有follower都确认接收到数据后才算一次发送完成,可靠性最高。当ISR中所有Replica都向Leader发送ACK时,leader才commit,这时候producer才能认为一个请求中的消息都commit了。

11.kafka unclean 配置代表啥,会对 spark streaming 消费有什么影响?

unclean.leader.election.enable 为true的话,意味着非ISR集合的broker 也可以参与选举,这样有可能就会丢数据,spark streaming在消费过程中拿到的 end offset 会突然变小,导致 spark streaming job挂掉。如果unclean.leader.election.enable参数设置为true,就有可能发生数据丢失和数据不一致的情况,Kafka的可靠性就会降低;而如果unclean.leader.election.enable参数设置为false,Kafka的可用性就会降低。

12.如果leader crash时,ISR为空怎么办?

kafka在Broker端提供了一个配置参数:unclean.leader.election,这个参数有两个值:

true(默认):允许不同步副本成为leader,由于不同步副本的消息较为滞后,此时成为leader,可能会出现消息不一致的情况。

false:不允许不同步副本成为leader,此时如果发生ISR列表为空,会一直等待旧leader恢复,降低了可用性。

13.kafka的message格式是什么样的?

一个Kafka的Message由一个固定长度的header和一个变长的消息体body组成。

header部分由一个字节的magic(文件格式)和四个字节的CRC32(用于判断body消息体是否正常)构成。

当magic的值为1的时候,会在magic和crc32之间多一个字节的数据:attributes(保存一些相关属性,比如是否压缩、压缩格式等等);如果magic的值为0,那么不存在attributes属性。

body是由N个字节构成的一个消息体,包含了具体的key/value消息。

14.kafka中consumer group 是什么概念?

同样是逻辑上的概念,是Kafka实现单播和广播两种消息模型的手段。同一个topic的数据,会广播给不同的group;同一个group中的worker,只有一个worker能拿到这个数据。换句话说,对于同一个topic,每个group都可以拿到同样的所有数据,但是数据进入group后只能被其中的一个worker消费。group内的worker可以使用多线程或多进程来实现,也可以将进程分散在多台机器上,worker的数量通常不超过partition的数量,且二者最好保持整数倍关系,因为Kafka在设计时假定了一个partition只能被一个worker消费(同一group内)。

15.Kafka中的消息是否会丢失和重复消费?

要确定Kafka的消息是否丢失或重复,从两个方面分析入手:消息发送和消息消费。

1、消息发送

Kafka消息发送有两种方式:同步(sync)和异步(async),默认是同步方式,可通过producer.type属性进行配置。Kafka通过配置request.required.acks属性来确认消息的生产:

  • 0—表示不进行消息接收是否成功的确认;
  • 1—表示当Leader接收成功时确认;
  • -1—表示Leader和Follower都接收成功时确认;

综上所述,有3种消息生产的情况,下面分情况来分析消息丢失的场景:

(1)acks=0,不和Kafka集群进行消息接收确认,则当网络异常、缓冲区满了等情况时,消息可能丢失;

(2)acks=1、同步模式下,只有Leader确认接收成功后但挂掉了,副本没有同步,数据可能丢失;

2、消息消费

Kafka消息消费有两个consumer接口,Low-level API和High-level API:

Low-level API:消费者自己维护offset等值,可以实现对Kafka的完全控制;

High-level API:封装了对parition和offset的管理,使用简单;

如果使用高级接口High-level API,可能存在一个问题就是当消息消费者从集群中把消息取出来、并提交了新的消息offset值后,还没来得及消费就挂掉了,那么下次再消费时之前没消费成功的消息就“诡异”的消失了;

解决办法:

针对消息丢失:同步模式下,确认机制设置为-1,即让消息写入Leader和Follower之后再确认消息发送成功;异步模式下,为防止缓冲区满,可以在配置文件设置不限制阻塞超时时间,当缓冲区满时让生产者一直处于阻塞状态;

针对消息重复:===看下面一个面试题===

16.如何保证消息不被重复消费?(如何保证消息消费时的幂等性)

首先,比如 RabbitMQ、RocketMQ、Kafka,都有可能会出现消息重复消费的问题,正常。因为这问题通常不是 MQ 自己保证的,是由我们开发来保证的。拿 Kafka 来举个例子,说说怎么重复消费吧。

Kafka 实际上有个 offset 的概念,就是每个消息写进去,都有一个 offset,代表消息的序号,然后 consumer 消费了数据之后,每隔一段时间(定时定期),会把自己消费过的消息的 offset 提交一下,表示“我已经消费过了,下次我要是重启啥的,你就让我继续从上次消费到的 offset 来继续消费吧”。

那出现重复消费的根本原因就是已经消费了数据,但是offset没提交(kafka没有或者不知道该数据已经被消费)。

基于这种原因总结以下几个易造成重复消费的配置:

原因1:强行kill线程,导致消费后的数据,offset没有提交(消费系统宕机、重启等)。

举个例子。

有这么个场景。数据 1/2/3 依次进入 kafka,kafka 会给这三条数据每条分配一个 offset,代表这条数据的序号,分配的 offset 依次是 152/153/154。消费者从 kafka 去消费的时候,也是按照这个顺序去消费。假如当消费者消费了 offset=153 的这条数据,刚准备去提交 offset 到 zookeeper,此时消费者进程被重启了。那么此时消费过的数据 1/2 的 offset 并没有提交,kafka 也就不知道你已经消费了 offset=153 这条数据。那么重启之后,消费者会找 kafka 说,嘿,哥儿们,你给我接着把上次我消费到的那个地方后面的数据继续给我传递过来。数据 1/2 再次被消费。

原因2:设置offset为自动提交,关闭kafka时,如果在close之前,调用 consumer.unsubscribe() 则有可能部分offset没提交,下次重启会重复消费。例如:

上面代码会导致部分offset没提交,下次启动时会重复消费。 

原因3:(重复消费最常见的原因):消费后的数据,当offset还没有提交时,partition就断开连接。比如,通常会遇到消费的数据,处理很耗时,导致超过了Kafka的session timeout时间(0.10.x版本默认是30秒),那么就会re-blance重平衡,此时有一定几率offset没提交,会导致重平衡后重复消费。 

原因4:当消费者重新分配partition的时候,可能出现从头开始消费的情况,导致重发问题。 

原因5:当消费者消费的速度很慢的时候,可能在一个session周期内还未完成,导致心跳机制检测报告出问题。

17.为什么Kafka不支持读写分离?

在 Kafka 中,生产者写入消息、消费者读取消息的操作都是与 leader 副本进行交互的,从 而实现的是一种主写主读的生产消费模型。

Kafka 并不支持主写从读,因为主写从读有 2 个很明 显的缺点:

(1)数据一致性问题。数据从主节点转到从节点必然会有一个延时的时间窗口,这个时间 窗口会导致主从节点之间的数据不一致。某一时刻,在主节点和从节点中 A 数据的值都为 X, 之后将主节点中 A 的值修改为 Y,那么在这个变更通知到从节点之前,应用读取从节点中的 A 数据的值并不为最新的 Y,由此便产生了数据不一致的问题。

(2)延时问题。类似 Redis 这种组件,数据从写入主节点到同步至从节点中的过程需要经 历网络→主节点内存→网络→从节点内存这几个阶段,整个过程会耗费一定的时间。而在 Kafka 中,主从同步会比 Redis 更加耗时,它需要经历网络→主节点内存→主节点磁盘→网络→从节 点内存→从节点磁盘这几个阶段。对延时敏感的应用而言,主写从读的功能并不太适用。

18.Kafka中是怎么体现消息顺序性的?

kafka每个partition中的消息在写入时都是有序的,消费时,每个partition只能被每一个group中的一个消费者消费,保证了消费时也是有序的。

整个topic不保证有序。如果为了保证topic整个有序,那么将partition调整为1。

19.消费者提交消费位移时提交的是当前消费到的最新消息的offset还是offset+1?

offset+1

20.kafka如何实现延迟队列?

Kafka并没有使用JDK自带的Timer或者DelayQueue来实现延迟的功能,而是基于时间轮自定义了一个用于实现延迟功能的定时器(SystemTimer)。JDK的Timer和DelayQueue插入和删除操作的平均时间复杂度为O(nlog(n)),并不能满足Kafka的高性能要求,而基于时间轮可以将插入和删除操作的时间复杂度都降为O(1)。时间轮的应用并非Kafka独有,其应用场景还有很多,在Netty、Akka、Quartz、Zookeeper等组件中都存在时间轮的踪影。

底层使用数组实现,数组中的每个元素可以存放一个TimerTaskList对象。TimerTaskList是一个环形双向链表,在其中的链表项TimerTaskEntry中封装了真正的定时任务TimerTask。

Kafka中到底是怎么推进时间的呢?Kafka中的定时器借助了JDK中的DelayQueue来协助推进时间轮。具体做法是对于每个使用到的TimerTaskList都会加入到DelayQueue中。Kafka中的TimingWheel专门用来执行插入和删除TimerTaskEntry的操作,而DelayQueue专门负责时间推进的任务。再试想一下,DelayQueue中的第一个超时任务列表的expiration为200ms,第二个超时任务为840ms,这里获取DelayQueue的队头只需要O(1)的时间复杂度。如果采用每秒定时推进,那么获取到第一个超时的任务列表时执行的200次推进中有199次属于“空推进”,而获取到第二个超时任务时有需要执行639次“空推进”,这样会无故空耗机器的性能资源,这里采用DelayQueue来辅助以少量空间换时间,从而做到了“精准推进”。Kafka中的定时器真可谓是“知人善用”,用TimingWheel做最擅长的任务添加和删除操作,而用DelayQueue做最擅长的时间推进工作,相辅相成。

21.Kafka中的事务是怎么实现的?

在说Kafka的事务之前,先要说一下Kafka中幂等的实现。幂等和事务是Kafka 0.11.0.0版本引入的两个特性,以此来实现EOS(exactly once semantics,精确一次处理语义)。

幂等,简单地说就是对接口的多次调用所产生的结果和调用一次是一致的。生产者在进行重试的时候有可能会重复写入消息,而使用Kafka的幂等性功能之后就可以避免这种情况。

开启幂等性功能的方式很简单,只需要显式地将生产者客户端参数enable.idempotence设置为true即可(这个参数的默认值为false)。

Kafka是如何具体实现幂等的呢?Kafka为此引入了producer id(以下简称PID)和序列号(sequence number)这两个概念。每个新的生产者实例在初始化的时候都会被分配一个PID,这个PID对用户而言是完全透明的。

对于每个PID,消息发送到的每一个分区都有对应的序列号,这些序列号从0开始单调递增。生产者每发送一条消息就会将对应的序列号的值加1。

broker端会在内存中为每一对维护一个序列号。对于收到的每一条消息,只有当它的序列号的值(SN_new)比broker端中维护的对应的序列号的值(SN_old)大1(即SN_new = SN_old + 1)时,broker才会接收它。

如果SN_new< SN_old + 1,那么说明消息被重复写入,broker可以直接将其丢弃。如果SN_new> SN_old + 1,那么说明中间有数据尚未写入,出现了乱序,暗示可能有消息丢失,这个异常是一个严重的异常。

引入序列号来实现幂等也只是针对每一对而言的,也就是说,Kafka的幂等只能保证单个生产者会话(session)中单分区的幂等。幂等性不能跨多个分区运作,而事务可以弥补这个缺陷。

事务可以保证对多个分区写入操作的原子性。操作的原子性是指多个操作要么全部成功,要么全部失败,不存在部分成功、部分失败的可能。

为了使用事务,应用程序必须提供唯一的transactionalId,这个transactionalId通过客户端参数transactional.id来显式设置。事务要求生产者开启幂等特性,因此通过将transactional.id参数设置为非空从而开启事务特性的同时需要将enable.idempotence设置为true(如果未显式设置,则KafkaProducer默认会将它的值设置为true),如果用户显式地将enable.idempotence设置为false,则会报出ConfigException的异常。

transactionalId与PID一一对应,两者之间所不同的是transactionalId由用户显式设置,而PID是由Kafka内部分配的。

另外,为了保证新的生产者启动后具有相同transactionalId的旧生产者能够立即失效,每个生产者通过transactionalId获取PID的同时,还会获取一个单调递增的producer epoch。如果使用同一个transactionalId开启两个生产者,那么前一个开启的生产者会报错。

从生产者的角度分析,通过事务,Kafka可以保证跨生产者会话的消息幂等发送,以及跨生产者会话的事务恢复。

前者表示具有相同transactionalId的新生产者实例被创建且工作的时候,旧的且拥有相同transactionalId的生产者实例将不再工作。

后者指当某个生产者实例宕机后,新的生产者实例可以保证任何未完成的旧事务要么被提交(Commit),要么被中止(Abort),如此可以使新的生产者实例从一个正常的状态开始工作。

KafkaProducer提供了5个与事务相关的方法,详细如下:

在消费端有一个参数isolation.level,与事务有着莫大的关联,这个参数的默认值为“read_uncommitted”,意思是说消费端应用可以看到(消费到)未提交的事务,当然对于已提交的事务也是可见的。

这个参数还可以设置为“read_committed”,表示消费端应用不可以看到尚未提交的事务内的消息。

举个例子,如果生产者开启事务并向某个分区值发送3条消息msg1、msg2和msg3,在执行commitTransaction()或abortTransaction()方法前,设置为“read_committed”的消费端应用是消费不到这些消息的,不过在KafkaConsumer内部会缓存这些消息,直到生产者执行commitTransaction()方法之后它才能将这些消息推送给消费端应用。反之,如果生产者执行了abortTransaction()方法,那么KafkaConsumer会将这些缓存的消息丢弃而不推送给消费端应用。

日志文件中除了普通的消息,还有一种消息专门用来标志一个事务的结束,它就是控制消息(ControlBatch)。控制消息一共有两种类型:COMMIT和ABORT,分别用来表征事务已经成功提交或已经被成功中止。

RecordBatch中attributes字段的第6位用来标识当前消息是否是控制消息。如果是控制消息,那么这一位会置为1,否则会置为0,如上图所示。

attributes字段中的第5位用来标识当前消息是否处于事务中,如果是事务中的消息,那么这一位置为1,否则置为0。由于控制消息也处于事务中,所以attributes字段的第5位和第6位都被置为1。

KafkaConsumer可以通过这个控制消息来判断对应的事务是被提交了还是被中止了,然后结合参数isolation.level配置的隔离级别来决定是否将相应的消息返回给消费端应用,如上图所示。注意ControlBatch对消费端应用不可见。

22.Kafka中有那些地方需要选举?这些地方的选举策略又有哪些?

Kafka是一个高性能,高容错,多副本,可复制的分布式消息系统。在整个系统中,涉及到多处选举机制,被不少人搞混,这里总结一下,本篇文章大概会从三个方面来讲解。

  • 控制器(Broker)选主
  • 分区多副本选主
  • 消费组选主

控制器(Broker)选举

所谓控制器就是一个Borker,在一个kafka集群中,有多个broker节点,但是它们之间需要选举出一个leader,其他的broker充当follower角色。集群中第一个启动的broker会通过在zookeeper中创建临时节点/controller来让自己成为控制器,其他broker启动时也会在zookeeper中创建临时节点,但是发现节点已经存在,所以它们会收到一个异常,意识到控制器已经存在,那么就会在zookeeper中创建watch对象,便于它们收到控制器变更的通知。

那么如果控制器由于网络原因与zookeeper断开连接或者异常退出,那么其他broker通过watch收到控制器变更的通知,就会去尝试创建临时节点/controller,如果有一个broker创建成功,那么其他broker就会收到创建异常通知,也就意味着集群中已经有了控制器,其他broker只需创建watch对象即可。

如果集群中有一个broker发生异常退出了,那么控制器就会检查这个broker是否有分区的副本leader,如果有那么这个分区就需要一个新的leader,此时控制器就会去遍历其他副本,决定哪一个成为新的leader,同时更新分区的ISR集合。

如果有一个broker加入集群中,那么控制器就会通过Broker ID去判断新加入的broker中是否含有现有分区的副本,如果有,就会从分区副本中去同步数据。

集群中每选举一次控制器,就会通过zookeeper创建一个controller epoch,每一个选举都会创建一个更大,包含最新信息的epoch,如果有broker收到比这个epoch旧的数据,就会忽略它们,kafka也通过这个epoch来防止集群产生“脑裂”。

分区副本选举机制

在kafka的集群中,会存在着多个主题topic,在每一个topic中,又被划分为多个partition,为了防止数据不丢失,每一个partition又有多个副本,在整个集群中,总共有三种副本角色:

  • 首领副本(leader):也就是leader主副本,每个分区都有一个首领副本,为了保证数据一致性,所有的生产者与消费者的请求都会经过该副本来处理。
  • 跟随者副本(follower):除了首领副本外的其他所有副本都是跟随者副本,跟随者副本不处理来自客户端的任何请求,只负责从首领副本同步数据,保证与首领保持一致。如果首领副本发生崩溃,就会从这其中选举出一个leader。
  • 首选首领副本:创建分区时指定的首选首领。如果不指定,则为分区的第一个副本。

follower需要从leader中同步数据,但是由于网络或者其他原因,导致数据阻塞,出现不一致的情况,为了避免这种情况,follower会向leader发送请求信息,这些请求信息中包含了follower需要数据的偏移量offset,而且这些offset是有序的。

如果有follower向leader发送了请求1,接着发送请求2,请求3,那么再发送请求4,这时就意味着follower已经同步了前三条数据,否则不会发送请求4。leader通过跟踪 每一个follower的offset来判断它们的复制进度。

默认的,如果follower与leader之间超过10s内没有发送请求,或者说没有收到请求数据,此时该follower就会被认为“不同步副本”。而持续请求的副本就是“同步副本”,当leader发生故障时,只有“同步副本”才可以被选举为leader。其中的请求超时时间可以通过参数replica.lag.time.max.ms参数来配置。

我们希望每个分区的leader可以分布到不同的broker中,尽可能的达到负载均衡,所以会有一个首选首领,如果我们设置参数auto.leader.rebalance.enable为true,那么它会检查首选首领是否是真正的首领,如果不是,则会触发选举,让首选首领成为首领。

消费组选主

在kafka的消费端,会有一个消费者协调器以及消费组,组协调器GroupCoordinator需要为消费组内的消费者选举出一个消费组的leader,那么如何选举的呢?

如果消费组内还没有leader,那么第一个加入消费组的消费者即为消费组的leader,如果某一个时刻leader消费者由于某些原因退出了消费组,那么就会重新选举leader,如何选举?

上面代码是kafka源码中的部分代码,member是一个hashmap的数据结构,key为消费者的member_id,value是元数据信息,那么它会将leaderId选举为Hashmap中的第一个键值对,它和随机基本没啥区别。

对于整个选举算法的详情需要先了解Raft选举算法,kafka是基于该算法来实现leader选举的。

23.Kafka 与传统消息系统之间有三个关键区别

Kafka 持久化日志,这些日志可以被重复读取和无限期保留
Kafka 是一个分布式系统:它以集群的方式运行,可以灵活伸缩,在内部通过复制数据提升容错能力和高可用性
Kafka 支持实时的流式处理

24.Kafka 创建 Topic 时如何将分区放置到不同的 Broker 中

副本因子不能大于 Broker 的个数,第一个分区(编号为 0)的第一个副本放置位置是随机从 brokerList 选择的,其他分区的第一个副本放置位置相对于第0个分区依次往后移。也就是如果我们有5个 Broker,5个分区,假设第一个分区放在第四个 Broker 上,那么第二个分区将会放在第五个 Broker 上,第三个分区将会放在第一个 Broker 上;第四个分区将会放在第二个 Broker 上,依次类推,剩余的副本相对于第一个副本放置位置其实是由 nextReplicaShift 决定的,而这个数也是随机产生的。

25.Kafka 新建的分区会在哪个目录下创建?

在启动 Kafka 集群之前,我们需要配置好 log.dirs 参数,其值是 Kafka 数据的存放目录,这个参数可以配置多个目录,目录之间使用逗号分隔,通常这些目录是分布在不同的磁盘
上用于提高读写性能。

当然我们也可以配置 log.dir 参数,含义一样。只需要设置其中一个即可。

如果 log.dirs 参数只配置了一个目录,那么分配到各个 Broker 上的分区肯定只能在这个目录下创建文件夹用于存放数据。

但是如果 log.dirs 参数配置了多个目录,那么 Kafka 会在哪个文件夹中创建分区目录呢?

答案是:Kafka 会在含有分区目录最少的文件夹中创建新的分区目录,分区目录名为 Topic 名+分区 ID。注意,是分区文件夹总数最少的目录,而不是磁盘使用量最少的目录!也就是说,如果你给 log.dirs 参数新增了一个新的磁盘,新的分区目录肯定是先在这个新的磁盘上创建直到这个新的磁盘目录拥有的分区目录不是最少为止。

26.partition 的数据如何保存到硬盘

topic 中的多个 partition 以文件夹的形式保存到 broker,每个分区序号从 0 递增,且消息有序 Partition 文件下有多个 segment(xxx.index,xxx.log)segment 文件里的 大小和配置文件大小一致可以根据要求修改 默认为 1g 如果大小大于 1g 时,会滚动一个新的 segment 并且以上一个 segment 最后一条消息的偏移量命名。

27.Kafka 判断一个节点是否还活着有那两个条件?

节点必须可以维护和 ZooKeeper 的连接,Zookeeper 通过心跳机制检查每个节点的连接
如果节点是个 follower,他必须能及时的同步 leader 的写操作,延时不能太久

0

Hadoop面试题精选集合带答案

1. 以下哪一项不属于Hadoop可以运行的模式___C___。

A. 单机(本地)模式

B. 伪分布式模式

C. 互联模式

D. 分布式模式

2. Hadoop的作者是下面哪一位__B____。

A. Martin Fowler

B. Doug cutting

C. Kent Beck

D. Grace Hopper

3. 下列哪个程序通常与 NameNode 在同一个节点启动__D___。

A. TaskTracker

B. DataNode

C. SecondaryNameNode

D. Jobtracker

4. HDFS 默认 Block Size的大小是___B___。

A.32MB

B.64MB

C.128MB

D.256M

5. 下列哪项通常是集群的最主要瓶颈____C__。

A. CPU

B. 网络

C. 磁盘IO

D. 内存

6. 下列关于MapReduce说法不正确的是_____C_。

A. MapReduce是一种计算框架

B. MapReduce来源于google的学术论文

C. MapReduce程序只能用java语言编写

D. MapReduce隐藏了并行计算的细节,方便使用

8. HDFS是基于流数据模式访问和处理超大文件的需求而开发的,具有高容错、高可靠性、高可扩展性、高吞吐率等特征,适合的读写任务是 __D____。

A.一次写入,少次读

B.多次写入,少次读

C.多次写入,多次读

D.一次写入,多次读

9. HBase依靠__A____存储底层数据。

A. HDFS

B. Hadoop

C. Memory

D. MapReduce

10. HBase依赖___D___提供强大的计算能力。

A. Zookeeper

B. Chubby

C. RPC

D. MapReduce

11. HBase依赖___A___提供消息通信机制

A. Zookeeper

B. Chubby

C. RPC

D. Socket

12. 下面与HDFS类似的框架是___C____?

A. NTFS

B. FAT32

C. GFS

D. EXT3

13. 关于 SecondaryNameNode 下面哪项是正确的___C___。

A. 它是 NameNode 的热备

B. 它对内存没有要求

C. 它的目的是帮助 NameNode 合并编辑日志,减少 NameNode 启动时间

D. SecondaryNameNode 应与 NameNode 部署到一个节点

14. 大数据的特点不包括下面哪一项___D___。

A. 巨大的数据量

B. 多结构化数据

C. 增长速度快

D. 价值密度高

HBase测试题

1. HBase来源于哪一项? C

A The Google File System

B MapReduce

C BigTable

D Chubby

2. 下面对HBase的描述哪些是正确的? B、C、D

A 不是开源的

B 是面向列的

C 是分布式的

D 是一种NoSQL数据库

3. HBase依靠()存储底层数据 A

A HDFS

B Hadoop

C Memory

D MapReduce

4. HBase依赖()提供消息通信机制 A

A Zookeeper

B Chubby

C RPC

D Socket

5. HBase依赖()提供强大的计算能力 D

A Zookeeper

B Chubby

C RPC

D MapReduce

6. MapReduce与HBase的关系,哪些描述是正确的? B、C

A 两者不可或缺,MapReduce是HBase可以正常运行的保证

B 两者不是强关联关系,没有MapReduce,HBase可以正常运行

C MapReduce可以直接访问HBase

D 它们之间没有任何关系

7. 下面哪些选项正确描述了HBase的特性? A、B、C、D

A 高可靠性

B 高性能

C 面向列

D可伸缩

8. 下面与Zookeeper类似的框架是?D

A Protobuf

B Java

C Kafka

D Chubby

9. 下面与HDFS类似的框架是?C

A NTFS

B FAT32

C GFS

D EXT3

10. 下面哪些概念是HBase框架中使用的?A、C

A HDFS

B GridFS

C Zookeeper

D EXT3

第二部分:HBase核心知识点

11. LSM含义是?A

A 日志结构合并树

B 二叉树

C 平衡二叉树

D 基于日志结构的合并树

12. 下面对LSM结构描述正确的是? A、C

A 顺序存储

B 直接写硬盘

C 需要将数据Flush到磁盘

D 是一种搜索平衡树

13. LSM更能保证哪种操作的性能?B

A 读

B 写

C 随机读

D 合并

14. LSM的读操作和写操作是独立的?A

A 是。

B 否。

C LSM并不区分读和写

D LSM中读写是同一种操作

15. LSM结构的数据首先存储在()。 B

A 硬盘上

B 内存中

C 磁盘阵列中

D 闪存中

16 HFile数据格式中的Data字段用于()。A

A 存储实际的KeyValue数据

B 存储数据的起点

C 指定字段的长度

D 存储数据块的起点

17 HFile数据格式中的MetaIndex字段用于()。D

A Meta块的长度

B Meta块的结束点

C Meta块数据内容

D Meta块的起始点

18 HFile数据格式中的Magic字段用于()。A

A 存储随机数,防止数据损坏

B 存储数据的起点

C 存储数据块的起点

D 指定字段的长度

19 HFile数据格式中的KeyValue数据格式,下列选项描述正确的是()。A、D

A 是byte[]数组

B 没有固定的结构

C 数据的大小是定长的

D 有固定的结构

20 HFile数据格式中的KeyValue数据格式中Value部分是()。C

A 拥有复杂结构的字符串

B 字符串

C 二进制数据

D 压缩数据

第三部分:HBase高级应用介绍

31 HBase中的批量加载底层使用()实现。A

A MapReduce

B Hive

C Coprocessor

D Bloom Filter

32. HBase性能优化包含下面的哪些选项?A、B、C、D

A 读优化

B 写优化

C 配置优化

D JVM优化

33. Rowkey设计的原则,下列哪些选项的描述是正确的?A、B、C

A 尽量保证越短越好

B 可以使用汉字

C 可以使用字符串

D 本身是无序的

34. HBase构建二级索引的实现方式有哪些? A、B

A MapReduce

B Coprocessor

C Bloom Filter

D Filter

35. 关于HBase二级索引的描述,哪些是正确的?A、B

A 核心是倒排表

B 二级索引概念是对应Rowkey这个“一级”索引

C 二级索引使用平衡二叉树

D 二级索引使用LSM结构

36. 下列关于Bloom Filter的描述正确的是?A、C

A 是一个很长的二进制向量和一系列随机映射函数

B 没有误算率

C 有一定的误算率

D 可以在Bloom Filter中删除元素

第四部分:HBase安装、部署、启动

37. HBase官方版本可以安装在什么操作系统上?A、B、C

A CentOS

B Ubuntu

C RedHat

D Windows

38. HBase虚拟分布式模式需要()个节点?A

A 1

B 2

C 3

D 最少3个

39. HBase分布式模式最好需要()个节点?C

A 1

B 2

C 3

D 最少

关于hadoop的选择题

1、Doug Cutting所创立的项目的名称都受到其家人的启发,以下项目不是由他创立的项目是

A. Hadoop

B. Nutch

C. Lucene

D. Solr

答案:D

2、配置Hadoop时,JAVA_HOME包含在哪一个配置文件中

A. hadoop-default.xml

B. hadoop-env.sh

C. hadoop-site.xml

D. configuration.xsl

答案:B

知识点:hadoop配置

3、Hadoop配置文件中,hadoop-site.xml显示覆盖hadoop-default.xml里的内容。在版本0.20中,hadoop-site.xml被分离成三个XML文件,不包括

A. conf-site.xml

B. mapred-site.xml

C. core-site.xml

D. hdfs-site.xml

答案:A

知识点:hadoop配置

4、HDFS默认的当前工作目录是/user/$USER,fs.default.name的值需要在哪个配置文件内说明

A. mapred-site.xml

B. core-site.xml

C. hdfs-site.xml

D. 以上均不是

答案:B

知识点:hadoop配置

5、关于Hadoop单机模式和伪分布式模式的说法,正确的是

A. 两者都起守护进程,且守护进程运行在一台机器上

B. 单机模式不使用HDFS,但加载守护进程

C. 两者都不与守护进程交互,避免复杂性

D. 后者比前者增加了HDFS输入输出以及可检查内存使用情况

答案:D

知识点:hadoop配置

6、下列关于Hadoop API的说法错误的是

A. Hadoop的文件API不是通用的,只用于HDFS文件系统

B. Configuration类的默认实例化方法是以HDFS系统的资源配置为基础的

C. FileStatus对象存储文件和目录的元数据

D. FSDataInputStream是java.io.DataInputStream的子类

答案:A

//HDFS

7、HDFS的NameNode负责管理文件系统的命名空间,将所有的文件和文件夹的元数据保存在一个文件系统树中,这些信息也会在硬盘上保存成以下文件:

A.日志

B.命名空间镜像

C.两者都是

答案:C

知识点:

8、HDFS的namenode保存了一个文件包括哪些数据块,分布在哪些数据节点上,这些信息也存储在硬盘上。

A.正确

B.错误

答案:B

知识点:在系统启动的时候从数据节点收集而成的

9、Secondary namenode就是namenode出现问题时的备用节点

A.正确

B.错误

答案:B

知识点:它和元数据节点负责不同的事情。其主要功能就是周期性将元数据节点的命名空间镜像文件和修改日志合并,以防日志文件过大。合并过后的命名空间镜像文件也在Secondary namenode保存了一份,以防namenode失败的时候,可以恢复。

10、出现在datanode的VERSION文件格式中但不出现在namenode的VERSION文件格式中的是

A. namespaceID

B. storageID

C. storageType

D. layoutVersion

答案:B

知识点:其他三项是公有的。layoutVersion是一个负整数,保存了HDFS的持续化在硬盘上的数据结构的格式版本号;namespaceID是文件系统的唯一标识符,是在文件系统初次格式化时生成的;storageType表示此文件夹中保存的是数据节点的类型

11、Client在HDFS上进行文件写入时,namenode根据文件大小和配置情况,返回部分datanode信息,谁负责将文件划分为多个Block,根据DataNode的地址信息,按顺序写入到每一个DataNode块

A. Client

B. Namenode

C. Datanode

D. Secondary namenode

答案:A

知识点:HDFS文件写入

12、HDFS的是基于流数据模式访问和处理超大文件的需求而开发的,默认的最基本的存储单位是64M,具有高容错、高可靠性、高可扩展性、高吞吐率等特征,适合的读写任务是

A.一次写入,少次读写

B.多次写入,少次读写

C.一次写入,多次读写

D.多次写入,多次读写

答案:C

知识点:HDFS特性

13、HDFS无法高效存储大量小文件,想让它能处理好小文件,比较可行的改进策略不包括

A. 利用SequenceFile、MapFile、Har等方式归档小文件

B. 多Master设计

C. Block大小适当调小

D. 调大namenode内存或将文件系统元数据存到硬盘里

答案:D

知识点:HDFS特性

14、关于HDFS的文件写入,正确的是

A. 支持多用户对同一文件的写操作

B. 用户可以在文件任意位置进行修改

C. 默认将文件块复制成三份存放

D. 复制的文件块默认都存在同一机架上

答案:C

知识点:在HDFS的一个文件中只有一个写入者,而且写操作只能在文件末尾完成,即只能执行追加操作。默认三份文件块两块在同一机架上,另一份存放在其他机架上。

15、Hadoop fs中的-get和-put命令操作对象是

A. 文件

B. 目录

C. 两者都是

答案:C

知识点:HDFS命令

16、Namenode在启动时自动进入安全模式,在安全模式阶段,说法错误的是

A. 安全模式目的是在系统启动时检查各个DataNode上数据块的有效性

B. 根据策略对数据块进行必要的复制或删除

C. 当数据块最小百分比数满足的最小副本数条件时,会自动退出安全模式

D. 文件系统允许有修改

答案:D

知识点:HDFS安全模式

//MapReduce

17、MapReduce框架提供了一种序列化键/值对的方法,支持这种序列化的类能够在Map和Reduce过程中充当键或值,以下说法错误的是

A. 实现Writable接口的类是值

B. 实现WritableComparable<T>接口的类可以是值或键

C. Hadoop的基本类型Text并不实现WritableComparable<T>接口

D. 键和值的数据类型可以超出Hadoop自身支持的基本类型

答案:C

18、以下四个Hadoop预定义的Mapper实现类的描述错误的是

A. IdentityMapper<K, V>实现Mapper<K, V, K, V>,将输入直接映射到输出

B. InverseMapper<K, V>实现Mapper<K, V, K, V>,反转键/值对

C. RegexMapper<K>实现Mapper<K, Text, Text, LongWritable>,为每个常规表达式的匹配项生成一个(match, 1)对

D. TokenCountMapper<K>实现Mapper<K, Text, Text, LongWritable>,当输入的值为分词时,生成(taken, 1)对

答案:B

知识点:InverseMapper<K, V>实现Mapper<K, V, V, K>

19、下列关于HDFS为存储MapReduce并行切分和处理的数据做的设计,错误的是

A. FSDataInputStream扩展了DataInputStream以支持随机读

B. 为实现细粒度并行,输入分片(Input Split)应该越小越好

C. 一台机器可能被指派从输入文件的任意位置开始处理一个分片

D. 输入分片是一种记录的逻辑划分,而HDFS数据块是对输入数据的物理分割

答案:B

知识点:每个分片不能太小,否则启动与停止各个分片处理所需的开销将占很大一部分执行时间

20、针对每行数据内容为”Timestamp Url”的数据文件,在用JobConf对象conf设置conf.setInputFormat(WhichInputFormat.class)来读取这个文件时,WhichInputFormat应该为以下的

A. TextInputFormat

B. KeyValueTextInputFormat

C. SequenceFileInputFormat

D. NLineInputFormat

答案:B

知识点:四项主要的InputFormat类。KeyValueTextInputFormat以每行第一个分隔符为界,分隔符前为key,之后为value,默认制表符为\t

21、有关MapReduce的输入输出,说法错误的是

A. 链接多个MapReduce作业时,序列文件是首选格式

B. FileInputFormat中实现的getSplits()可以把输入数据划分为分片,分片数目和大小任意定义

C. 想完全禁止输出,可以使用NullOutputFormat

D. 每个reduce需将它的输出写入自己的文件中,输出无需分片

答案:B

知识点:分片数目在numSplits中限定,分片大小必须大于mapred.min.size个字节,但小于文件系统的块

22、Hadoop Streaming支持脚本语言编写简单MapReduce程序,以下是一个例子:

bin/hadoop jar contrib/streaming/hadoop-0.20-streaming.jar

—input input/filename

—output output

—mapper ‘dosth.py 5’

—file dosth.py

—D mapred.reduce.tasks=1

23、以下说法不正确的是

A. Hadoop Streaming使用Unix中的流与程序交互

B. Hadoop Streaming允许我们使用任何可执行脚本语言处理数据流

C. 采用脚本语言时必须遵从UNIX的标准输入STDIN,并输出到STDOUT

D. Reduce没有设定,上述命令运行会出现问题

答案:D

知识点:没有设定特殊的reducer,默认使用IdentityReducer

24、在高阶数据处理中,往往无法把整个流程写在单个MapReduce作业中,下列关于链接MapReduce作业的说法,不正确的是

A.Job和JobControl类可以管理非线性作业之间的依赖

B.ChainMapper和ChainReducer类可以用来简化数据预处理和后处理的构成

C.使用ChainReducer时,每个mapper和reducer对象都有一个本地JobConf对象

D.ChainReducer.addMapper()方法中,一般对键/值对发送设置成值传递,性能好且安全性高

答案:D

知识点:ChainReducer.addMapper()方法中,值传递安全性高,引用传递性能高

25、下面哪个程序负责 HDFS 数据存储。答案C datanode

a)NameNode

b)Jobtracker

c)Datanode

d)secondaryNameNode

e)tasktracker

26. HDfS 中的 block 默认保存几份? 答案A默认3分

a)3 份

b)2 份

c)1 份

d)不确定

27. 下列哪个程序通常与 NameNode 在一个节点启动?答案D

a)SecondaryNameNode

b)DataNode

c)TaskTracker

d)Jobtracker

28. Hadoop 作者 答案C Doug cutting

a)Martin Fowler

b)Kent Beck

c)Doug cutting

29. HDFS 默认 Block Size 答案:B

a)32MB

b)64MB

c)128MB

30、下列哪项通常是集群的最主要瓶颈:答案:C磁盘

a)CPU

b)网络

c)磁盘IO

d)内存

31. 关于 SecondaryNameNode 哪项是正确的?答案C

a)它是 NameNode 的热备

b)它对内存没有要求

c)它的目的是帮助 NameNode 合并编辑日志,减少 NameNode 启动时间

d)SecondaryNameNode 应与 NameNode 部署到一个节点。

多选题:

1. 下列哪项可以作为集群的管理?答案:ABD

a)Puppet

b)Pdsh

c)Cloudera Manager

d)Zookeeper

2. 配置机架感知的下面哪项正确:答案ABC

a)如果一个机架出问题,不会影响数据读写

b)写入数据的时候会写到不同机架的 DataNode 中

c)MapReduce 会根据机架获取离自己比较近的网络数据

3. Client 端上传文件的时候下列哪项正确?答案B

a)数据经过 NameNode 传递给 DataNode

b)Client 端将文件切分为 Block,依次上传

c)Client 只上传数据到一台 DataNode,然后由 NameNode 负责 Block 复制工作

4. 下列哪个是 Hadoop 运行的模式:答案ABC

a)单机版

b)伪分布式

c)分布式

5. Cloudera 提供哪几种安装 CDH 的方法?答案:ABCD

a)Cloudera manager

b)Tarball

c)Yum

d)Rpm

判断题:

1. Ganglia 不仅可以进行监控,也可以进行告警。( 正确)

2. Block Size 是不可以修改的。(错误 )

3. Nagios 不可以监控 Hadoop 集群,因为它不提供 Hadoop 支持。(错误 )

4. 如果 NameNode 意外终止,SecondaryNameNode 会接替它使集群继续工作。(错误 )

5. Cloudera CDH 是需要付费使用的。(错误 )

6. Hadoop 是 Java 开发的,所以 MapReduce 只支持 Java 语言编写。(错误 )

7. Hadoop 支持数据的随机读写。(错 )

8. NameNode 负责管理 metadata,client 端每次读写请求,它都会从磁盘中读取或则会写入 metadata 信息并反馈 client 端。(错误)

9. Hadoop 自身具有严格的权限管理和安全措施保障集群正常运行。(错误 )

10. Slave 节点要存储数据,所以它的磁盘越大越好。( 错误)

11. hadoop dfsadmin –report 命令用于检测 HDFS 损坏块。(错误 )

12. Hadoop 默认调度器策略为 FIFO(正确 )

13. 集群内每个节点都应该配 RAID,这样避免单磁盘损坏,影响整个节点运行。(错误 )

14.因为 HDFS 有多个副本,所以 NameNode 是不存在单点问题的。(错误 )

15. 每个 map 槽就是一个线程。(错误 )

16. Mapreduce 的 input split 就是一个 block。(错误 )

17. DataNode 首次加入 cluster 的时候,如果 log 中报告不兼容文件版本,那需要 NameNode执行“Hadoop namenode -format”操作格式化磁盘。(错误 )

18. NameNode 的 Web UI 端口是 50030,它通过 jetty 启动的 Web 服务。(错误 )

19. Hadoop 环境变量中的 HADOOP_HEAPSIZE 用于设置所有 Hadoop 守护线程的内存。它默认是 200 GB。( 错误)

单纯的课本内容,并不能满足学生的需要,通过补充,达到内容的完善

0

kafka集群升级导致broker.id发生变动变动引起的问题

最近遇到一个问题,由于kafka集群升级导致每个broker.id出现了变动,但是topic的partition所在broker的信息依旧是原broker.id,这就造成了所有partition都丢失leader。

发现问题

通过kafka的命令发现topic的partition都没有leader,然后看了下集群监控和日志都没有明显的异常,但是日常显示的broker.id和通过kafka命令显示的有出入,进一步去zookeeper上查看了所有broker.id情况,发现是broker.id变了导致kafka controller无法通过partition依赖的broker.id找到对应的broker。

先说明一下自动生成broker.id的由来,kafka开启了broker.id.generation.enable,也就是自动生成broker.id功能,kafka在早期版本需要人为给每个broker分配一个broker.id,在server.properties配置里申明,从0.9.0版本开始,kafka支持并默认了自动生成broker.id功能。那么kafka是如何自动生成broker.id的呢?有一点是必须的,broker.id在这个kafka集群必须是全局唯一的,分布式下的全局唯一,那就联想到分布式锁了。kafka通过在zookeeper里写空字符串,触发该znode的版本自增,然后把获取的版本号和另一个配置reserved.broker.max.id相加,就得到了该broker节点的broker.id。

kafka查看topic所有partition依赖的broker,leader以及isr

zk查看当前kafka集群自增的broker序号

zk查看当前kafka集群所有的broker.id

zk查看topic所有partition的broker.id

解决问题

手动删除错误broker.id的topic,删除完成后重启kafka集群

0