目录
- [1 跨集群镜像的应用场景](#1 跨集群镜像的应用场景)
-
- [1.1 区域集群和中心集群](#1.1 区域集群和中心集群)
- [1.2 高可用(HA)和灾备(DR)](#1.2 高可用(HA)和灾备(DR))
- [1.3 监管与合规](#1.3 监管与合规)
- [1.4 云迁移](#1.4 云迁移)
- [1.5 聚合边缘集群的数据](#1.5 聚合边缘集群的数据)
- [2 多集群架构](#2 多集群架构)
-
- [2.1 星型架构](#2.1 星型架构)
- [2.2 双活架构](#2.2 双活架构)
- [2.2 主备架构](#2.2 主备架构)
-
- [2.2.1 如何实现Kafka集群的故障转移](#2.2.1 如何实现Kafka集群的故障转移)
-
- [2.2.1.1 故障转移包括的内容](#2.2.1.1 故障转移包括的内容)
-
- [1. 灾难恢复计划](#1. 灾难恢复计划)
- [2. 非计划内的故障转移导致的数据丢失和不一致性](#2. 非计划内的故障转移导致的数据丢失和不一致性)
- [3. 故障转移之后的起始偏移量](#3. 故障转移之后的起始偏移量)
-
- [1. 偏移量自动重置](#1. 偏移量自动重置)
- [2. 复制偏移量主题](#2. 复制偏移量主题)
- [3. 基于时间的故障转移](#3. 基于时间的故障转移)
- [4. 偏移量映射](#4. 偏移量映射)
- 4.故障转移之后
- [5. 关于集群发现](#5. 关于集群发现)
- [6. 定期演练](#6. 定期演练)
- [2.3 延展集群](#2.3 延展集群)
- [2.4 2.5数据中心架构](#2.4 2.5数据中心架构)
- [3 MirrorMaker](#3 MirrorMaker)
-
- [3.1 配置MirrorMaker](#3.1 配置MirrorMaker)
-
- [3.1.1 配置复制流](#3.1.1 配置复制流)
- [3.1.2 要镜像的主题](#3.1.2 要镜像的主题)
- [3.1.3 消费者偏移量的迁移](#3.1.3 消费者偏移量的迁移)
- [3.1.4 主题配置信息和ACL的迁移](#3.1.4 主题配置信息和ACL的迁移)
- [3.1.5 连接器任务](#3.1.5 连接器任务)
- [3.1.6 参数的前缀](#3.1.6 参数的前缀)
- [3.2 多集群复制拓扑](#3.2 多集群复制拓扑)
- [3.3 保护MirrorMaker](#3.3 保护MirrorMaker)
- [3.4 在生产环境中部署MirrorMaker](#3.4 在生产环境中部署MirrorMaker)
-
- [3.4.1 部署](#3.4.1 部署)
- [3.4.2 监控](#3.4.2 监控)
-
- [Connect 监控](#Connect 监控)
- [MirrorMaker 指标监控](#MirrorMaker 指标监控)
- 延迟监控
- 生产者和消费者的指标监控
- 金丝雀验证
- [3.4.3 MirrorMaker调优](#3.4.3 MirrorMaker调优)
-
- 单实例调优
- 多实例
- 网络调优
- MirrorMaker中的生产者和消费者进行调优
-
- [linger.ms fo batch.size](#linger.ms fo batch.size)
- max.in.flight.requests.per.connection
- fetch.max.bytes
- [fetch.min.bytes 和 fetch.max.wait.ms](#fetch.min.bytes 和 fetch.max.wait.ms)
- [4 附录](#4 附录)
-
- [4.1 灾备恢复](#4.1 灾备恢复)
-
- [4.1.1 灾难恢复计划](#4.1.1 灾难恢复计划)
- [4.1.2 灾备恢复的衡量指标](#4.1.2 灾备恢复的衡量指标)
-
- [4.1.2.1 核心指标](#4.1.2.1 核心指标)
- [4.1.2.2 其他指标](#4.1.2.2 其他指标)
- [4.1.3 灾备恢复的三个层次](#4.1.3 灾备恢复的三个层次)
- [4.1.4 国际标准SHARE78的七级灾备](#4.1.4 国际标准SHARE78的七级灾备)
- [4.2 Kafka灾备恢复架构实例](#4.2 Kafka灾备恢复架构实例)
-
- [4.2.1 架构简介](#4.2.1 架构简介)
- [4.2.2 Kafka故障转移流程](#4.2.2 Kafka故障转移流程)
-
- [4.2.2.1 手动切换](#4.2.2.1 手动切换)
- [4.2.2.2 自动切换](#4.2.2.2 自动切换)
- [4.2.2.3 故障回切](#4.2.2.3 故障回切)
- [4.2.3 相关知识](#4.2.3 相关知识)
-
- [4.2.3.1 Big-IP GTM](#4.2.3.1 Big-IP GTM)
- [4.2.3.2 BIG-IP DNS](#4.2.3.2 BIG-IP DNS)
- [4.2.3.3 BIG-IP LTM](#4.2.3.3 BIG-IP LTM)
- [4.3 基于VIP的高可用](#4.3 基于VIP的高可用)
-
- [4.3.1 Keeplived](#4.3.1 Keeplived)
- [4.3.2 LVS](#4.3.2 LVS)
- [4.3.3 VRRP](#4.3.3 VRRP)
在某些场景下,可能要用到多个Kafka集群。因为 复制(replication) 一词已经被用来描述在同一集群的不同节点之间移动数据,所以可以把几圈见得数据复制叫做 镜像(mirroring) 。Kafka内置的跨集群镜像工具叫做 MirrorMaker 。
1 跨集群镜像的应用场景
1.1 区域集群和中心集群
有时候,一家公司会有多个数据中心,分别分布在不同的地理区域、城市或大洲。这些数据中心都有自己的Kafka集群。有些应用程序只需要与本地的Kafka集群通信,有些应用程序则需要访问多个数据中心里的数据(否则就没必要考虑跨数据中心了)。
1.2 高可用(HA)和灾备(DR)
一个Kafka集群已经可以满足所有应用程序的需求,但你担心集群会因某些原因变得不可用。为了实现冗余,你希望有第二个Kafka集群,该集群的数据与第一个集群
同,如果发生紧急情况,则可以将应用程序重定向到第二个集群。
1.3 监管与合规
为了符合不同国家的法律和监管要求,一家公司在不同国家的运营可能需要不同的和
和策略。例如,一些数据可能需要被保存在具有严格访问控制的独立集群中,
则可以被复制到具有宽松访问权限的其他集群。为了满足不同区域对数据保留期限的么规性要求,保存在不同区域集群中的数据可以使用不同的配置。
1.4 云迁移
现如今,很多公司会将它们的业务同时部署在本地数据中心和云端。为了实现冗余,应用程序通常会运行在云供应商的多个服务区域,或使用多个云供应商提供的云服务。本地数据中心和每个云服务区域都至少有一个Kafka集群。本地数据中心和云服务区域中的应用程序通过这些Kafka集群在数据中心之间传输数据。例如,云端部署了一个应用程序,它需要访问本地数据中心里的数据。本地应用程序负责更新这些数据,并保存在本地数据库中。可以用Connect捕获这些数据库变更,先把它们保存在本地Kafka集群,然后再镜像到云端的Kafka集群,让云端的应用程序可以访问这些数据。这样既有助于控制跨数据中心的流量成本,也有助于提高流量的监管合规性和安全性。
1.5 聚合边缘集群的数据
一些行业,包括零售、电信、运输和医疗保健等,它们会收集小型设备生成的数据。这些设备使用的是受限的网络连接。大量的边缘集群会将收集到的数据聚合到一个高可用的聚合集群中。这些数据将被用于数据分析和其他用途。这种架构降低了对边缘集群(如物联网)在连通性、可用性和持久性方面的要求。即使边缘集群离线,高可用聚合集群仍然能够保证业务的连续性,并能够简化应用程序开发,无须直接与大量具有不稳定网络连接的边缘集群通信。
2 多集群架构
以下是在进行跨数据中心通信时需要考虑的一些问题:
- 高延迟
Kafka集群之间的通信延迟会随着集群间距离的增长和网络跳转次数的增加而增加。 - 有限带宽
单个数据中心的广域网带宽远比我们想象的要低得多,而且可用的带宽时刻在发生变化。另外,高延迟让带宽的充分利用变得更加困难。 - 高成本
不管是在本地还是在云端运行Kafka,集群之间的通信都需要更高的成本。
多集群的架构原则:
- 每个数据中心至少要有一个集群。
在这些集群间复制数据,而不是让应用程序直接通过广域网访问另一个数据中心里的数据。Kafka 服务器和客户端的设计、开发、测试以及调优都以单个数据中心为基础。因此,不建议将Kafka集群的一部分服务器安装在一个数据中心里,另一部分安装在另一个数据中心里(不过稍后将介绍一些例外情况)。 - 每两个数据中心之间的数据复制要做到每个事件仅复制一次(除非出现错误需要重试)。
- 如果有可能,那么尽量从远程数据中心读取数据,而不是向远程数据中心写入数据。
这是最安全的跨集群通信方式。在发生网络分区时,消费者无法从Kafka读取数据,但数据仍然驻留在Kafka中,当通信恢复正常时,消费者就可以继续读取数据。因此,网络分区不会造成数据丢失。
2.1 星型架构
这种架构适用于一个中心Kafka集群对应多个本地Kafka集群的情况。
应用场景:
- 当数据分散在多个数据中心而消费者需要访问全部数据时,可以使用这种架构。
- 如果每个数据中心的应用程序只访问自己所在数据中心的数据,那么也可以使用这种架构。但它不允许从每个数据中心访问整个数据集。
好处:
- 数据只会生成到本地的数据中心,并且每个数据中心的数据只会被镜像到中央数据中心一次。
- 只读取单个数据中心数据的应用程序可以被部署在本地数据中心里,需要读取全部数据的应用程序则可以被部署在中央数据中心里。
- 因为数据复制是单向的,并且消费者总是从同一个集群读取数据,所以这种架构易于部署、配置和监控。
不足:
- 不过这种简单的架构也有不足的地方,即一个数据中心里的应用程序无法访问另一个数据中心里的数据。
这种架构的简化变种只包含两个集群:一个首领和一个跟随者。
2.2 双活架构
当有两个或多个数据中心需要共享部分或全部数据,并且每个数据中心都可以生成和读取数据时,可以使用双活架构。
如果能够很好地处理多个数据中心在进行异步读写时发生冲突的问题,那么强烈建议使用这种架构。这种架构是我们所知道的最具伸缩性、弹性、灵活性和成本优势的解决方案。
好处:
- 它可以为就近用户提供速度更快的服务,具有性能方面的优势,而且不会因为数据可用性问题(在星型架构中就有这种问题)做出功能方面的牺牲。
- 冗余和弹性。因为每个数据中心都具备完整的功能,所以一旦一个数据中心发生故障,则可以把用户重定向到另一个数据中心。这种故障转移只涉及网络重定向,是一种最简单也最透明的故障转移方案。
不足:
- 如何在多个数据中心进行异步读写时避免冲突。比如,在镜像数据时如何确保同一条消息不会被无止境地来回镜像?在经过数据镜像之后,两个数据中心都有了这两个事件,也可以说两个数据中心都出现了两个冲突事件。应用程序需要知道如何处理这种情况。
- 保证跨数据中心的数据一致性会变得更加困难。
如果用户向一个数据中心发送数据,并从另一个数据中心读取数据,那么在用户读取数据之前,他发送的数据有可能还没有被镜像到那个数据中心。
挑战:
- 双活架构(特别是当数据中心的数量超过两个)的挑战之处在于每两个数据中心都需要进行镜像,而且是双向的。
- 还要避免循环镜像,相同的事件不能无止境地在两个数据中心之间来回镜像,
在Kafka 0.11.0中引入的消息标头可以包含源数据中心的信息,我们既可以使用这些信息来避免循环镜像,也可以用它们来单独处理来自不同数据中心的数据。当然,还可以使用结构化的数据格式(如Avro),在消息里添加标签和标头。
2.2 主备架构
有时候,我们使用多个集群只是为了达到灾备的目的。这是一种合规性需求,业务不一定会将其纳入规划范畴。
- 可以在同一个数据中心安装了两个集群,平常只使用其中一个,第二个集群(几乎)包含了与第一个集群相同的数据,当第一个集群不可用时,就可以使用第二个集群。
- 还可以将两个集群安装在不同地理位置的两个数据中心。
好处:
易于实现,而且可以被应用于任何一种场景中。你只需要安装第二个集群,并使用镜像进程将第一个集群的数据完全镜像到第二个集群中,不需要操心如何访问数据、如何处理冲突,也不需要担心它会带来额外的架构复杂性。
不足:
它浪费了一个集群。
为了减少浪费,有些组织会尝试减小灾备集群的规模,让它远小于生产环境集群的规模。这种做法存在一定的风险,因为你无法保证这种小规模集群能够在紧急情况下发挥应有的作用。
有些组织则倾向于让灾备集群在平常也发挥作用,它们把一些只读工作负载转移到灾备集群中,也就是说,它们实际上运行的是星型架构的一个简化版本(只有一个Spoke)。
目前,要实现完全不丢失数据或无重复数据的Kafka集群故障转移是不可能的,更为常见的情况是既丢失数据,又出现重复数据。我们只能尽量减少这些问题的发生,但无法完全避免。
2.2.1 如何实现Kafka集群的故障转移
2.2.1.1 故障转移包括的内容
1. 灾难恢复计划
灾难恢复计划 (DRP) 是一份详细的文档,概述了组织将如何应对计划外事件。除了业务连续性计划 (BCP) 和事件响应计划 (IRP) 外,灾难恢复计划还有助于确保企业准备好面对许多不同类型的灾难,包括停电、勒索软件和恶意软件攻击、自然灾害等等。
相关术语:
- 故障转移(failover)
故障转移是一种广泛使用的过程,当主系统因停电、网络攻击或其他威胁而出现故障时,IT操作会转移到辅助系统。 - 故障回切(failback)
故障回切是指原始系统恢复后切换回原始系统的过程。
在进行灾难恢复计划时,必须考虑两个关键指标:
- 恢复时间目标(recovery timeobjective,RTO)
RTO是指灾难发生后,从IT系统崩溃导致业务停顿开始,到IT系统完全恢复,业务恢复运营为止的这段时间长度。RTO用于衡量业务从停顿到恢复的所需时间。
RTO越低,就越要避免采用人工操作流程,因为只有自动化故障转移才能实现非常低的RTO。 - 恢复点目标(recovery point objective,RPO)
IT系统崩溃后,可以恢复到某个历史时间点,从历史时间点到灾难发生的时间点的这段时间长度就称为RPO。RPO用于衡量业务恢复所允许丢失的数据量。
低RPO需要低延迟的实时镜像,如果要求RPO为零,则需要进行同步复制。
灾备恢复介绍:
https://blog.csdn.net/yunyun1886358/article/details/135735006
2. 非计划内的故障转移导致的数据丢失和不一致性
因为Kafka的各种镜像解决方案都是异步的(后面将介绍一种同步的解决方案),所以灾备集群将无法及时获取主集群的最新数据。
监控灾备集群偏移量延迟
我们需要时刻注意灾备集群落后了主集群多少,并确保不要让它落后太多。但是,在一个繁忙的系统中,灾备集群与主集群之间可能有几百条甚至几千条消息的延迟。
计划内的故障转移
如果有故障转移计划,则可以:
- 先停止主集群,等待镜像进程将剩余数据镜像完毕。
- 然后再切换到灾备集群,这样可以避免数据丢失。
非计划内的故障转移
如果发生了非计划内的故障转移,则可能会丢失数千条消息。需要注意的是,目前镜像解决方案还不支持事务,也就是说,如果多个主题(比如保存销售数据的主题和保存产品数据的主题)之间有相关性,那么在故障转移过程中,有些数据可能可以及时到达灾备集群,有些则不能。在切换到灾备集群之后,应用程序需要知道如何处理没有相关销售信息的产品数据。
3. 故障转移之后的起始偏移量
在切换到灾备集群的过程中,最具挑战性的事情莫过于让应用程序知道该从哪里开始处理数据。
1. 偏移量自动重置
Kafka消费者有一个配置参数auto.offset.reset用于指定在没有前一个提交偏移量的情况下该作何处理。
如果灾备进化里面么有镜像偏移量,那么就要二者选其一:
- earlist,从头开始读取数据,并处理大量的重复数据。
- latest,直接跳到末尾,放弃一些数据(希望不会太多)。
如果重复处理数据或者丢失一些数据不是大问题,那么这种方案就是目前为止最为简单的。一般来说,在故障转移之后直接从主题末尾开始读取数据的方式更为常见。
2. 复制偏移量主题
如果你使用的是0.9.0及以上版本的Kafka消费者,那么它会把偏移量提交到一个叫作__consumer_offsets的主题上。如果你将这个主题镜像到了灾备集群,那么当消费者开始读取灾备集群时,就可以获取到原先的偏移量,并从这个位置开始处理数据。
这看起来很简单,但仍然有很多需要注意的地方:
- 我们并不能保证主集群中的偏移量与灾备集群中的偏移量是完全匹配的。
- 就算在主题创建之后立即镜像数据,并且主集群和灾备集群的偏移量都从0开
始,当生产者需要重试发送消息时仍然会造成偏移量偏离。 - 就算偏移量被完美地保留下来,因为主集群和灾备集群之间存在延迟以及目前的镜像方案不支持事务,消费者提交的偏移量仍有可能在记录之前或者之后到达。
在发生故障转移之后,消费者可能会找不到与偏移量匹配的记录,或者灾备集群中的偏移量会比主集群中的偏移量小。
3. 基于时间的故障转移
从Kafka 0.10.0开始,每条消息里都包含了一个时间戳 -- 消息发送给Kafka的时间。
从Kafka 0.10.1.0开始,broker提供了一个索引和可根据时间戳查找偏移量的API。
如何让消费者特定时间的位置开始处理数据:
-
在应用程序中完成。
我们为用户提供一个配置参数,用于指定从什么时间点开始处理数据。如果用户指定了时间,那么应用程序就可以通过新API获取指定时间戳对应的偏移量,然后从这个位置开始处理数据。
如果应用程序一开始就是这么设计的,那么使用这种方案就再好不过了。 -
kafka-consumer-groups工具。
我们可以用它基于一些参数来重置偏移量,包括在Kafka 0.11.0中引入的基于时间戳的偏移量重置。在使用这个工具时,需要先停止消费者群组,等工具运行完毕之后再立即启动。
例如,下面的命令会将某个消费者群组订阅的所有主题的偏移量都重置到指定的时间。bashbin/kafka-consumer-groups.sh -- bootstrap-server localhost:9092 -- reset- offsets -- all-topics -- group my-group -- to-datetime 2021-03-31T04:03:00.000 -- execute ```
这个方案适用于在发生故障转移时需要保证一定确定性的场景。
4. 偏移量映射
镜像偏移量主题的一个最大问题在于主集群和灾备集群的偏移量会发生偏离。在过去,一些组织会选择使用外部数据存储(如Apache Cassandra)来保存集群之间的偏移量对关系。每当一个事件被发送到灾备集群时,镜像工具会将两个集群的偏移量都发计动外部存储。现在的镜像解决方案(包括MirrorMaker)会使用Kafka主题来保存偏秋映射关系(只保留偏移量差值的变化,而不是保留每一个映射)。对于那些比记录先达到的偏移量或没有及时被镜像到灾备集群的偏移量,仍然会有问题,不过这至少已经覆盖了部分场景。
4.故障转移之后
假设故障转移进行得很顺利,灾备集群也运行得很正常,现在需要对主集群做一些改动,把它变成灾备集群。
如果能够简单地改变镜像进程的方向,让它将数据从新主集群镜像到旧主集群,那么就完美了。不过,这里有两个问题。
- 怎么知道该从哪里开始镜像呢?我们需要解决与镜像应用程序消费者所面临问题同样的问题。而且不要忘了,所有的解决方案都有可能导致数据丢失或重复,或两者兼有。
- 另外,正如之前所讨论的那样,旧主集群中可能有一些数据没有被镜像到新主集群中,如果这个时候开始镜像新主集群的数据,那么历史遗留数据会继续留在旧主集群中,导致两个集群的数据不一致。
因此,如果要保证数据的一致性和顺序,最简单的解决方案是清理旧主集群,删掉所有
数据和偏移量,然后从新主集群中把数据镜像回来。这样可以获得与新主集群一致的数据状态。
5. 关于集群发现
在设计灾备集群时,需要考虑的一个很重要的问题是在发生故障转移之后,应用程序如何与灾备集群通信。如果把主集群的主机名硬编码在生产者和消费者的配置文件中,就会很麻烦。为简单起见,大多数组织使用了DNS,并将其指向主集群,一旦发生紧急情况,则可以将其指向灾备集群。这些服务发现工具(DNS或其他)不需要包含所有broker的信息,只要Kafka客户端能够连接到其中一个broker,就可以获取整个集群的元数据,并发现集群中的其他broker。一般来说,提供3个broker的信息就可以了。不管使用哪种服务发现工具,在大多数情况下需要重启消费者,这样才能找到新的偏移量,并继续读取数据。对于为降低RTO而使用自动故障转移的场景,需要将故障转移处理逻辑放在客户端应用程序中。
6. 定期演练
不管选择哪一种故障转移方案,SRE团队都必须定期进行验证。
SRE工程师(Site Reliability Engineer) 是负责确保网站和应用程序的可靠性、稳定性和可伸缩性的工程师。他们通常需要具备深厚的系统和网络知识,能够编写自动化脚本和工具来管理和监控大规模的系统。
SRE工程师的主要职责包括:
- 设计、构建和维护高可靠性的系统架构
- 开发自动化工具和脚本来提高系统的稳定性和可维护性
- 监控系统性能,并进行故障排除和性能优化
- 参与容量规划和系统扩展
- 与开发团队合作,确保新功能的上线不会影响系统的稳定性
Chaos Monkey是Netflix开发的一款著名的故障注入工具,它会随机地制造灾难,有可能让任何一天都成为故障转移日。
2.3 延展集群
延展集群是指跨多个数据中心的Kafka集群。而当其中部分数据中心发生故障时,延展集群(stretch cluster)可以保证Kafka集群仍然可用。
延展集群与其他类型的跨数据中心集群有本质上的区别:
- 延展集群并非多个集群,而是单个集群,因此不需要使用镜像进程。
- 延展集群使用Kafka内置的复制机制来保持broker副本的同步。这里可以使用同步复制。生产者通常会在消息成功写入Kafka之后收到确认。在延展集群中,也可以配置类似的参数,在消息被写入两个数据中心的broker之后发送确认。
- 这还包括使用机架信息确保每个分区在其他数据中心都有相应的副本,并配置min.insync.replicas和acks=all,以确保每次写入消息时都可以收到来自至少两个数据中心的确认。从Kafka 2.4.0开始,消费者可以基于机架信息从最近的副本获取数据。
broker会检查自己的机架信息与消费者的机架信息,以便找到最新的本地副本,如果本地副本不可用,就从首领副本读取。从本地数据中心的跟随者副本读取数据可以提高吞吐量、降低延迟和成本,因为跨数据中心的流量减少了。
优势:
- 同步复制是这种架构的最大优势。有些类型的业务要求灾备站点与主站点保100%的同步。这是一种合规性需求,适用于公司内的任何一种数据存储,包括Kafka。
- 这种架构还有一个优势,即两个数据中心及集群内的所有broker都发挥了作用,不会浪费资源。
不足:
- 这种架构的不足之处是它所能应对的灾难类型是有限的。它只能应对数据中心故障,但无法应对应用程序或者Kafka故障。
- 运维复杂性是它的另一个不足之处,它所需要的物理基础设施并不是所有公司都能承担得起的。
如果能够在至少3个具有高带宽和低延迟的数据中心里安装Kafka(包括ZooKeeper),那么就可以使用这种架构。如果你的公司在同一个街区有3栋大楼,或者你的云供应商在同一个地区有3个可用区域,那么就可以考虑使用这种方案。
之所以是3个数据中心,主要是因为ZooKeeper要求集群的节点个数是奇数,并且只有当大多数节点可用时,整个集群才可用。如果只有两个数据中心,并且ZooKeeper的节点是奇数个,那么其中一个数据中心将包含大多数节点,这就意味着如果这个数据中心不可用,那么ZooKeeper和Kafka也不可用。如果有3个数据中心,那么在分配节点时,可以做到每个数据中心都不会包含大多数节点。如果其中一个数据中心不可用,那么其他两个数据中心里还有大多数节点,此时ZooKeeper和Kafka仍然可用。
2.4 2.5数据中心架构
一种比较流行的延展集群模型是2.5数据中心架构,即两个数据中心里都安装了Kafka和ZooKeeper,然后再在另外"半"个数据中心里安装一个ZooKeeper节点,当其中一个数据中心发生故障时,它可以提供仲裁。
3 MirrorMaker
Kafka提供了一个叫作MirrorMaker的工具,用于在两个数据中心之间镜像数据。
MirrorMaker 2.0是Kafka的下一代多集群镜像解决方案,它基于Connect框架,张补了旧版本的很多不足。我们可以很容易地配置出复杂的拓扑来支持更为广泛的场景,比如灾难恢复、备份、迁移和数据聚合。
MirrorMaker看起来很简单,但因为我们想要做到既高效又非常接近精确一
次传递,所以其实现起来是很困难的。
MirrorMaker 使用源连接器来读取另一个Kafka集群而不是数据库的数据。Connect框架的使用减轻了企业IT部门管理Kafka的负担。
- 在MirrorMaker中,每个Connect任务对应一个消费者和一个生产者。
- Connect框架会根据需要将这些任务分配给不同的Connect工作节点,所以一台服务器上可能有多个任务,或者任务可能会被分散到多台服务器上。这样就无须手动计算每个实例要运行多少个MirrorMaker以及每台机器要运行多少个实例。
- Connect还提供了用于集中管理连接器和任务配置的REST API。
- 假设大多数Kafka集群因为某些原因而启用了Connect(将数据库变更事件发送到Kafka就是一个常见的场景),那么,在Connect内部运行MirrorMaker就可以减少需要管理的集群的数量。
- 为避免在添加新主题或分区时发生再均衡而导致延迟激增,在为任务分配分区时,
MirrorMaker并没有使用Kafka的消费者群组管理协议。源集群每一个分区的事件都会被镜像到目标集群的相同分区,保留语义分区并维护每个分区的事件顺序。如果源主题添加了新分区,那么目标主题也会自动创建对应的分区。 - 除了数据复制,MirrorMaker还支持迁移消费者偏移量、主题配置和主题ACL。这是一种完整的多集群镜像解决方案。
- 从源集群到目标集群的定向流配置叫作复制流。MirrorMaker可以有多个复制流,从而定义出复杂的拓扑,包括前面介绍过的各种架构模式,比如星型模式、主备模式和双活模式。
3.1 配置MirrorMaker
MirrorMaker是高度可配置的。除了用于配置拓扑、Connect和连接器的集群参数,
MirrorMaker 所使用的生产者、消费者和AdminClient的每一个属性都是可配置的。
下面的命令会使用属性文件中指定的配置参数来启MirrorMaker:
bash
bin/connect-mirror-maker.sh etc/kafka/connect-mirror-maker.properties
3.1.1 配置复制流
在两个数据中心之间建立主备复制流的配置参数。
bash
# 定义在复制流中使用的集群的别名。
clusters = PROD, DR
# 配置每个集群的地址,使用集群别名作为前缀。
PROD.bootstrap.servers = kafka.prod.example.com:9092
DR.bootstrap.servers = kafka.dr.example.com:9092
# 使用 source->target这样的前缀配置两个集群之间的复制流。与这个复制流相关的所有配置都使用相同的前缀。
PROD->DR.enabled = true
#配置复制流要镜像的主题。
PROD->DR.topics = .*
3.1.2 要镜像的主题
对于每个复制流,可以使用正则表达式指定需要镜像的主题。上面示例中镜像了每一个主题,但在实际当中,最好使用类似prod .* 这样的表达式,以免镜像了测试主题。
也可以指定要排除的主题或使用类似test .* 这样的表达式来排除不需要镜像的主题。
在默认情况下,目标主题会自动加上源集群别名作为前缀。如果既要将主题从PROD镜像到DR,又要将主题从DR镜像到PROD,那么这种默认命名策略可以防止循环镜像(数据在两个集群之间无休止地来回镜像)。
本地主题和远程主题之间的名称差异并不影响聚合,因为消费者既可以通过正则表达式订阅本地主题,也可以订阅远程主题,以便获得完整的数据集。
MirrorMaker会定期检查源集群是否有新增主题,如果有,并且与指定的模式匹配,就
会自动开始镜像这些主题。如果源主题新增了分区,则目标主题也会自动添加相同数量的分区,确保源主题中的事件在目标主题中以相同的顺序出现在相同的分区中。
3.1.3 消费者偏移量的迁移
MirrorMaker提供了一个叫作RemoteClusterUtils的辅助类,在发生故障转移后,可以用它在灾备集群中找到最后的检查点偏移量。
Kafka 2.7.0支持定时迁移消费者偏移量,它会自动将转换后的偏移量提交到灾备集群的_consumer_offsets主题,消费者在切换到灾备集群后就可以从之前停止的位置重新开始处理数据,不会发生数据丢失。
重复处理消息的可能性降到最低。为安全起见,如果目标集群的消费者正在使用目标消费者群组,那么MirrorMaker就不会覆盖偏移量,从而能够避免出现意外冲突。
3.1.4 主题配置信息和ACL的迁移
除了数据,MirrorMaker也可以镜像主题的配置信息和访问控制列表(ACL)
便保留相同的主题行为。
这个功能默认是启用的,并会以合理的时间间隔刷新。
的大部分配置参数会被应用于目标主题,但有一些参数在默认情况下不会被应用,H
min.insync.replicas。需要排除哪些配置参数可以自行指定。
只有那些与被镜像的主题匹配的字面量ACL会被迁移,因此,如果你使用的是包含备
缀或通配符的ACL或者其他身份验证机制,则需要在目标集群中显式配置。
为了确保只有MirrorMaker能够向目标主题写入数据,Topic:Write权限不会被迁移。在发生故障转移时,必须显式地授予应用程序适当的访问权限,确保它们可以正常访问第二个集群。
3.1.5 连接器任务
参数 tasks.max指定了与MirrorMaker关联的连接器可以使用的最大任务数。默认值
为1,但建议最少将其设置为2。在复制大量的主题分区时,为了增加并行度,应该尽
可能设置更大的值。
3.1.6 参数的前缀
MirrorMaker 支持其所有组件的配置参数定制化,包括连接器、生产者、消费者和管理客户端。Connect和连接器的配置参数可以不带任何前缀。
但是,由于MirrorMaker可以包含多个集群的配置,因此可以使用前缀来指定特定于集群或复制流的配置。之前的示例中是将集群别名作为集群相关配置参数的前缀。
前缀可用在层级结构配置中,包含特定前缀的配置比相对不那么特定或没有前缀的配置具有更高的优先级。
MirrorMaker支持以下这些前缀:
{cluster}. {connector_config}
{cluster}.admin. {admin_config}
{source_cluster}.consumer.{consumer_config}
{target_cluster}.producer.{producer_config}
{source_cluster}->{target_cluster}.{replication_flow_config}
3.2 多集群复制拓扑
前面介绍了一个简单的主备复制流的配置示例,下面来配置双向复制流来支持双活拓扑。
bash
clusters = PROD, DR
PROD.bootstrap.servers = kafka.prod.example.com:9092
DR.bootstrap.servers = kafka.dr.example.com:9092
# 启用从PROD到DR的复制。
PROD->DR.enabled = true
PROD->DR.topics = .*
# 启用从DR到PROD的复制。
DR->PROD.enabled = true
DR->PROD.topics = .*
事件不会在两个集群之间无止境地来回镜像,因为远程主题使用集群别名作为前缀。
议让不同的MirrorMaker进程使用同一个包含完整复制拓扑的配置文件,这样可以避免在使用目标数据中心的内部配置主题共享配置信息时发生冲突。在启动目标数据中心的MirrorMaker 进程时,可以使用 -- clusters选项指定目标集群。
还可以向拓扑中添加更多包含其他源或目标集群的复制流。
bash
clusters = PROD, DR, DR1
DR1.bootstrap.servers = kafka.dr1.example.com:9092
PROD->DR1.enabled = true
PROD->DR1.topics = .*
3.3 保护MirrorMaker
对于生产环境中的集群,需要确保所有的跨数据中心流量都是安全的。
我们必须在源集群和目标集群中使用安全的broker监听器,必须配置集群的客户端安全选项,让MirrorMaker能够使用需要身份验证的安全连接。还需要使用SSL加密所有的跨数据中心通信。
例如,可以像下面这样配置MirrorMaker的密钥凭证。
bash
# 安全协议应该与指定集群所对应的broker监听器的安全协议相匹配,建议使用SS或SASL_SSL。
PROD.security.protocol=SASL_SSL
PROD.sasl.mechanism=PLAIN
# 因为使用了SASL,所以这里需要指定JAAS密钥凭证。如果使用的是SSL,并启用了
双向身份验证,则还需要指定密钥存储文件。
PROD.sasl.jaas.config=org.apache.kafka.common.security.plain.PlainLoginModule \
required username="MirrorMaker" password="MirrorMaker-password";
如果在集群中启用了授权,则必须将源集群和目标集群的一些权限授予MirrorMaker相关的主体。必须为MirrorMaker进程授予以下这些ACL权限。
- 源集群的Topic:Read,这样就可以从源主题读取数据;目标集群的Topic:Create和
Topic:Write,这样就可以创建目标主题并写入数据。 - 源集群的Topic:DescribeConfigs,这样就可以获取源王题的配直信息;目标集群的Topic:AlterConfigs,这样就可以更新目标主题的配置。
- 目标集群的Topic:Alter,如果源主题增加了新分区,就可以在目标集群中也添加相的的分区。
- 源集群的Group:Describe,这样就可以获取包括偏移量在内的源消费者群组的元数握目标集群的Group:Read,这样就可以提交目标消费者群组的偏移量。
- 源集群的Cluster:Describe,这样就可以获取源主题的ACL;目标集群的Cluster:Alter
这样就可以修改目标主题的ACL。 - 源集群和目标集群的Topic:Create和Topic:Write,这样就可以操作MirrorMaker的内部主题。
3.4 在生产环境中部署MirrorMaker
3.4.1 部署
也可以启动任意数量的MirrorMaker进程,让它们形成一个可伸缩、具备容错能力的MirrorMaker集群。镜像到同一集群的进程知道彼此的存在,并会自动进行负载均衡。
通常,在生产环境中,你可能希望将MirrorMaker作为一个后台服务运行,并将控制台输出重定向到日志文件。MirrorMaker提供了一个命令行选项-daemon,我们可以用它来实现在后台运行MirrorMaker。
大多数使用MirrorMaker的公司有自己的启动脚本,脚本中包含了它们使用的配置参数。一些部署系统,比如Ansible、Puppet、Chef和Salt,经常被用于自动部署和管理配置参数。
MirrorMaker也可以运行在Docker容器中。MirrorMaker是完全状态的,不需要磁盘存储(所有的数据和状态都保存在Kafka中)。
因为MirrorMaker是基于Connect的,所以Connect所有的部署模式都可以应用于MirrorMaker。在开发和测试时可以使用独立模式,MirrorMaker将作为一个单独的Connectworker运行在一台机器上。MirrorMaker也可以作为一个连接器运行在分布式Connect集群中。在生产环境中,建议在分布式模式下运行MirrorMaker,既可以是专有的MirrorMaker集群,也可以是共享的分布式Connect集群。
如果有可能,那么尽量让MirrorMaker运行在目标数据中心里。也就是说,如果要将PROD的数据复制到DR,那么MirrorMaker应该运行在DR的数据中心里,并消费PROD数据中心里的数据。这是因为长距离的外部网络比数据中心的内部网络更加不可靠,如果发生了网络分区,数据中心之间断开了连接,那么一个无法连接到集群的消费者要比无法连接到集群的生产者安全得多。如果消费者无法连接到集群,那么最多也就是无法读取数据,数据仍然可以在Kafka集群中保留很长一段时间,不会有丢失的风险。相反,在发生网络分区时,如果MirrorMaker已经读取了数据,但无法将数据生成到目标集群中,则会造成数据丢失。所以说,远程读取数据比远程生成数据更加安全。
本地读取消息并将其生成到远程数据中心的场景:
- 当你要求数据在传输过程中加密但在数据中心里不加密的时候。消费者在使用SSL连接时对性能有一定的影响,而且比生产者要严重得多。这是因为消费者在使用SSL连接时需要复制数据并对其加密,无法享受零复制带来的性能好处。
用这种方式时,需要确保:- MirrorMaker的Connect生产者配置了acks=all和适当的重试次数。
- 可以将MirrorMaker的 errors.tolerance设置为none,让它在出现错误时快速失效,这通常比继续发送事件更为安全。
- 新版本的Java显著提升了SSL性能,所以在本地生成数据和从远程读取数据可能也是一个可行的选择,即使是在使用了加密的情况下。
- 将数据从本地集群镜像到云端集群。出于安全考虑,本地集群可能位于防火墙后面,拒绝来自云端的连接,但在本地运行的MirrorMaker可以连接到云端。
3.4.2 监控
在将MirrorMaker部署到生产环境时,一定要记得监控下面这些内容:
Connect 监控
Connect提供了大量的指标,比如用于监控连接器状态的连接器指标、用于监控吞吐量的源连接器指标,以及用于监控再均衡延迟的worker指标。Connect还提供了一个用于查看和管理连接器的REST API。
MirrorMaker 指标监控
除了Connect提供的指标,MirrorMaker也提供了用于监控镜像吞吐量和复制延迟的指标。复制延迟指标 replication-latency-ms可以告诉我们消息的时间戳与消息被成功写入目标集群时的时间间隔。如果想知道目标集群是否及时跟上了源集群,那么这个指标就非常有用。在高峰时段,如果目标集群有足够的能力赶上源集群,那么即使延迟增加了也没问题,但如果延迟持续增加,则说明目标集群能力不足。
其他指标,比如record-age-ms(在进行镜像时消息的年龄)、byte-rate(镜像吞吐量)和checkpoint-latency-ms(偏移量迁移延迟),也非常有用。在默认情况下,MirrorMaker还会定时发送心跳,我们可以用它来监控MirrorMaker的运行状况。
延迟监控
你肯定想知道目标集群是否落后于源集群。延迟体现在源集群最新偏移量与目标集群最新偏移量的差异上。
以下是两种跟踪延迟的方式,但它们都不完美。
- 检查MirrorMaker提交到源集群的最新偏移量。
可以用Kafka-consumer-groups检查MirrorMaker读取的每一个分区最后一条消息的偏移量、MirrorMake提交的最新偏移量以及它们之间的延迟。不过这个偏移量并不会100%准确,因为MirrorMaker并不会每时每刻都提交偏移量。在默认情况下,它会每分钟提交一次所以,我们可能会在一分钟内看到延迟增加,然后又突然下降。 - 检查MirrorMaker读取的最新偏移量(即使还未提交)。
内嵌在MirrorMaker中的消费者通过JMX发布关键指标,其中的一个指标是消费者最大延迟(基于它读取的所有分区计算得出)。这个延迟也不是100%准确,因为它只反映了消费者已读取的数据,并没有考虑生产者是否成功地将数据发送到目标集群中并收到确认。
需要注意的是,如果MirrorMaker跳过或丢弃了部分消息,则上述的两种方法是无法检测到的,因为它们只跟踪最新的偏移量。
生产者和消费者的指标监控
MirrorMaker所使用的Connect包含了一个生产者和一个消费者,它们提供了很多可用的指标。建议监控这些指标。Kafka的文档列出了所有可用的指标。
下面列出了几个对MirrorMaker 调优非常有用的指标。
- 消费者
fetch-size-avg, fetch-size-max, fetch-rate, fetch-throttle-time-avg fll fetch-
throttle-time-max. - 生产者
batch-size-avg, batch-size-max, requests-in-flight fll record-retry-rate. - 同时适用于两者
io-ratio 和 io-wait-ratio。
金丝雀验证
如果对所有东西都进行了监控,那么金丝雀(canary)验证就不是严格必需的,但为了
实现多层监控,我们还是会进行金丝雀验证。我们每分钟向源集群的某个主题发送一条消息,然后再尝试从目标集群读取这条消息。如果消息在指定的时间之后才到达,就会发出告警,说明MirrorMaker出现了延迟或已经运行不正常了。
3.4.3 MirrorMaker调优
MirrorMaker是水平可伸缩的,集群的大小取决于吞吐量需求和对延迟的容忍度。
如果不能容忍任何延迟,那么MirrorMaker的集群容量就需要满足吞吐量的上限。
如果可以容忍一些延迟,则只要保证在95%-99%的时间里有75%-80%的容量可用即可。
单实例调优
然后,你可能想通过设置不同的连接器任务数(通过tasks.max参数配置)来了解
MirrorMaker的吞吐量。这主要取决于你所使用的硬件、数据中心或云服务供应商,所以需要自己进行测试。Kafka提供了kafka-performance-producer工具,用于在源集群中制造负载,然后启动MirrorMaker镜像这个负载。在测试时,可以分别为MirrorMaker配置1、2、4、8、16、24和32个任务,并观察性能在哪个任务数开始出现下降,然后将tasks.max设置为比这个任务数小的值。
如果你读取或生成的数据是压缩过的(因为网络带宽是跨集群镜像的瓶颈,所以建议将数据压缩后再传输),那么MirrorMaker还需要进行解压缩和再压缩。这会消耗很多CPU资源,所以在增加任务数时,要注意观察CPU的使用情况。通过这种方式你就可以知道单个MirrorMaker实例的最大吞吐量。
多实例
如果单个实例的吞吐量还不够,那么可以测试更多的MirrorMaker实例和服务器。如果运行MirrorMaker的Connect集群中还有其他连接器,那么在调整集群大小时也要将这些连接器的负载考虑在内。
另外,你可能希望使用单独的MirrorMaker集群来镜像包含敏感数据的主题(要求低延迟并且镜像必须尽可能靠近源主题),这样可以避免主题过于臃肿或被失控的生产者拖慢数据管道。
网络调优
如果MirrorMaker是跨数据中心运行的,则可以通过调整TCP栈来增加有效带宽。
可以分别用 send.buffer.bytes 和 receive.buffer.bytes配置生产者和消费者的TCP缓冲区大小。
可以用socket.send.buffer.bytes和 socket.receive.buffer.bytes 配置broker端的缓冲区大小。
这些配置参数需要与Linux网络配置相结合,如下所示。
- 增加TCP缓冲区大小(net.core.rmem_default、net.core.rmem_max、net.core.wmem_default、net.core.wmem_max和net.core.optmem_max)。
- 启用时间窗口自动伸缩(sysctl -w net.ipv4.tcp_window_scaling=1或者在/etc/sysctl.conf中添加 net.ipv4.tcp_window_scaling=1)。
- 减少TCP慢启动时间(将/proc/sys/net/ipv4/tcp_slow_start_after_idle设为0)。
需要注意的是,Linux网络调优包含了太多的内容。
MirrorMaker中的生产者和消费者进行调优
首先,需要知道生产者或消费者是不是瓶颈所在,即生产者是否在等待消费者提供更多的数据,或者消资者在等待生产者提供更多的数据。
- 一种办法是查看生产者和消费者的指标。如果其中一万空闲,而另一方很繁忙,那么就知道哪个需要调优了。
- 另外一种办法是查看线程转储。(可以使用jstack获得线程转储)。
如果MirrorMaker的大部分时间用在轮询上,那么说们消费者是瓶颈所在,如果MirrorMaker的大部分时间用在发送消息上,则说明生产者时瓶颈所在。
可以使用下面的配置参数进行调优:
linger.ms fo batch.size
如果你发现生产者总是发送未被填满的批次(指标batch-size-avg和 batch-size-ms
值总是比batch.size小),那么可以通过增加一些延迟来提升夺吐量。可以把linger,n
设置得大一些,让生产者在发送批次之前等待几毫秒,让批次填充更多的数据。如果发达的数据都是满批的,并且还有空余内存,则可以配置更大的 batch.size,以便发送面大的批次。
max.in.flight.requests.per.connection
目前,如果某些消息需要多次重试才能确认发送成功,那么MirrorMaker保证消息有序
的唯一方法是将处理中的请求数量限制为1。但这意味着在发送下一条消息之前,生产者当前发送的消息必须得到目标集群的确认。这可能会对吞吐量造成限制,特别是如果在broker确认消息之前存在显著的延迟。如果消息顺序对你来说不是很关键,那么保留 max.in.flight.requests.per.connection的默认值5可以显著增加吞吐量。
下面的配置参数可用于提升消费者的吞吐量。
fetch.max.bytes
如果指标 fetch-size-avg和fetch-size-max的数值与fetch.max.bytes很接近,那么说
明消费者读取的数据已经接近broker允许的上限。如果有更多的可用内存,则可以配
置更大的 fetch.max.bytes,这样消费者就可以在每个请求中读取更多的数据。
fetch.min.bytes 和 fetch.max.wait.ms
如果指标fetch-rate的数值很高,那么说明消费者发送了太多请求,但每个请求都获
取不到足够的数据。这个时候可以配置更大的fetch.min.bytes和 fetch.max.wait.ms,
这样消费者的每个请求就可以获取到更多数据,broker会等到有足够可用数据时才将响应返回。
4 附录
4.1 灾备恢复
灾备恢复是指在灾难性事件发生后,组织能够迅速恢复业务运作并继续提供服务的能力。这包括备份数据、制定灾难恢复计划、建立备用设施等措施。
4.1.1 灾难恢复计划
灾难恢复计划 (DRP) 是一份详细的文档,概述了组织将如何应对计划外事件。除了业务连续性计划 (BCP) 和事件响应计划 (IRP) 外,灾难恢复计划还有助于确保企业准备好面对许多不同类型的灾难,包括停电、勒索软件和恶意软件攻击、自然灾害等等。
创建灾备计划的5个步骤:
- 进行业务影响分析
业务影响分析 (BIA) 是对公司可能面临的每个威胁及其后果的仔细评估。强大的 BIA 会检查潜在威胁如何影响日常运营、沟通渠道和工人安全等方面。BIA 潜在考虑因素的一些示例包括收入损失、停机成本、声誉修复成本(公共关系)、客户和投资者损失(短期和长期)以及因违反合规而产生的任何处罚。 - 执行风险分析
不同的行业和类型的企业面临不同的威胁,因此风险分析 (RA) 对于确定如何应对每个威胁至关重要。您可以通过考虑其可能性和潜在影响来单独评估每个风险。确定风险有两种广泛使用的方法:定性和定量风险分析。定性分析基于感知的风险,而定量分析则使用可验证的数据进行。 - 创建资产清单
要从网络事件中恢复,必须全面了解企业拥有的资产。定期盘点有助于识别对业务运营至关重要的硬件、软件、IT 基础设施、数据和其他资产。您可以使用以下标签作为起点,将资产划分为三个总体类别,然后根据需要为其分配更具体的标签:- 严重:仅当正常业务运营需要资产时,才将资产标记为关键。
- 重要提示:为每天至少使用一次的资产添加此标签,如果资产中断,将对业务 运营产生影响(但不会完全关闭它们)。
- 不重要:这些是您的企业不经常使用的资产,这些资产对于正常业务运营不是必需的。
- 建立角色和职责
灾难恢复计划 (DRP) 的角色和职责部分可以说是最重要的。没有它,没有人会知道在发生意外事件时该怎么做。虽然实际角色和职责会因您开展的业务类型而有很大差异,但以下是大多数 DRP 中包含的一些典型角色和职责:- 事件报告:您应该在每个部门中指派一个人(或多个人),其唯一职责是在发生破坏性事件时与管理团队、利益相关者和所有相关机构进行沟通。
- DRP 管理:您应该任命一名 DRP 主管,以确保团队成员正在执行分配给他们的任务,并且 DRP 运行顺利。
- 资产保护:当灾难发生时,您应该让某人负责保护您最关键的资产,并向管理层和利益相关者报告其状态。
- 第三方沟通:您应该让一个人负责与您作为 DRP 的一部分雇用的任何第三方供应商进行协调。此人应不断向任何相关利益相关者提供有关 DRP 进展情况的最新信息。
- 测试和优化
为确保您的灾难恢复计划 (DRP) 在实际事件期间无缝展开,您需要定期练习它,并根据您对业务所做的任何有意义的更改进行更新。例如,如果您的公司在您的 DRP 成立后收购了一项新资产,您需要将其纳入您的计划,以确保其在未来受到保护。
测试和改进可以分为三个简单的步骤。- 创建准确的模拟:尝试创建一个尽可能接近公司将面临的实际场景的环境,而不会使任何人面临物理风险。
- 识别问题:使用测试过程来识别与计划的故障和不一致之处,然后在 DRP 的下一次迭代中解决它们。
- 测试备份和还原功能:了解您将如何响应事件至关重要,但测试您在事件结束后为还原关键系统而实施的程序也同样重要。测试您将如何重新打开网络、恢复任何丢失的数据并恢复正常业务运营。
IB关于灾难恢复计划的定义:
https://www.ibm.com/topics/disaster-recovery-plan
4.1.2 灾备恢复的衡量指标
4.1.2.1 核心指标
-
RTO(Recovery Time Objective)
RTO是指灾难发生后,从IT系统崩溃导致业务停顿开始,到IT系统完全恢复,业务恢复运营为止的这段时间长度。RTO用于衡量业务从停顿到恢复的所需时间。
-
RPO(Recovery Point Objective)
IT系统崩溃后,可以恢复到某个历史时间点,从历史时间点到灾难发生的时间点的这段时间长度就称为RPO。RPO用于衡量业务恢复所允许丢失的数据量。
假设在业务系统正常运行的情况下,随着时间的推移,会持续产生新的业务数据。IT运维人员考虑到业务的重要性,小心又谨慎,写了个脚本对业务系统进行周期性的备份。
从上图可以直观看出,RPO是 "备份时间点" 到 "IT系统出现故障" 的时间长度,RTO是指 "IT系统出现故障" 到 "IT系统恢复正常" 的时间长度。
在RPO的这段时间内,存在一部分实际数据的丢失,所以一般认为RPO越小,丢失的数据量就越小。在RPO+RTO的这段时间内,本来有预期的业务数据增长,但由于IT系统故障需要时间修复,这部分的预期增长就损失掉了。可见RTO+RPO越小,对业务营收的损失也就越小。因此,越重要的业务越需要保证RPO和RTO趋近于0,当然所需要的投入也就越大。RPO和RPO也成为衡量灾难恢复的最核心指标。
4.1.2.2 其他指标
随着灾备技术的不断升级,灾备系统的建设越来越复杂,就开始出现了一些新的指标。
-
RRO(Recovery Reliability Objective)
恢复可靠性指标RRO,用于衡量业务恢复的可靠性。如果一个业务连续性系统在10次恢复/切换中出现了2次失败,那么这个可靠性就只有80%。虽然成功的恢复/切换可以帮助你短时间内的恢复业务,但如果恢复/切换失败了,那可能就需要花更多的时间来排查和解决问题。因此,将RRO和RTO结合起来可以更好的评估灾难恢复的时间。
基于上面的案例,假设IT运维人员写了不错的备份脚本,但是恢复脚本没有经过详细的测试,质量不咋滴。在IT系统修复过程中,总出现恢复失败的情况,需要边定位失败的原因边进行恢复。那么我们就可以认为这个脚本的RRO指标很低,会导致RTO变长。
-
RIO (Recovery Integrity Objective)
当灾备系统因为逻辑错误或数据丢失,就会造成实际恢复/切换的数据同样存在逻辑错误,或者数据丢失/不完整的情况。因此,单独的RPO不能保证灾备系统对数据丢失的防范能力,故引入恢复完整性指标RIO 。RIO指标可以反映出业务系统灾难恢复到某个正确完整的状态的能力。
基于上面的案例,假设IT运维人员写的备份脚本也出了问题,数据恢复是恢复出来了,但是只恢复了一部分,还有一部分数据因为脚本存在bug漏备了。那么我们就可以认为这个脚本的RIO指标也很低,RPO数据丢失的基础上再添损失。 说到这里,可怜的IT运维人员背了锅,也许你该考虑采购专业的灾备产品了。
-
DOO(Degraded Operations Objective)
DOO 是指灾难事件发生期间数据中心不可用时,关键业务系统在灾备中心运行的服务级别允许降低到一个可接受程度。这意味着灾难事件发生时,为了加快恢复速度,可以允许关键业务恢复到一个较低的服务级别,这个事先确定的允许降低的服务级别就是 DOO。
服务降级一般是由IT系统本身提供的能力,并不由灾备厂商来提供,当然专业的业务连续性管理也会将IT系统本身的容错、服务降级能力考虑在内。
-
NRO(Network Recovery Objective)
网络恢复目标NRO 是指在灾难发生后切换到灾备中心所需的时间。在这一预定时间内不仅要求将网络连接从数据中心切换到灾备中心,还要使用户的网络访问能够成功地转移到灾备中心。
4.1.3 灾备恢复的三个层次
在行业中,一般认为灾备分为3个等级:数据级灾备、应用级灾备、业务级灾备。其中数据级和应用级的灾备一般都在IT系统的范畴,可以通过专业的灾备产品做到。业务级灾备在数据级、应用级的基础上,还需要对IT系统之外的因素进行保障,比如办公地点、办公人员等等。
数据级灾备的关注点在于保证用户的数据不会丢失或者遭到破坏。高级的数据级灾备会考虑将本地的通过某些手段(人工/灾备工具)保存到异地。而应用级灾备更强调实际的IT系统可以在遇到灾难后能够直接接管。一般来讲应用级灾备需要在异地灾备中心有完整的设备、网络条件,借助专业灾备产品做到生产中心到灾备中心的数据同步。
4.1.4 国际标准SHARE78的七级灾备
目前,通用的灾难恢复标准采用的是 1992 年在 AnaheimM028 会议上制定的 SHARE78 标准。根据定义,灾备方案可以根据以下主要方面所达到的程度而分为七级:
-
Tier0 层:没有异地数据 (No off-site Data)
即没有任何异地备份或应急计划。数据仅在本地进行备份恢复,没有数据送往异地。
-
Tier1 层:PTAM 卡车运送访问方式 (Pickup Truck Access Method)
异地备份 , 能够备份所需要的信息并将它存储到异地。PTAM 指将本地备份的数据用交通工具送到远方。这种方案相对来说成本较低,但难于管理。
-
Tier2 层:PTAM 卡车运送访问方式 + 热备份中心 (PTAM + Hot Center)
相当于 Tier1 再加上热备份中心能力。热备份中心就是指在异地制定相应的灾难恢复计划,将运送到此处的数据定期的进行恢复,以确保生产中心出现灾难后热备份中心可以尽快接管。当然,热备份中心拥有足够的硬件和网络设备去支持关键应用。
-
Tier3 层:电子链接 (Electronic Vaulting)
在 Tier2 的基础上用网络传输取代了卡车进行数据的传送。
-
Tier4 层:活动状态的备份中心 (Active Secondary Center)
指两个中心同时处于活动状态并同时互相备份。在这种场景下,两中心通过备份软件系统进行周期性的备份和恢复。在灾难发生时,关键应用的恢复也可降低到小时级或分钟级。
-
Tier5层:两个活动的数据中心,确保数据一致性的两阶段提交(Two-Site Two-Phase Commit)
它提供了更好的数据完整性和一致性。Tier5 要求两中心的数据能够同时更新。在灾难发生时,仅是传送中的数据被丢失,恢复时间被降低到分钟级。
-
Tier6 层:0 数据丢失 (Zero Data Loss),自动系统故障切换
Tier6 可以实现 0 数据丢失,是灾难恢复的最高级别,在本地和远程的所有数据被更新的同时,利用了双重在线存储和网络切换能力,当发生灾难时,能够提供跨站点动态负载平衡和自动系统。
4.2 Kafka灾备恢复架构实例
4.2.1 架构简介
下面就一个笔者公司的实际的案例,结合上述的理论知识,来说明Kafka灾备解决方案是如何应用到实际的生产当中的,我们暂且称之为H公司。
H公司近年来在进行IT系统的数字化转型,采用了事件驱动(EDA)的架构,对公司数十个独立的IT系统进行重构和整合。
其中Kafka作为一个核心的中间件,它的角色主要是:
- 事件驱动
公有云和私有云/遗留系统之间的消息订阅与发布 - 消息队列
Kafka作为一个消息的临时缓存
H公司在托管的数据中心KSG搭建了一个Kafka集群,我们称之为PROD集群。集群采用了RedHat的AMQ Stream产品,部署在OCP容器平台中。集群主要包含:
- 3个broker实例
- 3个Zookeeper实例
因为需要满足合规性要求,需要提供灾备恢复方案。所以又在另一个区域的数据中心CRE搭建了第二个Kafka集群,资源,配置完全一样。
架构类似下图:
灾备架构采用上文中描述的主备模式,整个架构包含两个Kafka集群,称之为PROD和DR。每个集群主要包含:
- 3个broker实例
- 3个Zookeeper实例
- 1个MirrorMaker2实例
- 1个Kafka Bridge服务,用于GMT的健康检查
PROD和DR两个集群分别位于不同区域的两个数据中心KSG和CRE,采用异地容灾。
DR集群完全作为备用集群,平时无应用接入,只运行MirrorMaker2实例作为消费者,同步PROD集群数据。PROD集群的MirrorMaker2处于停止状态。
采用两层负载均衡:
- 全局负载均衡
使用F5 BIG-IP GTM全局负载均衡,用于处理跨数据中心的故障转移。实现方式为智能DNS负载均衡,提供对目标集群的健康检查,选择策略等的配置。 - 本地负载均衡
使用F5 BIG-IP LTM本地负载均衡,用于处理在数据中心内部Kafka服务器之间的负载均衡。
4.2.2 Kafka故障转移流程
采用F5 GTM全局负载均衡,用于跨数据中心的故障转移。
故障转移之后的架构如下图:
当GTM的DNS服务检测到Kafka集群不可用时,有两种方式进行故障转移:
4.2.2.1 手动切换
当GTM的DNS服务检测到Kafka集群健康检查请求失败后,立刻发送告警邮件给支持团队,团队街道告警后,执行如下过程:
-
首先查看监控,确认告警确实是由于PROD集群故障导致的,而不是误报或偶发错误,并且集群确实已经不可用了。
-
确认RTO指标,需要在规定时间内恢复服务,如1个小时内。
-
确认故障原因,那么需要权衡是否要进行故障转移:如果故障在1小时内可以在PROD集群修复,那么就不转移,等待问题修复;如果确定故障在1小时肯定无法修复,那么就需要进行故障转移。
-
如果要进行故障转移,首先查看监控,确认DR与PROD集群之间的同步延迟(数据,偏移量)。
-
如果DR与RPOD之间的同步还在进行,等待DR同步完成同步。
-
理想情况下,DR与PROD之间完全同步,网络团队切换DNS的域名映射,将客户端配置的域名映射到DR集群的IP:
kafka.k.com.hk --> 1.1.1.1 到 kafka.k.com.hk --> 2.2.2.2
-
一般情况下,DR和PROD之间都会存在不完全同步的情况。如果是这样,通知客户端应用程序存在数据不一致,需要处理。处理过程可能也分为程序自动处理的和需要人工处理的情况。
-
客户端应用程序可能需要重启或者刷新Kafka连接,以连接到DR集群。
-
停止DR集群的MirrorMaker2实例,停止数据镜像。
-
处理完以上问题,进行测试,使得系统在DR集群上平稳运行。
-
启动PROD集群的MirrorMakder2实例,启动数据镜像。这时候如果PROD和DR集群的数据存在不一致,可能需要将PROD中的数据进行清空,然后再开始数据镜像。
4.2.2.2 自动切换
自动切换与手动切换的区别在于当GTM的DNS服务检测到Kafka集群健康检查请求失败并持续10分钟之后,自动切换DNS的域名映射:
kafka.k.com.hk --> 2.2.2.2
并立刻进行发送告警邮件给支持团队,故障转移结束。
过程看起来非常简单,但是有几个问题需要解决:
- 客户端应用程序需要支持自动重置Kafka连接,以连接到DR集群。
- 应用程序需要支持自动处理集群之间数据不一致的问题,否则系统的服务可能还是不可用的。
- DR的MirrorMaker2实例也需要自动停止。
4.2.2.3 故障回切
待PROD服务恢复以后,需要进行故障回切,切换回PROD集群。
-
首先确保PROD集群和DR集群的数据已完全同步
-
关闭DNS的健康检查
-
首先网络团队切换DNS的域名映射,将客户端应用程序配置的域名映射到DR集群的IP:
kafka.k.com.hk --> 2.2.2.2 到 kafka.k.com.hk --> 1.1.1.1
-
停止DR集群
-
停止PROD集群的MirrorMaker2实例
-
客户端应用程序可能需要重启或者刷新Kafka连接,以连接到DR集群。
-
进行测试,确保系统业务在PROD集群正常运行。
-
启动DR集群
-
启动DR集群的MirrorMaker2实例
-
启动DNS的健康检查
4.2.3 相关知识
4.2.3.1 Big-IP GTM
Big-IP GTM(Global Triffic Manger)是由 F5 Networks 公司开发的全局流量管理器,用于管理和优化网络流量。它可以帮助企业实现负载均衡、故障转移和全局流量管理,以提高网络性能和可靠性。
Big-IP GTM 的主要功能包括:
- 健康检查:GTM提供ping、tcp、http(s)三种方式的健康检查,依靠强大的监控系统,应用智能选点技术,为调度决策提供可靠的基础数据。
- 全局负载均衡:根据服务器负载情况和网络状况,自动将流量分发到最佳的服务器上,以确保网络流量的均衡和高效。
- 故障转移:在服务器发生故障时,自动将流量转移到备用服务器上,以确保网络的连续性和可靠性。
- DNS 解析优化:通过优化 DNS 解析过程,减少网络延迟和提高用户访问网站的速度。
- 调度策略管理:按负载权重、地域或运营商属性来进行流量分配,不同的资源分配不同比例的流量,当资源发生故障时,可自动或手动切换至正常的资源,保障资源持续可用。
调度策略丰富多样,不仅支持自定义线路配置,支持主备负载均衡,还支持线路智能调度、动态比例智能切换,这些特性让GTM能够灵活快速的构建同城多活和异地容灾服务。
访问流程:
- 用户终端浏览器输入的URL,例如http://www.example.com,浏览器发送域名解析请求到本地DNS服务器解析;
- 本地DNS服务器发送域名解析请求到授权DNS服务器(即GTM系统);
- GTM系统根据预定策略,分析请求IP,返回最佳的解析结果(如同运营商,同区域等);
- 本地DNS服务器得到最优的IP,返回给用户;
- 用户得到网站IP地址,向网站发出访问请求;
- 网站根据用户的请求,返回内容给用户;
- GTM系统实时监控源站资源的情况等,并在系统出现故障时,及时调整,保障服务可用。
4.2.3.2 BIG-IP DNS
BIG-IP DNS是由F5 Networks开发的一种高性能、可扩展的域名系统(DNS)解决方案。它可以帮助组织管理和优化其全球网络流量,提高网站的可用性和性能。
BIG-IP DNS提供了智能的负载均衡功能,可以根据实时的网络条件和服务器负载来动态地分配流量,从而确保用户始终能够访问到最佳的服务器。它还具有强大的安全功能,可以保护网络免受DDoS攻击和其他恶意活动的影响。
此外,BIG-IP DNS还提供了丰富的监控和报告功能,可以帮助管理员实时地了解网络流量和性能状况,及时发现和解决问题。
4.2.3.3 BIG-IP LTM
BIG-IP LTM(Local Traffic Manger)是由F5 Networks开发的一款应用交付控制器,用于管理和优化应用程序交付。它可以帮助企业提高应用程序的性能、安全性和可靠性。
一些关于BIG-IP LTM的特点包括:
- 负载均衡:可以根据流量和服务器负载来分配请求,以确保应用程序的高可用性和性能。
- SSL加速:提供SSL卸载和加速,以减轻服务器负担并提高安全性。
- Web应用防火墙:通过检测和阻止恶意流量,保护应用程序免受攻击。
- 缓存控制:可以缓存静态内容,减少服务器负载并加快内容传输速度。
负载均衡策略
BIG-IP LTM进行四层负载均衡的最小元素为TCP连接,所有分配策略均以TCP连接为最小单位,而在七层负载均衡中,最小的元素为每一个完整的交易数据报包,如一个HTTP请求,因此以交易为最小单位进行分配。
负载分配策略主要包含以下几种:
- 静态负载均衡算法:轮询,比率,优先权
- 动态负载均衡算法:最少连接数,最快响应速度,观察方法,预测法,动态性能分配。
- 可编程控制的负载均衡策略:通过编程控制应用流量的导向。
静态负载均衡算法:轮询
轮询算法下,以每个客户端新建连接为单位,客户端连接轮流分配到后台的服务器上。
比率算法:比率算法
比率算法下,以每个客户端新建连接为单位,将客户端请求按照比率分配到后台的服务器上
优先权算法
在正常情况下,所有的客户端请求全部发送到属于高优先级组的member上;当最高优先级群组中的健康的服务器数量小于预定值时,BIG-IP LTM才将请求发送给次优先级的服务器组。
动态负载均衡算法:最少连接数
最小连接数为最常用的负载均衡算法之一,在后台服务器处理能力均等的情况下,使用最小的连接数可以得到最为平衡的负载均衡效果。(但是BIG-IP 要维护一张并发表,上面有各个服务器的并发参数)
动态负载均衡算法:动态性能分配
前提;BIG-IP知道服务器的CPU使用率(通过健康检查)
动态性能分配通常用于一些服务器资源敏感应用,如集中计算、视频点播等。动态算法是通过BIG-IP上的健康检查来检测服务器的资源占用率,新的请求被分配到资源占用最少的服务器。
如何选择合适的负载均衡策略
在大部分的应用场景中,都采用最小连接算法。如果系统的每秒新建连接数非常高,如果还是采用最小连接数,由于算法在计算时候不可能实时的统计后台服务器的连接数,且是有时间间隔的去进行统计。在这种情况下,可能采用轮询算法可以更为有效的实现负载均衡。
4.3 基于VIP的高可用
GTM中用到了Visual server和VIP,不知道是否就是Linux中的LVS应用,在这里顺便谈一下基于Linux VIP在高可用中的简单应用和原理。
假如我们用应用集群使用Ngix充当负载均衡服务器,实现了应用服务器的负载均衡。但是Ngix是一个单点服务器,所有的流量都会经过它,随着用户的增加,流量越来越大,它可能成为一个性能的瓶颈。
那该如何解决Ngix的单点问题呢?我们可以用Nigix集群+VIP+Keepalived来解决这个问题。如下图所示:
我们部署三台Ngix服务器,一主两备。每台服务器上都运行Keepalived,一台为主服务器(MASTER),两台为备份服务器(BACKUP),但是对外只暴露一个虚拟IP。应用程序通过这个VIP,可以访问到主Ngix服务器。主Ngix服务器会发送特定的消息给备份服务器,当备份服务器收不到这个消息的时候,即主服务器宕机的时候,备份服务器就会向路由器发送请求,刷新路由器的路由表,从而将这个VIP映射到自己的MAC地址,从而接替主服务器继续提供服务,从而保证了高可用性。等到主服务器恢复的时候,可以重新加入集群,从而保证集群的节点数量。
4.3.1 Keeplived
Keepalived是Linux下一个轻量级别的高可用解决方案,通过虚拟路由冗余协议(VRRP,Virtual Router Redundancy Protocol)来实现服务或者网络的高可用。
起初是为LVS设计的,专门用来监控集群系统中各个服务节点的状态。如果某个服务器节点出现故障,Keepalived将检测到后自动将节点从集群系统中剔除而在故障节点恢复正常后,Keepalived又可以自动将此节点重新加入集群中。
这些工作自动完成,不需要人工干预,需要人工完成的只是修复出现故障的节点。
4.3.2 LVS
LVS 是 Linux Virtual Server 的简写,也就是 Linux 虚拟服务器,是一个虚拟的服务器集群系统。
LVS 是一个实现负载均衡集群的开源软件项目,LVS 架构从逻辑上可分为调度层、Server 集群层和共享存储层。
官方网站:http://www.linuxvirtualserver.org,LVS 实际上相当于基于 IP 地址的虚拟化应用,为基于 IP 地址和内容请求分发的负载均衡提出了高效的解决方法,现在 LVS 已经是 Linux 内核标准的一部分。
使用 LVS 可以达到的技术目标是:通过 LVS 达到的负载均衡技术和 Linux 操作系统实现一个高性能高可用的 Linux 服务器集群,具有良好的可靠性、可扩展性和可操作性,从而以低廉的成本实现最优的性能。
4.3.3 VRRP
在现实的网络环境中,主机之间的通信都是通过配置静态路由(默认网关)来完成的,而主机之间的路由器一旦出现故障,就会通信失败。
因此在这种通信模式下,路由器就会有单点瓶颈问题,为了解决这个问题,引入了VRRP 协议(虚拟路由冗余协议),通过VRRP可以在网络发生故障时透明的进行设备切换而不影响主机之间的数据通信。
VRRP可以将两台或多台物理路由器设备虚拟成一个虚拟路由器,这个虚拟路由器通过虚拟IP(一个或多个)对外提供服务,而在虚拟路由器内部是多个物理路由器协同工作,VRRP角色如下:
1、角色
- 虚拟路由器:VRRP组中所有的路由器,拥有虚拟的IP+MAC(00-00-5e-00-01-VRID)地址
- 主路由器(master):虚拟路由器内部通常只有一台物理路由器对外提供服务,主路由器是由选举算法产生,对外提供各种网络功能
- 备份路由器(backup):VRRP组中除主路由器之外的所有路由器,不对外提供任何服务,只接受主路由的通告,当主路由器挂掉之后,重新进行选举算法接替master路由器
master路由器由选举算法产生,它拥有对外服务的VIP,提供各种网络服务,如ARP请求、数据转发、ICMP等等,而backup路由器不拥有VIP,也不对外提供网络服务
当master发生故障时,backup将重新进行选举,产生一个新的master继续对外提供服务。