大数据私房菜
Kafka为什么吞吐量大、速度快?
一、顺序读写
Kafka就是使用了磁盘顺序读写来提升的性能。Kafka的message是不断追加到本地磁盘文件末尾的,而不是随机的写入,这使得Kafka写入吞吐量得到了显著提升 。
这种方法有一个缺陷—— 没有办法删除数据 ,所以Kafka是不会删除数据的,它会把所有的数据都保留下来,每个消费者(Consumer)对每个Topic都有一个offset用来表示 读取到了第几条数据 。
二、Page Cache
为了优化读写性能,Kafka利用了操作系统本身的Page Cache,就是利用操作系统自身的内存而不是JVM空间内存。这样做的好处有:
1避免Object消耗:如果是使用 Java 堆,Java对象的内存消耗比较大,通常是所存储数据的两倍甚至更多。
2避免GC问题:随着JVM中数据不断增多,垃圾回收将会变得复杂与缓慢,使用系统缓存就不会存在GC问题
相比于使用JVM或in-memory cache等数据结构,利用操作系统的Page Cache更加简单可靠。首先,操作系统层面的缓存利用率会更高,因为存储的都是紧凑的字节结构而不是独立的对象。其次,操作系统本身也对于Page Cache做了大量优化,提供了 write-behind、read-ahead以及flush等多种机制。再者,即使服务进程重启,系统缓存依然不会消失,避免了in-process cache重建缓存的过程。
通过操作系统的Page Cache,Kafka的读写操作基本上是基于内存的,读写速度得到了极大的提升。
三、零拷贝
通过这种 “零拷贝” 的机制,Page Cache 结合 sendfile 方法,Kafka消费端的性能也大幅提升。这也是为什么有时候消费端在不断消费数据时,我们并没有看到磁盘io比较高,此刻正是操作系统缓存在提供数据。
当Kafka客户端从服务器读取数据时,如果不使用零拷贝技术,那么大致需要经历这样的一个过程:
1.操作系统将数据从磁盘上读入到内核空间的读缓冲区中。
2.应用程序(也就是Kafka)从内核空间的读缓冲区将数据拷贝到用户空间的缓冲区中。
3.应用程序将数据从用户空间的缓冲区再写回到内核空间的socket缓冲区中。
4.操作系统将socket缓冲区中的数据拷贝到NIC缓冲区中,然后通过网络发送给客户端。
kafka与传统的消息队列有什么不同
1.首先kafka会将接收到的消息分区(partition),每个主题(topic)的消息有不同的分区,这样一方面消息的存储就不会受到单一服务器存储空间大小的限制,另一方面消息的处理也可以在多个服务器上并行。
2.其次为了保证高可用,每个分区都会有一定数量的副本(replica)。这样如果有部分服务器不可用,副本所在的服务器就会接替上来,保证应用的持续性。
3.然后保证分区内部消息的消费有序性。
4.Kafka还具有consumer group的概念,每个分区只能被同一个group的一个consumer消费,但可以被多个group消费。
hadoop的ha
Active NameNode 和 Standby NameNode:两台 NameNode 形成互备,一台处于 Active 状态,为主 NameNode,另外一台处于 Standby 状态,为备 NameNode,只有主 NameNode 才能对外提供读写服务。
主备切换控制器 ZKFailoverController:ZKFailoverController 作为独立的进程运行,对 NameNode 的主备切换进行总体控制。ZKFailoverController 能及时检测到 NameNode 的健康状况,在主 NameNode 故障时借助 Zookeeper 实现自动的主备选举和切换,当然 NameNode 目前也支持不依赖于 Zookeeper 的手动主备切换。
Zookeeper 集群:为主备切换控制器提供主备选举支持。
共享存储系统:共享存储系统是实现 NameNode 的高可用最为关键的部分,共享存储系统保存了 NameNode 在运行过程中所产生的 HDFS 的元数据。主 NameNode 和备NameNode 通过共享存储系统实现元数据同步。在进行主备切换的时候,新的主 NameNode 在确认元数据完全同步之后才能继续对外提供服务。
DataNode 节点:除了通过共享存储系统共享 HDFS 的元数据信息之外,主 NameNode 和备 NameNode 还需要共享 HDFS 的数据块和 DataNode 之间的映射关系。DataNode 会同时向主 NameNode 和备 NameNode 上报数据块的位置信息。
HBase查询为什么这么快?
首先数据量很大的时候,HBase会拆分成多个Region分配到多台RegionServer.
客户端通过meta信息定位到某台RegionServer(也可能是多台),
通过Rowkey定位Region,这当中会先经过BlockCache,这边找不到的话,再经过MemStore和Hfile查询,这当中通过布隆过滤器过滤掉一些不需要查询的HFile。
使用场景
- 单表数据量超千万,而且并发还挺高。
- 数据分析需求较弱,或者不需要那么灵活或者实时
用户登录表A,字段:user_id,device_id,login_date,求用户最大连续登录天数
1 | select |
今日面经
synchronized与volatile的区别
- volatile是线程同步的轻量级实现,因此volatile性能好于synchronized
- voaltile修饰变量,synchronized修饰方法和代码块
- 多线程访问volatile不会发生阻塞,但访问synchronized可能会阻塞
- volatile可以保证数据的可见性,但不能保证原子性;而synchronized既可以保证原子性,也可以间接保证可见性。
- volatile解决的是变量在多个线程之间的可见性,而Synchronized解决的是多个线程之间访问资源的同步性
hadoop是什么
Apache Hadoop软件库是一个框架,它允许使用简单的编程模型跨计算机群集分布式处理大型数据集(海量的数据)。
HADOOP的核心组件有:
HDFS(分布式文件系统)
YARN(运算资源调度系统)
MAPREDUCE(分布式运算编程框架)
ArrayList原理,为什么初始是10,为什么扩容1.5倍
优点:
ArrayList底层以数组实现,是一种随机访问模式,再加上它实现了RandomAccess接口,因此查找也就是get的时候非常快。
ArrayList在顺序添加一个元素的时候非常方便,只是往数组里面添加了一个元素而已。
根据下标遍历元素,效率高。
通过上述:我们大概可知当add一个元素时候的扩容流程。
添加一个元素,首先计算当前的list所需最小的容量大小,是否需要扩容等。当需要扩容时:
1.得到当前的ArrayList的容量(oldCapacity)。
2.计算除扩容后的新容量(newCapacity),其值(oldCapacity + (oldCapacity >> 1))约是oldCapacity 的1.5倍。
这里采用的是移位运算(关于移位运算,后续会讲到)。
为什么采用这种方法呢?应该是出于效率的考虑。
3.当newCapacity小于所需最小容量,那么将所需最小容量赋值给newCapacity。
4.newCapacity大于ArrayList的所允许的最大容量,处理。
5.进行数据的复制,完成向ArrayList实例添加元素操作。
b+树和b树
B+树中只有叶子节点会带有指向记录的指针(ROWID),而B树则所有节点都带有,在内部节点出现的索引项不会再出现在叶子节点中。
B+树中所有叶子节点都是通过指针连接在一起,而B树不会。
B+树的优点:
非叶子节点不会带上ROWID,这样,一个块中可以容纳更多的索引项,一是可以降低树的高度。二是一个内部节点可以定位更多的叶子节点。
叶子节点之间通过指针来连接,范围扫描将十分简单,而对于B树来说,则需要在叶子节点和内部节点不停的往返移动。
公平锁和非公平锁
公平锁:多个线程按照申请锁的顺序去获得锁,线程会直接进入队列去排队,永远都是队列的第一位才能得到锁。
非公平锁:多个线程去获取锁的时候,会直接去尝试获取,获取不到,再去进入等待队列,如果能获取到,就直接获取到锁。
redeuce怎么知道从哪里下载map输出的文件
Shuffle是MapReduce处理流程中的一个流程,它的每一个处理步骤是分散在各个maptask和reducetask节点上完成的,整体来看,分为3个操作:
\1.分区partition
\2.Sort根据key排序
\3.Combiner进行局部value的合并
详细流程
- maptask收集map方法输出的kv对,放到内存缓冲区中
- 从内存缓冲区不断溢出本地磁盘文件,可能会溢出多个文件
- 多个溢出文件会被合并成大的溢出文件
- 在溢出过程中,及合并的过程中,都要调用partition进行分组和针对key进行排序
- reducetask根据自己的分区号,去各个maptask机器上去响应的结果分区数据
- reducetask会取到同一个分区来自不同maptask的结果文件,reducetask会将这些文件再进行合并(归并排序)
- 合并成大文件后,Shullfe的过程也就结束了,后面进入reducetask的逻辑运算过程(从文件中取出一个一个的键值对组,调用用户自定义的reduce()方法)
Shullfe中的缓冲区大小会影响到MapReduce程序的执行效率,原则上说,缓冲区越大,磁盘io的次数越少,执行速度就越快.缓冲区大大小可以通过参数调整,参数:io.sort.mb,默认为100M.
spring ioc和aop
(1)IOC是什么?
注:(Inversion Of Controll 控制反转) 对象之间的依赖关系由容器来建立。
(2)DI是什么?
注:(Dependency Injection 依赖注入) 容器通过调用set方法或者构造器来建立对象之间的 依赖关系。 IOC是目标,DI是手段。
aop
Spring AOP是其实是通过动态代理来实现业务逻辑的插入,是开发者在开发是不用关注其他与业务无关的点,通过代理的方式做到了插拔式操作。