有时候,一家公司会有多个数据中心,分别分布在不同的地理区域、城市或大洲。这些数据中心都有自己的Kafka集群。有些应用程序只需要与本地的Kafka集群通信,有些应用程序则需要访问多个数据中心里的数据(否则就没必要考虑跨数据中心了)。
一个Kafka集群已经可以满足所有应用程序的需求,但你担心集群会因某些原因变得不可用。为了实现冗余,你希望有第二个Kafka集群,该集群的数据与第一个集群
同,如果发生紧急情况,则可以将应用程序重定向到第二个集群。
为了符合不同国家的法律和监管要求,一家公司在不同国家的运营可能需要不同的和
和策略。例如,一些数据可能需要被保存在具有严格访问控制的独立集群中,
则可以被复制到具有宽松访问权限的其他集群。为了满足不同区域对数据保留期限的么规性要求,保存在不同区域集群中的数据可以使用不同的配置。
现如今,很多公司会将它们的业务同时部署在本地数据中心和云端。为了实现冗余,应用程序通常会运行在云供应商的多个服务区域,或使用多个云供应商提供的云服务。本地数据中心和每个云服务区域都至少有一个Kafka集群。本地数据中心和云服务区域中的应用程序通过这些Kafka集群在数据中心之间传输数据。例如,云端部署了一个应用程序,它需要访问本地数据中心里的数据。本地应用程序负责更新这些数据,并保存在本地数据库中。可以用Connect捕获这些数据库变更,先把它们保存在本地Kafka集群,然后再镜像到云端的Kafka集群,让云端的应用程序可以访问这些数据。这样既有助于控制跨数据中心的流量成本,也有助于提高流量的监管合规性和安全性。
一些行业,包括零售、电信、运输和医疗保健等,它们会收集小型设备生成的数据。这些设备使用的是受限的网络连接。大量的边缘集群会将收集到的数据聚合到一个高可用的聚合集群中。这些数据将被用于数据分析和其他用途。这种架构降低了对边缘集群(如物联网)在连通性、可用性和持久性方面的要求。即使边缘集群离线,高可用聚合集群仍然能够保证业务的连续性,并能够简化应用程序开发,无须直接与大量具有不稳定网络连接的边缘集群通信。
以下是在进行跨数据中心通信时需要考虑的一些问题:
多集群的架构原则:
这种架构适用于一个中心Kafka集群对应多个本地Kafka集群的情况。
应用场景:
好处:
不足:
当有两个或多个数据中心需要共享部分或全部数据,并且每个数据中心都可以生成和读取数据时,可以使用双活架构。
如果能够很好地处理多个数据中心在进行异步读写时发生冲突的问题,那么强烈建议使用这种架构。这种架构是我们所知道的最具伸缩性、弹性、灵活性和成本优势的解决方案。
好处:
不足:
挑战:
有时候,我们使用多个集群只是为了达到灾备的目的。这是一种合规性需求,业务不一定会将其纳入规划范畴。
不足:
它浪费了一个集群。
为了减少浪费,有些组织会尝试减小灾备集群的规模,让它远小于生产环境集群的规模。这种做法存在一定的风险,因为你无法保证这种小规模集群能够在紧急情况下发挥应有的作用。
有些组织则倾向于让灾备集群在平常也发挥作用,它们把一些只读工作负载转移到灾备集群中,也就是说,它们实际上运行的是星型架构的一个简化版本(只有一个Spoke)。
目前,要实现完全不丢失数据或无重复数据的Kafka集群故障转移是不可能的,更为常见的情况是既丢失数据,又出现重复数据。我们只能尽量减少这些问题的发生,但无法完全避免。
灾难恢复计划 (DRP) 是一份详细的文档,概述了组织将如何应对计划外事件。除了业务连续性计划 (BCP) 和事件响应计划 (IRP) 外,灾难恢复计划还有助于确保企业准备好面对许多不同类型的灾难,包括停电、勒索软件和恶意软件攻击、自然灾害等等。
相关术语:
在进行灾难恢复计划时,必须考虑两个关键指标:
灾备恢复介绍:
https://blog.csdn.net/yunyun1886358/article/details/135735006
因为Kafka的各种镜像解决方案都是异步的(后面将介绍一种同步的解决方案),所以灾备集群将无法及时获取主集群的最新数据。
我们需要时刻注意灾备集群落后了主集群多少,并确保不要让它落后太多。但是,在一个繁忙的系统中,灾备集群与主集群之间可能有几百条甚至几千条消息的延迟。
如果有故障转移计划,则可以:
如果发生了非计划内的故障转移,则可能会丢失数千条消息。需要注意的是,目前镜像解决方案还不支持事务,也就是说,如果多个主题(比如保存销售数据的主题和保存产品数据的主题)之间有相关性,那么在故障转移过程中,有些数据可能可以及时到达灾备集群,有些则不能。在切换到灾备集群之后,应用程序需要知道如何处理没有相关销售信息的产品数据。
在切换到灾备集群的过程中,最具挑战性的事情莫过于让应用程序知道该从哪里开始处理数据。
Kafka消费者有一个配置参数auto.offset.reset用于指定在没有前一个提交偏移量的情况下该作何处理。
如果灾备进化里面么有镜像偏移量,那么就要二者选其一:
如果重复处理数据或者丢失一些数据不是大问题,那么这种方案就是目前为止最为简单的。一般来说,在故障转移之后直接从主题末尾开始读取数据的方式更为常见。
如果你使用的是0.9.0及以上版本的Kafka消费者,那么它会把偏移量提交到一个叫作__consumer_offsets的主题上。如果你将这个主题镜像到了灾备集群,那么当消费者开始读取灾备集群时,就可以获取到原先的偏移量,并从这个位置开始处理数据。
这看起来很简单,但仍然有很多需要注意的地方:
在发生故障转移之后,消费者可能会找不到与偏移量匹配的记录,或者灾备集群中的偏移量会比主集群中的偏移量小。
从Kafka 0.10.0开始,每条消息里都包含了一个时间戳 – 消息发送给Kafka的时间。
从Kafka 0.10.1.0开始,broker提供了一个索引和可根据时间戳查找偏移量的API。
如何让消费者特定时间的位置开始处理数据:
bin/kafka-consumer-groups.sh -- bootstrap-server localhost:9092 -- reset-
offsets -- all-topics -- group my-group -- to-datetime
2021-03-31T04:03:00.000 -- execute
```
这个方案适用于在发生故障转移时需要保证一定确定性的场景。
镜像偏移量主题的一个最大问题在于主集群和灾备集群的偏移量会发生偏离。在过去,一些组织会选择使用外部数据存储(如Apache Cassandra)来保存集群之间的偏移量对关系。每当一个事件被发送到灾备集群时,镜像工具会将两个集群的偏移量都发计动外部存储。现在的镜像解决方案(包括MirrorMaker)会使用Kafka主题来保存偏秋映射关系(只保留偏移量差值的变化,而不是保留每一个映射)。对于那些比记录先达到的偏移量或没有及时被镜像到灾备集群的偏移量,仍然会有问题,不过这至少已经覆盖了部分场景。
假设故障转移进行得很顺利,灾备集群也运行得很正常,现在需要对主集群做一些改动,把它变成灾备集群。
如果能够简单地改变镜像进程的方向,让它将数据从新主集群镜像到旧主集群,那么就完美了。不过,这里有两个问题。
因此,如果要保证数据的一致性和顺序,最简单的解决方案是清理旧主集群,删掉所有
数据和偏移量,然后从新主集群中把数据镜像回来。这样可以获得与新主集群一致的数据状态。
在设计灾备集群时,需要考虑的一个很重要的问题是在发生故障转移之后,应用程序如何与灾备集群通信。如果把主集群的主机名硬编码在生产者和消费者的配置文件中,就会很麻烦。为简单起见,大多数组织使用了DNS,并将其指向主集群,一旦发生紧急情况,则可以将其指向灾备集群。这些服务发现工具(DNS或其他)不需要包含所有broker的信息,只要Kafka客户端能够连接到其中一个broker,就可以获取整个集群的元数据,并发现集群中的其他broker。一般来说,提供3个broker的信息就可以了。不管使用哪种服务发现工具,在大多数情况下需要重启消费者,这样才能找到新的偏移量,并继续读取数据。对于为降低RTO而使用自动故障转移的场景,需要将故障转移处理逻辑放在客户端应用程序中。
不管选择哪一种故障转移方案,SRE团队都必须定期进行验证。
SRE工程师(Site Reliability Engineer)是负责确保网站和应用程序的可靠性、稳定性和可伸缩性的工程师。他们通常需要具备深厚的系统和网络知识,能够编写自动化脚本和工具来管理和监控大规模的系统。
SRE工程师的主要职责包括:
- 设计、构建和维护高可靠性的系统架构
- 开发自动化工具和脚本来提高系统的稳定性和可维护性
- 监控系统性能,并进行故障排除和性能优化
- 参与容量规划和系统扩展
- 与开发团队合作,确保新功能的上线不会影响系统的稳定性
Chaos Monkey是Netflix开发的一款著名的故障注入工具,它会随机地制造灾难,有可能让任何一天都成为故障转移日。
延展集群是指跨多个数据中心的Kafka集群。而当其中部分数据中心发生故障时,延展集群(stretch cluster)可以保证Kafka集群仍然可用。
延展集群与其他类型的跨数据中心集群有本质上的区别:
优势:
不足:
一种比较流行的延展集群模型是2.5数据中心架构,即两个数据中心里都安装了Kafka和ZooKeeper,然后再在另外“半”个数据中心里安装一个ZooKeeper节点,当其中一个数据中心发生故障时,它可以提供仲裁。
Kafka提供了一个叫作MirrorMaker的工具,用于在两个数据中心之间镜像数据。
MirrorMaker 2.0是Kafka的下一代多集群镜像解决方案,它基于Connect框架,张补了旧版本的很多不足。我们可以很容易地配置出复杂的拓扑来支持更为广泛的场景,比如灾难恢复、备份、迁移和数据聚合。
MirrorMaker看起来很简单,但因为我们想要做到既高效又非常接近精确一
次传递,所以其实现起来是很困难的。
MirrorMaker 使用源连接器来读取另一个Kafka集群而不是数据库的数据。Connect框架的使用减轻了企业IT部门管理Kafka的负担。
MirrorMaker是高度可配置的。除了用于配置拓扑、Connect和连接器的集群参数,
MirrorMaker 所使用的生产者、消费者和AdminClient的每一个属性都是可配置的。
下面的命令会使用属性文件中指定的配置参数来启MirrorMaker:
bin/connect-mirror-maker.sh etc/kafka/connect-mirror-maker.properties
在两个数据中心之间建立主备复制流的配置参数。
# 定义在复制流中使用的集群的别名。
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 = .*
对于每个复制流,可以使用正则表达式指定需要镜像的主题。上面示例中镜像了每一个主题,但在实际当中,最好使用类似prod .* 这样的表达式,以免镜像了测试主题。
也可以指定要排除的主题或使用类似test .* 这样的表达式来排除不需要镜像的主题。
在默认情况下,目标主题会自动加上源集群别名作为前缀。如果既要将主题从PROD镜像到DR,又要将主题从DR镜像到PROD,那么这种默认命名策略可以防止循环镜像(数据在两个集群之间无休止地来回镜像)。
本地主题和远程主题之间的名称差异并不影响聚合,因为消费者既可以通过正则表达式订阅本地主题,也可以订阅远程主题,以便获得完整的数据集。
MirrorMaker会定期检查源集群是否有新增主题,如果有,并且与指定的模式匹配,就
会自动开始镜像这些主题。如果源主题新增了分区,则目标主题也会自动添加相同数量的分区,确保源主题中的事件在目标主题中以相同的顺序出现在相同的分区中。
MirrorMaker提供了一个叫作RemoteClusterUtils的辅助类,在发生故障转移后,可以用它在灾备集群中找到最后的检查点偏移量。
Kafka 2.7.0支持定时迁移消费者偏移量,它会自动将转换后的偏移量提交到灾备集群的_consumer_offsets主题,消费者在切换到灾备集群后就可以从之前停止的位置重新开始处理数据,不会发生数据丢失。
重复处理消息的可能性降到最低。为安全起见,如果目标集群的消费者正在使用目标消费者群组,那么MirrorMaker就不会覆盖偏移量,从而能够避免出现意外冲突。
除了数据,MirrorMaker也可以镜像主题的配置信息和访问控制列表(ACL)
便保留相同的主题行为。
这个功能默认是启用的,并会以合理的时间间隔刷新。
的大部分配置参数会被应用于目标主题,但有一些参数在默认情况下不会被应用,H
min.insync.replicas。需要排除哪些配置参数可以自行指定。
只有那些与被镜像的主题匹配的字面量ACL会被迁移,因此,如果你使用的是包含备
缀或通配符的ACL或者其他身份验证机制,则需要在目标集群中显式配置。
为了确保只有MirrorMaker能够向目标主题写入数据,Topic:Write权限不会被迁移。在发生故障转移时,必须显式地授予应用程序适当的访问权限,确保它们可以正常访问第二个集群。
参数 tasks.max指定了与MirrorMaker关联的连接器可以使用的最大任务数。默认值
为1,但建议最少将其设置为2。在复制大量的主题分区时,为了增加并行度,应该尽
可能设置更大的值。
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}
前面介绍了一个简单的主备复制流的配置示例,下面来配置双向复制流来支持双活拓扑。
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选项指定目标集群。
还可以向拓扑中添加更多包含其他源或目标集群的复制流。
clusters = PROD, DR, DR1
DR1.bootstrap.servers = kafka.dr1.example.com:9092
PROD->DR1.enabled = true
PROD->DR1.topics = .*
对于生产环境中的集群,需要确保所有的跨数据中心流量都是安全的。
我们必须在源集群和目标集群中使用安全的broker监听器,必须配置集群的客户端安全选项,让MirrorMaker能够使用需要身份验证的安全连接。还需要使用SSL加密所有的跨数据中心通信。
例如,可以像下面这样配置MirrorMaker的密钥凭证。
# 安全协议应该与指定集群所对应的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权限。
也可以启动任意数量的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已经读取了数据,但无法将数据生成到目标集群中,则会造成数据丢失。所以说,远程读取数据比远程生成数据更加安全。
本地读取消息并将其生成到远程数据中心的场景:
在将MirrorMaker部署到生产环境时,一定要记得监控下面这些内容:
Connect提供了大量的指标,比如用于监控连接器状态的连接器指标、用于监控吞吐量的源连接器指标,以及用于监控再均衡延迟的worker指标。Connect还提供了一个用于查看和管理连接器的REST API。
除了Connect提供的指标,MirrorMaker也提供了用于监控镜像吞吐量和复制延迟的指标。复制延迟指标 replication-latency-ms可以告诉我们消息的时间戳与消息被成功写入目标集群时的时间间隔。如果想知道目标集群是否及时跟上了源集群,那么这个指标就非常有用。在高峰时段,如果目标集群有足够的能力赶上源集群,那么即使延迟增加了也没问题,但如果延迟持续增加,则说明目标集群能力不足。
其他指标,比如record-age-ms(在进行镜像时消息的年龄)、byte-rate(镜像吞吐量)和checkpoint-latency-ms(偏移量迁移延迟),也非常有用。在默认情况下,MirrorMaker还会定时发送心跳,我们可以用它来监控MirrorMaker的运行状况。
你肯定想知道目标集群是否落后于源集群。延迟体现在源集群最新偏移量与目标集群最新偏移量的差异上。
以下是两种跟踪延迟的方式,但它们都不完美。
需要注意的是,如果MirrorMaker跳过或丢弃了部分消息,则上述的两种方法是无法检测到的,因为它们只跟踪最新的偏移量。
MirrorMaker所使用的Connect包含了一个生产者和一个消费者,它们提供了很多可用的指标。建议监控这些指标。Kafka的文档列出了所有可用的指标。
下面列出了几个对MirrorMaker 调优非常有用的指标。
如果对所有东西都进行了监控,那么金丝雀(canary)验证就不是严格必需的,但为了
实现多层监控,我们还是会进行金丝雀验证。我们每分钟向源集群的某个主题发送一条消息,然后再尝试从目标集群读取这条消息。如果消息在指定的时间之后才到达,就会发出告警,说明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网络配置相结合,如下所示。
首先,需要知道生产者或消费者是不是瓶颈所在,即生产者是否在等待消费者提供更多的数据,或者消资者在等待生产者提供更多的数据。
如果MirrorMaker的大部分时间用在轮询上,那么说们消费者是瓶颈所在,如果MirrorMaker的大部分时间用在发送消息上,则说明生产者时瓶颈所在。
可以使用下面的配置参数进行调优:
如果你发现生产者总是发送未被填满的批次(指标batch-size-avg和 batch-size-ms
值总是比batch.size小),那么可以通过增加一些延迟来提升夺吐量。可以把linger,n
设置得大一些,让生产者在发送批次之前等待几毫秒,让批次填充更多的数据。如果发达的数据都是满批的,并且还有空余内存,则可以配置更大的 batch.size,以便发送面大的批次。
目前,如果某些消息需要多次重试才能确认发送成功,那么MirrorMaker保证消息有序
的唯一方法是将处理中的请求数量限制为1。但这意味着在发送下一条消息之前,生产者当前发送的消息必须得到目标集群的确认。这可能会对吞吐量造成限制,特别是如果在broker确认消息之前存在显著的延迟。如果消息顺序对你来说不是很关键,那么保留 max.in.flight.requests.per.connection的默认值5可以显著增加吞吐量。
下面的配置参数可用于提升消费者的吞吐量。
如果指标 fetch-size-avg和fetch-size-max的数值与fetch.max.bytes很接近,那么说
明消费者读取的数据已经接近broker允许的上限。如果有更多的可用内存,则可以配
置更大的 fetch.max.bytes,这样消费者就可以在每个请求中读取更多的数据。
如果指标fetch-rate的数值很高,那么说明消费者发送了太多请求,但每个请求都获
取不到足够的数据。这个时候可以配置更大的fetch.min.bytes和 fetch.max.wait.ms,
这样消费者的每个请求就可以获取到更多数据,broker会等到有足够可用数据时才将响应返回。
灾备恢复是指在灾难性事件发生后,组织能够迅速恢复业务运作并继续提供服务的能力。这包括备份数据、制定灾难恢复计划、建立备用设施等措施。
灾难恢复计划 (DRP) 是一份详细的文档,概述了组织将如何应对计划外事件。除了业务连续性计划 (BCP) 和事件响应计划 (IRP) 外,灾难恢复计划还有助于确保企业准备好面对许多不同类型的灾难,包括停电、勒索软件和恶意软件攻击、自然灾害等等。
创建灾备计划的5个步骤:
IB关于灾难恢复计划的定义:
https://www.ibm.com/topics/disaster-recovery-plan
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也成为衡量灾难恢复的最核心指标。
随着灾备技术的不断升级,灾备系统的建设越来越复杂,就开始出现了一些新的指标。
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 是指在灾难发生后切换到灾备中心所需的时间。在这一预定时间内不仅要求将网络连接从数据中心切换到灾备中心,还要使用户的网络访问能够成功地转移到灾备中心。
在行业中,一般认为灾备分为3个等级:数据级灾备、应用级灾备、业务级灾备。其中数据级和应用级的灾备一般都在IT系统的范畴,可以通过专业的灾备产品做到。业务级灾备在数据级、应用级的基础上,还需要对IT系统之外的因素进行保障,比如办公地点、办公人员等等。
数据级灾备的关注点在于保证用户的数据不会丢失或者遭到破坏。高级的数据级灾备会考虑将本地的通过某些手段(人工/灾备工具)保存到异地。而应用级灾备更强调实际的IT系统可以在遇到灾难后能够直接接管。一般来讲应用级灾备需要在异地灾备中心有完整的设备、网络条件,借助专业灾备产品做到生产中心到灾备中心的数据同步。
目前,通用的灾难恢复标准采用的是 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 数据丢失,是灾难恢复的最高级别,在本地和远程的所有数据被更新的同时,利用了双重在线存储和网络切换能力,当发生灾难时,能够提供跨站点动态负载平衡和自动系统。
下面就一个笔者公司的实际的案例,结合上述的理论知识,来说明Kafka灾备解决方案是如何应用到实际的生产当中的,我们暂且称之为H公司。
H公司近年来在进行IT系统的数字化转型,采用了事件驱动(EDA)的架构,对公司数十个独立的IT系统进行重构和整合。
其中Kafka作为一个核心的中间件,它的角色主要是:
H公司在托管的数据中心KSG搭建了一个Kafka集群,我们称之为PROD集群。集群采用了RedHat的AMQ Stream产品,部署在OCP容器平台中。集群主要包含:
因为需要满足合规性要求,需要提供灾备恢复方案。所以又在另一个区域的数据中心CRE搭建了第二个Kafka集群,资源,配置完全一样。
架构类似下图:
灾备架构采用上文中描述的主备模式,整个架构包含两个Kafka集群,称之为PROD和DR。每个集群主要包含:
PROD和DR两个集群分别位于不同区域的两个数据中心KSG和CRE,采用异地容灾。
DR集群完全作为备用集群,平时无应用接入,只运行MirrorMaker2实例作为消费者,同步PROD集群数据。PROD集群的MirrorMaker2处于停止状态。
采用两层负载均衡:
采用F5 GTM全局负载均衡,用于跨数据中心的故障转移。
故障转移之后的架构如下图:
当GTM的DNS服务检测到Kafka集群不可用时,有两种方式进行故障转移:
当GTM的DNS服务检测到Kafka集群健康检查请求失败后,立刻发送告警邮件给支持团队,团队街道告警后,执行如下过程:
kafka.k.com.hk --> 1.1.1.1 到
kafka.k.com.hk --> 2.2.2.2
自动切换与手动切换的区别在于当GTM的DNS服务检测到Kafka集群健康检查请求失败并持续10分钟之后,自动切换DNS的域名映射:
kafka.k.com.hk --> 2.2.2.2
并立刻进行发送告警邮件给支持团队,故障转移结束。
过程看起来非常简单,但是有几个问题需要解决:
待PROD服务恢复以后,需要进行故障回切,切换回PROD集群。
kafka.k.com.hk --> 2.2.2.2 到
kafka.k.com.hk --> 1.1.1.1
Big-IP GTM(Global Triffic Manger)是由 F5 Networks 公司开发的全局流量管理器,用于管理和优化网络流量。它可以帮助企业实现负载均衡、故障转移和全局流量管理,以提高网络性能和可靠性。
Big-IP GTM 的主要功能包括:
BIG-IP DNS是由F5 Networks开发的一种高性能、可扩展的域名系统(DNS)解决方案。它可以帮助组织管理和优化其全球网络流量,提高网站的可用性和性能。
BIG-IP DNS提供了智能的负载均衡功能,可以根据实时的网络条件和服务器负载来动态地分配流量,从而确保用户始终能够访问到最佳的服务器。它还具有强大的安全功能,可以保护网络免受DDoS攻击和其他恶意活动的影响。
此外,BIG-IP DNS还提供了丰富的监控和报告功能,可以帮助管理员实时地了解网络流量和性能状况,及时发现和解决问题。
BIG-IP LTM(Local Traffic Manger)是由F5 Networks开发的一款应用交付控制器,用于管理和优化应用程序交付。它可以帮助企业提高应用程序的性能、安全性和可靠性。
一些关于BIG-IP LTM的特点包括:
BIG-IP LTM进行四层负载均衡的最小元素为TCP连接,所有分配策略均以TCP连接为最小单位,而在七层负载均衡中,最小的元素为每一个完整的交易数据报包,如一个HTTP请求,因此以交易为最小单位进行分配。
负载分配策略主要包含以下几种:
轮询算法下,以每个客户端新建连接为单位,客户端连接轮流分配到后台的服务器上。
比率算法下,以每个客户端新建连接为单位,将客户端请求按照比率分配到后台的服务器上
在正常情况下,所有的客户端请求全部发送到属于高优先级组的member上;当最高优先级群组中的健康的服务器数量小于预定值时,BIG-IP LTM才将请求发送给次优先级的服务器组。
最小连接数为最常用的负载均衡算法之一,在后台服务器处理能力均等的情况下,使用最小的连接数可以得到最为平衡的负载均衡效果。(但是BIG-IP 要维护一张并发表,上面有各个服务器的并发参数)
前提;BIG-IP知道服务器的CPU使用率(通过健康检查)
动态性能分配通常用于一些服务器资源敏感应用,如集中计算、视频点播等。动态算法是通过BIG-IP上的健康检查来检测服务器的资源占用率,新的请求被分配到资源占用最少的服务器。
在大部分的应用场景中,都采用最小连接算法。如果系统的每秒新建连接数非常高,如果还是采用最小连接数,由于算法在计算时候不可能实时的统计后台服务器的连接数,且是有时间间隔的去进行统计。在这种情况下,可能采用轮询算法可以更为有效的实现负载均衡。
GTM中用到了Visual server和VIP,不知道是否就是Linux中的LVS应用,在这里顺便谈一下基于Linux VIP在高可用中的简单应用和原理。
假如我们用应用集群使用Ngix充当负载均衡服务器,实现了应用服务器的负载均衡。但是Ngix是一个单点服务器,所有的流量都会经过它,随着用户的增加,流量越来越大,它可能成为一个性能的瓶颈。
那该如何解决Ngix的单点问题呢?我们可以用Nigix集群+VIP+Keepalived来解决这个问题。如下图所示:
我们部署三台Ngix服务器,一主两备。每台服务器上都运行Keepalived,一台为主服务器(MASTER),两台为备份服务器(BACKUP),但是对外只暴露一个虚拟IP。应用程序通过这个VIP,可以访问到主Ngix服务器。主Ngix服务器会发送特定的消息给备份服务器,当备份服务器收不到这个消息的时候,即主服务器宕机的时候,备份服务器就会向路由器发送请求,刷新路由器的路由表,从而将这个VIP映射到自己的MAC地址,从而接替主服务器继续提供服务,从而保证了高可用性。等到主服务器恢复的时候,可以重新加入集群,从而保证集群的节点数量。
Keepalived是Linux下一个轻量级别的高可用解决方案,通过虚拟路由冗余协议(VRRP,Virtual Router Redundancy Protocol)来实现服务或者网络的高可用。
起初是为LVS设计的,专门用来监控集群系统中各个服务节点的状态。如果某个服务器节点出现故障,Keepalived将检测到后自动将节点从集群系统中剔除而在故障节点恢复正常后,Keepalived又可以自动将此节点重新加入集群中。
这些工作自动完成,不需要人工干预,需要人工完成的只是修复出现故障的节点。
LVS 是 Linux Virtual Server 的简写,也就是 Linux 虚拟服务器,是一个虚拟的服务器集群系统。
LVS 是一个实现负载均衡集群的开源软件项目,LVS 架构从逻辑上可分为调度层、Server 集群层和共享存储层。
官方网站:http://www.linuxvirtualserver.org,LVS 实际上相当于基于 IP 地址的虚拟化应用,为基于 IP 地址和内容请求分发的负载均衡提出了高效的解决方法,现在 LVS 已经是 Linux 内核标准的一部分。
使用 LVS 可以达到的技术目标是:通过 LVS 达到的负载均衡技术和 Linux 操作系统实现一个高性能高可用的 Linux 服务器集群,具有良好的可靠性、可扩展性和可操作性,从而以低廉的成本实现最优的性能。
在现实的网络环境中,主机之间的通信都是通过配置静态路由(默认网关)来完成的,而主机之间的路由器一旦出现故障,就会通信失败。
因此在这种通信模式下,路由器就会有单点瓶颈问题,为了解决这个问题,引入了VRRP 协议(虚拟路由冗余协议),通过VRRP可以在网络发生故障时透明的进行设备切换而不影响主机之间的数据通信。
VRRP可以将两台或多台物理路由器设备虚拟成一个虚拟路由器,这个虚拟路由器通过虚拟IP(一个或多个)对外提供服务,而在虚拟路由器内部是多个物理路由器协同工作,VRRP角色如下:
1、角色
master路由器由选举算法产生,它拥有对外服务的VIP,提供各种网络服务,如ARP请求、数据转发、ICMP等等,而backup路由器不拥有VIP,也不对外提供网络服务
当master发生故障时,backup将重新进行选举,产生一个新的master继续对外提供服务。