秋招大数据\算法\数据挖掘面试总结(三)

HashMap为什么线程不安全concurrentHashMap

1 在put数据的时候可能照成插入的数据被掩盖。

2.在插入时,可能会照成resize,此时可能会造成环形链表 ,在get时会造成死循环

HashMap在put的时候,插入的元素超过了容量(由负载因子决定)的范围就会触发扩容操作,就是rehash,这个会重新将原数组的内容重新hash到新的扩容数组中,在多线程的环境下,存在同时其他的元素也在进行put操作,如果hash值相同,可能出现同时在同一数组下用链表表示,造成闭环,导致在get时会出现死循环,所以HashMap是线程不安全的。

concurrentHashMap底层使用的是CAS乐观锁技术

Kafka与现有MQ的比较

可扩展。Kafka集群可以透明的扩展,增加新的服务器进集群。

高性能。Kafka性能远超过传统的ActiveMQ、RabbitMQ等,Kafka支持Batch操作。

容错性。Kafka每个Partition数据会复制到几台服务器,当某个Broker失效时,Zookeeper将通知生产者和消费者从而使用其他的Broker。

缺点:

 

重复消息。Kafka保证每条消息至少送达一次,虽然几率很小,但一条消息可能被送达多次。

消息乱序。Kafka某一个固定的Partition内部的消息是保证有序的,如果一个Topic有多个Partition,partition之间的消息送达不保证有序。

复杂性。Kafka需要Zookeeper的支持,Topic一般需要人工创建,部署和维护比一般MQ成本更高

 

 

保证每个消费者读取数据都是有序的,而传统队列在服务器上按顺序保留消息,如果多个消费者从队列中消耗,则服务器按照存储的顺序分发消息。但是,尽管服务器按顺序分发消息,但消息是异步传递给消费者的,因此它们可能会在不同的消费者上无序传送。

 

 

Kafka 持久化日志,这些日志可以被重复读取和无限期保留

Kafka 是一个分布式系统:它以集群的方式运行,可以灵活伸缩,在内部通过复制数据提升容错能力和高可用性

Kafka 支持实时的流式处理

 

 

kafka设计的目标是:

高吞吐量,支持大容量事件流;高抗压,支持离线系统周期性的数据压力;低延迟;动态分布式分区;容错;

2.1 消息交付保证

消息交付是否可靠,有以下几种保证:

At least once。至少一次。消息绝不会丢失,但有可能重新发送。(request.required.acks=1或-1)。Kafka的默认保证。 At most once。最多一次。消息可能丢失,但永远不会重发。通过设置Producer异步提交可以实现。(request.required.acks=0)。 Exactly once。传递一次且仅一次。要求利用外部存储系统配合Kafka的offset来保证。

2.2 高吞吐量

高吞吐量依赖于OS文件系统的页缓存、sendfile技术和线性读写磁盘:

PageCache

依赖OS的页缓存能大量减少IO,高效利用内存来作为缓存。当上层有写操作时,操作系统只是将数据写入OS的PageCache,同时标记Page属性为Dirty。当读操作发生时,先从PageCache中查找,如果发生缺页才进行磁盘调度,最终返回需要的数据。实际上PageCache是把尽可能多的空闲内存都当做了磁盘缓存来使用。同时如果有其他进程申请内存,回收PageCache的代价又很小。

zero-copy

传统网络IO,OS 从硬盘把数据读到内核区的PageCache,用户进程把数据从内核区Copy到用户区。然后用户进程再把数据写入到Socket,数据流入内核区的Socket Buffer上。OS 再把数据从Buffer中Copy到网卡的Buffer上,这样完成一次发送。整个过程共经历两次Context Switch,四次System Call。

同一份数据在内核Buffer与用户Buffer之间重复拷贝,效率低下。其中2、3两步没有必要,完全可以直接在内核区完成数据拷贝。这也正是Sendfile所解决的问题,经过Sendfile优化后,整个I/O过程就变成了下面这个样子。

 

秋招大数据\算法\数据挖掘面试总结(三)_第1张图片

秋招大数据\算法\数据挖掘面试总结(三)_第2张图片

磁盘顺序写

磁盘线性读写要比随机读写快很多。顺序IO不仅可以利用RAID技术带来很高的吞吐量,同时可以基于文件的读和追加来构建持久化队列,利用队列来提供常量时间O(1)时间复杂度的put和get。

消息压缩

Producer支持End-to-End的压缩。数据在本地压缩后放到网络上传输,在Broker一般不解压(除非指定要Deep-Iteration),直至消息被Consume之后在客户端解压。

当然用户也可以选择自己在应用层上做压缩和解压的工作(毕竟Kafka目前支持的压缩算法有限,只有GZIP和Snappy),不过这样可能造成效率的意外降低!

Kafka的End-to-End压缩与MessageSet配合在一起工作效果最佳,上面的做法直接割裂了两者间联系。至于道理其实很简单,压缩算法中一条基本的原理“重复的数据量越多,压缩比越高”。大多数情况下输入数据量大一些会取得更好的压缩比。

 

Zookeeper的特性和怎么实现主从切换

Zookeeper通过事务日志和数据快照来避免因为服务器故障导致的数据丢失。

  • 事务日志是指服务器在更新内存数据前先将事务操作以日志的方式写入磁盘,Leader和Follower服务器都会记录事务日志。
  • 数据快照是指周期性通过深度遍历的方式将内存中的树形结构数据转入外存快照中。但要注意这种快照是"模糊"的,因为可能在做快照时内存数据发生了变化。但是因为Zookeeper本身对事务操作进行了幂等性保证,故在将快照加载进内存后会通过执行事务日志的方式来讲数据恢复到最新状态。

 

Redis分片

redis cluster集群通过分片的方式来保存数据库中键值对:集群的整个数据库被分为16384个槽(slot),

数据库中的每个键都属于这16384个槽的其中一个,集群中的每个节点可以处理0个或者最多16384个槽

每个结点存储一部分的slot。一个槽只能存储一条数据?

Kafka中bootstrap-server、broker-list和zookeeper的区别

0.8 以前,消费进度是直接写到 zookeeper 的,consumer 必须知道 zookeeper 的地址。这个方案有性能问题,0.9 的时候整体大改了一次,brokers 接管了消费进度,consumer 不再需要和 zookeeper 通信

broker-list和bootstrap-server是同种意思,前者是老版本

Kafka如何保证数据不丢失

生产端配置参数:

 

request.required.acks

This value controls when a produce request is considered completed. Specifically, how many other brokers must have committed the data to their log and acknowledged this to the leader? Typical values are

  • 0, which means that the producer never waits for an acknowledgement from the broker (the same behavior as 0.7). This option provides the lowest latency but the weakest durability guarantees (some data will be lost when a server fails).
  • 1, which means that the producer gets an acknowledgement after the leader replica has received the data. This option provides better durability as the client waits until the server acknowledges the request as successful (only messages that were written to the now-dead leader but not yet replicated will be lost).
  • -1, The producer gets an acknowledgement after all in-sync replicas have received the data. This option provides the greatest level of durability. However, it does not completely eliminate the risk of message loss because the number of in sync replicas may, in rare cases, shrink to 1. If you want to ensure that some minimum number of replicas (typically a majority) receive a write, then you must set the topic-level min.insync.replicas setting. Please read the Replication section of the design documentation for a more in-depth discussion.

 

 

 

 

min.insync.replicas

 

When a producer sets request.required.acks to -1, min.insync.replicas specifies the minimum number of replicas that must acknowledge a write for the write to be considered successful. If this minimum cannot be met, then the producer will raise an exception (either NotEnoughReplicas or NotEnoughReplicasAfterAppend). 

When used together, min.insync.replicas and request.required.acks allow you to enforce greater durability guarantees. A typical scenario would be to create a topic with a replication factor of 3, set min.insync.replicas to 2, and produce with request.required.acks of -1. This will ensure that the producer raises an exception if a majority of replicas do not receive a write.

request.required.acks = ALL   (0就是不需要任何ack,相当于异步发送,只管发不管ack; 设成all或者-1,要求所有的fowller给leader回复,然后leader给producer确认,是最保险的,但是牺牲吞吐量)

数据复制及ISR队列

leader会维护一个与其基本保持同步的replica列表,这个列表被称为isr(in-sync-replica)

如果一个follower比leader落后太多,或者超过一定时间未发起数据复制请求,则leader将其从ISR移除

当Isr中所有replica都向leader发送ACK时,leader就commit同步的数据,之后consumer才能够消费这部分commit的数据

https://blog.csdn.net/longlovefilm/article/details/88342512

 

 

 

 

你可能感兴趣的:(面试)