消息队列高手课
ZooKeeper 作为一个分布式的协调服务框架,主要用来解决分布式集群中,应用系统需要面对的各种通用的一致性问题。ZooKeeper 本身可以部署为一个集群,集群的各个节点之间可以通过选举来产生一个 Leader,选举遵循半数以上的原则,所以一般集群需要部署奇数个节点。
ZooKeeper 最核心的功能是,它提供了一个分布式的存储系统,数据的组织方式类似于 UNIX 文件系统的树形结构。
临时节点和 Watcher 机制
在这个树形的存储结构中,每个节点被称为一个“ZNode”。
ZooKeeper 提供了一种特殊的 ZNode 类型:临时节点。这种临时节点有一个特性:如果创建临时节点的客户端与 ZooKeeper 集群失去连接,这个临时节点就会自动消失。在 ZooKeeper 内部,它维护了 ZooKeeper 集群与所有客户端的心跳,通过判断心跳的状态,来确定是否需要删除客户端创建的临时节点。
ZooKeeper 还提供了一种订阅 ZNode 状态变化的通知机制:Watcher,一旦 ZNode 或者它的子节点状态发生了变化,订阅的客户端会立即收到通知。
Kafka 在 ZooKeeper 中保存的信息
- 左侧这棵树保存的是 Kafka 的 Broker 信息,
/brokers/ids[0…N]
- 每个临时节点对应着一个在线的 Broker,Broker 启动后会创建一个临时节点,代表 Broker 已经加入集群可以提供服务了,节点名称就是 BrokerID,节点内保存了包括 Broker 的地址、版本号、启动时间等等一些 Broker 的基本信息
- 如果 Broker 宕机或者与 ZooKeeper 集群失联了,这个临时节点也会随之消失
- 右侧部分的这棵树保存的就是主题和分区的信息。
/brokers/topics/
节点下面的每个子节点都是一个主题,节点的名称就是主题名称- 每个主题节点下面都包含一个固定的 partitions 节点,pattitions 节点的子节点就是主题下的所有分区,节点名称就是分区编号
图中圆角的矩形是临时节点,直角矩形是持久化的节点。
![Kafka 客户端如何找到对应的 Broker?](Kafka 客户端如何找到对应的 Broker?)
ZooKeeper 也并不是完美的,在使用的时候你需要注意几个问题:
- 不要往 ZooKeeper 里面写入大量数据
- 它不是一个真正意义上的存储系统,只适合存放少量的数据。
- 依据服务器配置的不同,ZooKeeper 在写入超过几百 MB 数据之后,性能和稳定性都会严重下降
- 不要让业务集群的可用性依赖于 ZooKeeper 的可用性
- 你的系统可以使用 Zookeeper,但你要留一手,要考虑如果 Zookeeper 集群宕机了,你的业务集群最好还能提供服务
- 因为 ZooKeeper 的选举过程是比较慢的,而它对网络的抖动又比较敏感,一旦触发选举,这段时间内的 ZooKeeper 是不能提供任何服务的
后端技术面试 38 讲
但是对于写操作,缓存是无能为力的。虽然缓存的写入速度也很快,但是通常情况下,我们不能把用户提交的数据直接写入缓存中,因为缓存通常被认为是一种不可靠的存储。缓存通常无法保证数据的持久性和一致性等这些数据存储的基本要求,因此数据写操作还是需要写入到 RDBMS 或者 NoSQL 数据库中,但是数据库操作通常都比较慢。
消息队列实现异步架构是目前互联网应用系统中一种典型的架构模式。所谓异步架构是和同步架构相对应的。
- 同步架构是说,当应用程序调用服务的时候,当前程序需要阻塞等待服务完成,返回服务结果后才能继续向下执行
典型的消息队列异步架构如下:
消息队列异步架构的主要角色包括消息生产者、消息队列和消息消费者。
- 消息生产者通常就是主应用程序,生产者将调用请求封装成消息发送给消息队列
- 此外还需要开发一个专门的消息消费者程序,用来从消息队列中获取、消费消息,由消息消费者完成业务逻辑处理
- 消息队列的职责就是缓冲消息,等待消费者消费。
- 根据消息消费方式又分为点对点模式和发布订阅模式两种。
点对点模式
多个消息生产者向消息队列发送消息,多个消息消费者消费消息,每个消息只会被一个消息消费者消费。
发布订阅模式
开发者可以在消息队列中设置主题,消息生产者的消息按照主题进行发送,多个消息消费者可以订阅同一个主题,每个消费者都可以收到这个主题的消息拷贝,然后按照自己的业务逻辑分别进行处理计算。
发布订阅模式下,一个主题可以被重复订阅,所以如果需要扩展功能,可以在对当前的生产者和消费者都没有影响的前提下,增加新的消费者订阅同一个主题即可。
消息队列异步架构的好处
- 改善写操作请求的响应时间
- 使用消息队列,生产者应用程序只需要将消息发送到消息队列之后,就可以继续向下执行了,无需等待耗时的消息消费处理
- 更容易进行伸缩
- 削峰填谷
- 互联网应用的访问压力随时都在变化,系统的访问高峰和低谷的并发压力可能也有非常大的差距
- 如果按照压力最大的情况部署服务器集群,那么服务器在绝大部分时间内都处于闲置状态
- 利用消息队列,我们可以将需要处理的消息放入消息队列,而消费者可以控制消费速度,因此能够降低系统访问高峰时压力,而在访问低谷的时候还可以继续消费消息队列中未处理的消息,保持系统的资源利用率
- 隔离失败
- 使用消息队列,生产者发送消息到消息队列后就继续自己后面的计算,消费者如果在处理消息的过程中失败,不会传递给生产者,应用程序具有更高的可用性。
- 降低耦合