本文分享自华为云社区《Sermant在异地多活场景下的实践》,作者:华为云开源。

Sermant社区在1.3.0和1.4.0版本相继推出了消息队列禁止消费插件数据库禁写插件,分别用于解决异地多活场景下的故障切流和保护数据一致性问题。本文将对Sermant在异地多活场景下的实践进行剖析。

一、异地多活

1.1 什么是异地多活

对于一个软件系统,我们希望当系统出现故障时仍然可以正常对外提供服务,软件系统的这种特性称之为高可用, 异地多活架构便是用来解决高可用问题的。

最早的系统架构一般为单机架构,当数据库出现故障时,可能会导致业务长时间中断。为了解决这一问题,数据库发展为由主库和从库组成,主库负责读和写操作,从库只提供读操作,主数据库的数据会实时同步至从数据库保持数据的一致性和完整性。当主库出现问题时,从库切换为主库继续工作。不过,这些服务都部署在同一机房甚至是同一个机柜,当机房出现故障后,系统仍然不能正常对外提供服务。

此时,同城双活成为很好的解决方案,在一个城市部署两个机房,两个机房部署相同的软件环境,并且均提供服务。当其中一个机房出现故障时,可以将流量切换至另一个机房继续执行,以保证系统的高可用。如图一所示,机房1数据库为主数据库,两个机房所有的写操作均操作机房1的主数据库,读操作则可以读取本机房的数据库。两个机房部署的物理距离较近,同时两个机房可以使用专线进行网络连接,因此不同机房服务调用的网络延迟较低,机房2的服务写入机房1的数据库时延在可接受范围内。

图一:同城双活架构图

同城双活架构很好地解决了软件系统的高可用问题,但是城市如果出现了自然灾害,比如地震、水灾等,这些部署在同一城市的所有机房仍然会受到损害从而停止提供服务。并且因为这些灾害的破坏性较强,系统修复的周期也会相对漫长,会严重影响公司业务的正常运行。在这种情况下,很明显需要这些机房部署在不同的地域,同时这些地域的地理距离需要足够遥远,这样就能抵抗自然灾害的风险,这就是异地多活架构的由来和价值所在。

针对上图,机房1和机房2如果部署在两个城市,就变成了异地双活,为了更好的抵御风险,可以在多个地域部署机房,这样异地双活就升级为了异地多活。

异地多活的架构图如图二所示,客户端的流量通过路由层分发至不同的地域机房执行。和同城双活架构不同的一点在于不同地域的机房物理距离遥远,部署网络专线的成本巨大且不现实,不同机房之间访问的网络时延是不可忽视的,因此需要操作本机房内的数据库,不能跨机房操作。在异地多活架构下,每个机房的数据库均为主库,不同机房的数据会同步至中心机房,并由中心机房再同步至其他机房。因为所有机房的数据库都可以写入,当不同机房修改同一条数据时,就不可避免的引入了数据冲突的问题。为了解决数据冲突,可以在路由层根据分片策略使一些流量固定转发到某一机房,流量分片的策略可以基于业务类型或地理位置。通过流量分片,保证同一用户的相关请求,会路由至同一个机房内完成所有业务操作,并且机房内的流量保证只在本机房内流转,降低网络延迟。

图二:异地多活架构图

1.2 异地多活典型场景

异地多活架构通过在不同地域部署机房对外提供服务来抵御自然灾害带来的风险,是实现系统高可用的有效手段。但是,异地多活架构也使系统变得更加复杂,在故障切流、数据一致性等方面引入了新的需求:

  • 云服务场景下,当某可用区发生故障时,需要故障区的消费者停止拉取消息进行消费,同时将已分配的消息队列重平衡给正常可用区的消费者处理,从而避免引发业务异常。
  • 异地多活通过对流量分片处理,可以很好地解决数据一致性问题。但是对于全局数据,比如商品数量,在写入数据时,只允许操作中心机房的全局数据库。一般需要将操作全局数据的流量路由至中心机房,其他机房只允许读该数据库。当流量路由错误时,仍可能会写入非中心机房的数据库,导致数据冲突问题。此时需要对全局数据库添加防护,在非中心机房禁止写操作的执行。

针对以上两个典型问题,Sermant分别开发了消息队列禁止消费插件和数据库禁写插件来处理,下文将详细介绍。

二、消息队列禁止消费插件

2.1 消息队列禁止消费插件介绍

消息队列禁止消费插件允许微服务在运行态根据实际需求动态调整消费者对消息队列中间件的消费行为,确保在非正常环境或状态下,业务处理流程中的消息得到妥善管理,避免不必要的业务影响。例如,在异地多活架构系统中,如果发生区域性故障需要对流量做切流处理时,可在发生故障的可用区开启消息队列禁止消费功能,让正常可用区的消费者来处理业务,避免故障区域消费流量从而导致业务异常,保障系统的高可用。待故障处理完成后,可重新开启消费。

消息队列禁止消费插件目前支持Kafka和RocketMQ两种消息中间件。在Kafka方面,该插件实现了Topic级别的禁止和恢复消费功能。对于RocketMQ, 控制消费的粒度为消费者实例级别。Sermant支持通过配置中心下发需要禁止消费的消息队列类型和具体Topic。

关于消费队列禁止消费插件更多的介绍、配置说明和场景演示等请参考官网文档消息队列禁止消费

2.2 消息队列禁止消费插件故障切流场景应用

应用场景:某软件系统使用Kafka作为消息队列,生产者往topic-test主题生产消息,该topic消息包含四个partition。可用区A和可用区B各有两个消费者加入test消费者组并消费topic-test的消息,每个消费者各分配一个partition,其中可用区A和可用区B分布在不同地域,即异地多活的两个机房。如下图所示。

该场景下,消费者服务通过挂载Sermant的消息队列禁止消费插件运行后,可以实时控制消费者消费的主题,从而确保在非正常环境或状态下,业务处理流程中的消息得到妥善管理。

当可用区A发生故障后,可用区A的消费者应该停止消费。在可用区A下发全局配置禁止消费者A和消费者B消费topic-test主题,并释放已分配的消息队列。

消息队列禁止消费插件的配置如下所示,enableKafkaProhibition表示开启Kafka队列禁消费能力,kafkaTopics指明需要禁止消费的订阅主题Topic。下发配置的方式请参考官网文档消息队列禁止消费

enableKafkaProhibition: true
kafkaTopics:
- topic-test

配置下发后,可用区A的消费者停止消费,可用区B消费者重新分配topic-test主题的partition,如下图所示。

待可用区A恢复正常后,可以重新通过动态配置中心下发配置,开启消费者A和B对topic-test主题的消费。开启消费配置下发后Kafka将触发重平衡,可用区A和B的消费者重新分配partition。

消息队列禁止消费插件实现了异地多活场景下消息队列的故障切流能力,保障了系统的可用性。

三、数据库禁写插件

3.1 消息队列禁止消费插件介绍

服务在挂载数据库禁写插件启动后,可以动态开启或关闭对指定数据库的禁止写入能力。在异地多活场景下,用户希望停止对个别或全部数据库的写入操作,仅允许读取数据,以保证数据库系统的数据完整性、一致性和安全性。比如,某业务数据库全局数据写入仅允许操作中心机房,通过开启数据库禁写插件,使路由异常流量写入非中心机房数据库失败;多地多写场景下,对流量手动切流前,被切流的机房先禁止写入数据库,等待其他机房数据同步完成后,再进行切流。以上场景中数据库禁写插件的使用保障了数据库数据的一致性。

数据库禁写插件目前支持MySQL、MongoDB、PostgreSQL和OpenGauss数据库。在微服务运行时,可以通过配置中心下发禁写的数据库类型和名称。支持禁写的具体写操作和插件使用方式请参考官网文档数据库禁写

3.2 数据库禁写插件保护数据一致性应用

应用场景:异地多活架构下,某业务微服务用于修改商品库存等全局数据,同时全局数据保存在名为global的MySQL数据库中。对于该全局数据,写操作仅允许操作中心机房的global数据库,其他机房的global数据库只能读取数据。为了保证数据一致性,当修改全局数据时,该流量在路由层被路由至中心机房执行,其他读操作可路由至任意机房,如下图所示。

当路由层对写全局数据的流量发生路由错误从而在非中心机房执行时,如果中心机房和非中心机房同时修改同一商品的数量,就可能导致数据冲突问题,为了防止这种情况的发生,业务微服务可以挂载Sermant的数据库禁写插件,禁止在非中心机房写入global数据库。

在非中心机房禁止写入global数据库,需要通过动态配置中心下发如下配置:

enableMySqlWriteProhibition: true
mySqlDatabases:
- global

其中,enableMySqlWriteProhibition表示开启对MySQL数据库的禁写能力,mySqlDatabases用于指明具体的禁写数据库名称,本示例为global数据库。

下发配置后,当路由异常的流量在非中心机房写入global数据库时,数据库禁写插件对业务微服务抛出java.sql.SQLException异常,并禁止写入该数据库。业务系统需要处理该异常,比如加入重试操作重新路由该流量至中心机房执行,以保证系统的正常运行,执行逻辑如下图所示。

数据库禁写插件在异地多活场景下禁止对指定数据库的写入能力可以防止异常流量的写操作,保证不同机房数据库的数据一致性。

四、总结

在异地多活场景下,Sermant的消息队列禁止消费插件可以实现可用区故障时消息队列的切流问题,让正常可用区的消费者消费数据;数据库禁写插件则用于禁止写入指定的数据库,并且不影响读数据库,防止发生数据冲突问题。

Sermant在异地多活场景实现了丰富的服务治理能力,未来,Sermant还将持续发力,逐步构建更加完善的服务治理能力体系。

Sermant作为专注于服务治理领域的字节码增强框架,致力于提供高性能、可扩展、易接入、功能丰富的服务治理体验,并会在每个版本中做好性能、功能、体验的看护,广泛欢迎大家的加入。

点击关注,第一时间了解华为云新鲜技术~

Sermant在异地多活场景下的实践的更多相关文章

  1. 【转】MySQL乐观锁在分布式场景下的实践

    背景 在电商购物的场景下,当我们点击购物时,后端服务就会对相应的商品进行减库存操作.在单实例部署的情况,我们可以简单地使用JVM提供的锁机制对减库存操作进行加锁,防止多个用户同时点击购买后导致的库存不 ...

  2. MySQL乐观锁在分布式场景下的实践

    背景 在电商购物的场景下,当我们点击购物时,后端服务就会对相应的商品进行减库存操作.在单实例部署的情况,我们可以简单地使用JVM提供的锁机制对减库存操作进行加锁,防止多个用户同时点击购买后导致的库存不 ...

  3. B 站崩了,总结下「高可用」和「异地多活」

    你好,我是悟空. 一.背景 不用想象一种异常场景了,这就真实发生了:B 站晚上 11 点突然挂了,网站主页直接报 404. 手机 APP 端数据加载不出来. 23:30 分,B 站做了降级页面,将 4 ...

  4. 不同场景下 MySQL 的迁移方案

    一 目录 一 目录 二 为什么要迁移 三 MySQL 迁移方案概览 四 MySQL 迁移实战 4.1 场景一 一主一从结构迁移从库 4.2 场景二 一主一从结构迁移指定库 4.3 场景三 一主一从结构 ...

  5. 秒杀场景下MySQL的低效(转)

    秒杀场景下MySQL的低效 2016-01-14 17:12 178人阅读 评论(0) 收藏 举报 最近业务试水电商,接了一个秒杀的活.之前经常看到淘宝的同行们讨论秒杀,讨论电商,这次终于轮到我们自己 ...

  6. MySQL金融应用场景下跨数据中心的MGR架构方案(2)

    GreatSQL社区原创内容未经授权不得随意使用,转载请联系小编并注明来源. 如何在多个数据中心部署多套MGR集群,并实现故障快速切换. 上篇文章介绍了如何在多数据中心部署多套MGR集群,并构建集群间 ...

  7. ADO.NET Entity Framework 在哪些场景下使用?

    在知乎回答了下,顺手转回来. Enity Framework已经是.NET下最主要的ORM了.而ORM从一个Mapping的概念开始,到现在已经得到了一定的升华,特别是EF等对ORM框架面向对象能力的 ...

  8. CephRGW 在多个RGW负载均衡场景下,RGW 大文件并发分片上传功能验证

    http://docs.ceph.com/docs/master/radosgw/s3/objectops/#initiate-multi-part-upload 根据分片上传的API描述,因为对同一 ...

  9. 荔枝FM架构师刘耀华:异地多活IDC机房架构 - 极客头条 - CSDN.NET

    荔枝FM架构师刘耀华:异地多活IDC机房架构 - 极客头条 - CSDN.NET 荔枝FM架构师刘耀华:异地多活IDC机房架构 - 极客头条 - CSDN.NET 途牛谭俊青:多数据中心状态同步&am ...

  10. Entity Framework:如果允许模型处于非法状态,在某些场景下,记得清空DbContext

    Entity Framework:如果允许模型处于非法状态,在某些场景下,记得清空DbContext 背景 之前写过两篇文章介绍模型的合法性: DDD:关于模型的合法性,Entity.IsValid( ...

随机推荐

  1. copy 导入包含特殊符号的文本

    客户提供了一份数据记录需要导入数据库,但是文本中有一个列的内容是反斜杠"\" ,因为""是特殊的转义字符,需要使用两个"\"才能表示,如果直 ...

  2. UE4 c++重构简单死亡之眼的效果

    虚幻社区中有蓝图教学视频 使用C++重构,主要用到UGameplayStatics类中的SetGlobalTimerDilation方法,以及角色的相机管理器的调用,之后通过StartCameraFa ...

  3. debian12 linux root能用lightdm登陆xfce桌面,普通用户不能用lightdm登陆xfce桌面,闪一下黑屏和一个_,又回到lightdm

    Fn+Ctrl+F3,进入tty,发现登陆普通用户后再使用startxfce4可以直接进桌面 下面参照 https://forums.opensuse.org/t/normal-user-can-no ...

  4. vector优化

    C++的stdvector使用优化 #include<iostream> #include<vector> using namespace std; class Vectex ...

  5. #背包#nssl 1488 上升子序列

    题目 给一个长度为\(n\)的数组\(a\).试将其划分为两个严格上升子序列,并使其长度差最小. 分析 当\(max([1,i])<min([i+1,n])\)时显然两个区间互不影响,把\(i\ ...

  6. 在Keycloak中实现多租户并在ASP.NET Core下进行验证

    Keycloak是一个功能强大的开源身份和访问管理系统,提供了一整套解决方案,包括用户认证.单点登录(SSO).身份联合.用户注册.用户管理.角色映射.多因素认证和访问控制等.它广泛应用于企业和云服务 ...

  7. OpenHarmony有氧拳击之应用端开发

    一.简介 继<OpenHarmony有氧拳击设备端的开发>后,本次为大家带来酷炫的应用端开发.如下,开发者伴随着音乐,律动出拳后,那开发板屡屡播放"挨打"效果,这究竟是 ...

  8. Git 安全远程访问:SSH 密钥对生成、添加和连接步骤解析

    使用 SSH 密钥对的 Git 安全远程访问:生成.添加和连接 SSH(Secure Shell)是一种用于安全远程访问的协议,它提供了加密通信和身份验证机制.在使用 SSH 连接到远程 Git 存储 ...

  9. Docker学习路线13:部署容器

    部署容器是使用Docker和容器化管理应用程序更高效.易于扩展和确保跨环境一致性性能的关键步骤.本主题将为您概述如何部署Docker容器以创建和运行应用程序. 概述 Docker容器是轻量级.可移植且 ...

  10. JS实现文件转base64

    核心: function file2base64(){ fileAddress = document.getElementById("fileImage").files[0]; f ...