一些面试问题

1. zk上一个节点挂了,还能不能正常使用?

在高可用框架中,咱们在系统架构设计时,会尽量避免单点问题,引入冗余的副本机制,分布式CAP理论中,无论AP还是CP,Partition Tolerance分区容错的特征必须得到保障;

Zookeeper 本身也是集群,推荐配置不少于 3 个服务器。Zookeeper 自身也要保证当一个节点宕机时,其他节点会继续提供服务。

如果是一个 Follower 宕机,还有 2 台服务器提供访问,因为 Zookeeper 上的数据是有多个副本的,数据并不会丢失;

如果是一个 Leader 宕机,Zookeeper 会选举出新的 Leader。
ZK 集群的机制是只要超过半数的节点正常,集群就能正常提供服务。只有在 ZK 节点挂得太多,只剩一半或不到一半节点能工作,集群才失效。
所以
3 个节点的 cluster 可以挂掉 1 个节点(leader 可以得到 2 票>1.5)
2 个节点的 cluster 就不能挂掉任何 1 个节点了(leader 可以得到 1 票<=1)

2.zookeeper 集群支持动态添加机器吗?

其实就是水平扩容了,Zookeeper 在这方面不太好。两种方式:

全部重启 :关闭所有 Zookeeper 服务,修改配置之后启动。不影响之前客户端的会话。
逐个重启在过半存活即可用的原则下,一台机器重启不影响整个集群对外提供服务。这是比较常用的方式。
3.5 版本开始支持动态扩容。

3. 如果zookeeper上面连接的服务器突然断了,那么客户端会不会断掉,如果没断怎么连接到新的服务器,这个过程是什么样的?客户端怎么获取到新的服务器的IP地址和端口号?是zookeeper主动提供的还是客户端自己拉取的?

在 ZooKeeper 中,当客户端与其连接的服务器断开时,ZooKeeper 会有一种内置的机制来处理这种情况,以确保客户端能够重新连接到一个可用的服务器。这整个过程是由客户端库来管理的,而不是需要用户手动处理。下面是详细的说明:

1. 客户端是否会断掉连接?

当客户端与它连接的 ZooKeeper 服务器断开时,客户端会立即感知到该连接已经中断(通常是通过 Socket 断开、心跳检测失败等方式)。但是,这并不意味着客户端就彻底断开了 ZooKeeper 服务。客户端会尝试在内部自动重新连接到集群中的其他服务器。

2. 重新连接到新的服务器的过程

ZooKeeper 集群通常有多个节点(称为ensemble)。每个客户端在最初连接时,都会获取 ZooKeeper 集群的配置信息(包括各个服务器的 IP 地址和端口号)。当与当前服务器断开后,客户端会自动尝试重新连接到其他可用的 ZooKeeper 服务器。

具体过程如下:

  • ZooKeeper 客户端库会自动监测到与服务器的连接中断。
  • 它会根据已经缓存的集群信息,轮询其他节点,尝试重新连接到可用的服务器。
  • 客户端会使用内置的重连机制,如果当前重试的服务器不可用,它会继续尝试连接到下一个服务器,直到成功连接为止。

3. 客户端如何获取新的服务器 IP 和端口?

在客户端初始连接时,它是通过一个服务器列表(IP : 端口号)来建立连接的。客户端并不会主动向 ZooKeeper 服务器拉取其他服务器的 IP 和端口号,而是在初始连接时由用户提供一个或多个服务器的地址(即ZooKeeper Quorum)。

  • 当客户端第一次连接到 ZooKeeper 集群时,它会向集群中的一个节点发起连接,并且从该节点获取到集群的所有节点信息。
  • 这个信息会缓存在客户端,并在连接断开时用来进行重新连接

总结来说,ZooKeeper 集群的 IP 地址和端口号通常是在客户端初始化时由配置文件提供的,客户端并不需要在运行时从 ZooKeeper 主动获取新的服务器地址。ZooKeeper 的客户端库会自动处理断线后的重连逻辑,并使用缓存的服务器地址进行重新连接。

4. 在rpc远程过程调用框架中使用zookeeper做服务注册,比如login方法仅配置在服务器1上,将该方法注册到zookeeper上成为rpc远程方法,此时客户端a请求login方法。但请求过程中客户端a与服务器1连接断开,此时客户端还能调用login方法吗?

  1. 服务注册过程:服务器 1 启动时,会将 login 方法注册到 ZooKeeper 上,表示服务器 1 提供 login 服务。

  2. 客户端调用过程:客户端 A 在调用 login 方法时,首先需要从 ZooKeeper 查询提供 login 服务的服务器节点,即服务器 1 的信息。之后,客户端 A 会直接与服务器 1 建立连接并发起 RPC 调用。

  3. 连接断开场景:如果在调用过程中,客户端 A 与服务器 1 的连接断开:

    • 短期断开:如果只是短暂的网络问题,客户端可能会在重试机制下重新发起请求,只要服务器 1 还存活并继续提供 login 服务,客户端 A 还能重新连接并调用 login 方法。
    • 服务器宕机:如果服务器 1 出现故障并下线,ZooKeeper 会自动感知到该节点不可用了,并将其从服务列表中移除。在这种情况下,客户端 A 将无法继续调用 login 方法,除非有其他服务器提供 login 服务。

总结来说,如果客户端 A 与服务器 1 的连接断开,而 ZooKeeper 中没有其他提供 login 服务的节点,客户端 A 将无法继续调用该方法,除非服务器 1 恢复服务或者新的服务器注册了相同的方法。

5. 说一下zk的容灾

ZooKeeper 的容灾机制依赖于集群的部署,通过多节点集群来实现高可用性和故障恢复。单个 ZooKeeper 节点无法提供可靠的容灾能力,因此生产环境中通常会部署 ZooKeeper 集群,具体机制如下:

  1. 集群部署: ZooKeeper 通常被部署为一个 集群(ensemble),集群中的多个节点(通常是奇数个节点,如 3、5、7 个)共同协作,以保证服务的高可用性。当某些节点宕机时,集群仍然可以继续提供服务。

  2. 选举机制: ZooKeeper 使用分布式一致性算法,在集群中选举一个Leader节点,其他节点作为FollowerLeader 负责处理请求并将更改同步到 Follower,所有的读取请求可以从 Leader 或 Follower 中读取

  3. 故障恢复

    • 当某个节点宕机时,集群中的其他节点依然可以提供服务,只要大多数节点(即集群中的 过半节点)仍然存活,ZooKeeper 就能正常运行。
    • 如果 Leader 节点宕机,集群会通过选举机制自动选出一个新的 Leader,继续处理请求。整个选举过程是自动的,通常对外部透明,不需要人工干预。
  4. 数据一致性: 为了保证数据一致性,ZooKeeper 的写操作需要通过 Leader 进行,并且在写入数据时,Leader 会将数据同步到多数 Follower,确保在部分节点故障的情况下,数据不会丢失。

容灾的关键点

  • 多节点部署:ZooKeeper 集群至少需要 3 个节点来提供容灾能力。如果是 1 个节点的部署,那么该节点宕机后,服务将不可用。
  • 节点容错:如果集群中宕机的节点数量没有超过集群中的过半节点,ZooKeeper 仍然可以正常工作。例如,在 5 个节点的集群中,允许最多 2 个节点同时出现故障。
  • 网络分区处理:ZooKeeper 可以通过其一致性协议处理网络分区问题,确保只有能够与集群中多数节点通信的那部分继续对外提供服务,从而避免“脑裂”问题。

因此,ZooKeeper 的高可用性和容灾能力是基于集群部署和多数节点存活的机制来实现的,单个节点的 ZooKeeper 无法保证这一点。

6. 为什么消息队列不用kafka而用redis,可以实现类似功能的还有什么?

MongDB, RabbitDB,ActiveDB,kafka

对于RabbitMQ和Redis的入队和出队操作,各执行100万次,每10万次记录一次执行时间。测试数据分为128Bytes、512Bytes、1K和10K四个不同大小的数据。实验表明:入队时,当数据比较小时Redis的性能要高于RabbitMQ,而如果数据大小超过了10K,Redis则慢的无法忍受;出队时,无论数据大小,Redis都表现出非常好的性能,而RabbitMQ的出队性能则远低于Redis。 

Redis

一些不足

  1. 消息持久化:redis是内存数据库,虽然有aof和rdb两种机制进行持久化,但这只是辅助手段,这两种手段都是不可靠的。当redis服务器宕机时一定会丢失一部分数据,这对于很多业务都是没法接受的。
  2. 热key性能问题:不论是用codis还是twemproxy这种集群方案,对某个队列的读写请求最终都会落到同一台redis实例上,并且无法通过扩容来解决问题。如果对某个list的并发读写非常高,就产生了无法解决的热key,严重可能导致系统崩溃。
  3. 没有确认机制:每当执行rpop消费一条数据,那条消息就被从list中永久删除了。如果消费者消费失败,这条消息也没法找回了。你可能说消费者可以在失败时把这条消息重新投递到进队列,但这太理想了,极端一点万一消费者进程直接崩了呢,比如被kill -9
  4. 不支持多订阅者:一条消息只能被一个消费者消费,rpop之后就没了。如果队列中存储的是应用的日志,对于同一条消息,监控系统需要消费它来进行可能的报警,BI系统需要消费它来绘制报表,链路追踪需要消费它来绘制调用关系……这种场景redis list就没办法支持了。
  5. 不支持二次消费:一条消息rpop之后就没了。如果消费者程序运行到一半发现代码有bug,修复之后想从头再消费一次就不行了。

Kafka
Kafka是Apache下的一个子项目,是一个高性能跨语言分布式发布/订阅消息队列系统,具有以下特性:快速持久化,可以在O(1)的系统开销下进行消息持久化高吞吐,在一台普通的服务器上既可以达到10W/s的吞吐速率;完全的分布式系统,Broker、Producer、Consumer都原生自动支持分布式,自动实现负载均衡;支持Hadoop数据并行加载,对于像Hadoop的一样的日志数据和离线分析系统,但又要求实时处理的限制,这是一个可行的解决方案。Kafka通过Hadoop的并行加载机制统一了在线和离线的消息处理。Apache Kafka相对于ActiveMQ是一个非常轻量级的消息系统,除了性能非常好之外,还是一个工作良好的分布式系统。kafka支持多订阅者和二次消费。

不足

  • 无法弹性扩容:对partition的读写都在partition leader所在的broker,如果该broker压力过大,也无法通过新增broker来解决问题;
  • 扩容成本高:集群中新增的broker只会处理新topic,如果要分担老topic-partition的压力,需要手动迁移partition,这时会占用大量集群带宽;
  • 消费者新加入和退出会造成整个消费组rebalance:导致数据重复消费,影响消费速度,增加e2e延迟;
  • partition过多会使得性能显著下降:ZK压力大,broker上partition过多让磁盘顺序写几乎退化成随机写。

4. RPC和HTTP的区别 

1. 传输协议:
RPC:可以基于TCP也可以基于HTTP。
HTTP:基于HTTP。

2. 传输效率:
RPC:使用自定义的TCP协议,可以让请求报文体积更小,或者使用HTTP2协议,也可以很好的减少报文的体积,提高传输效率。
HTTP:如果是基于HTTP1.1的协议,请求中会包含很多无用的内容,如果是基于HTTP2.0,那么简单的封装以下是可以作为一个RPC来使用的,这时标准RPC框架更多的是服务治理。

3. 性能消耗,主要在于序列化和反序列化的耗时:
RPC:可以基于protobuf实现高效的二进制传输。
HTTP:大部分是通过json来实现的,字节大小和序列化耗时都比protobuf要更消耗性能。

4. 负载均衡:
RPC:基本都自带了负载均衡策略。
HTTP:需要配置Nginx,HAProxy来实现。

5. 服务治理(下游服务新增,重启,下线时如何不影响上游调用者):
RPC:能做到自动通知,不影响上游。
HTTP:需要事先通知,修改Nginx/HAProxy配置。

5. epoll的底层实现?

epoll最详细的介绍以及与epoll相关的问答题_epoll机制中最核 的数据结构-CSDN博客

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值