使用 Feature Flags 与可观测工具实现数据库灰度迁移

场景描述

很多企业会遇到数据库升级、或数据库迁移的情况,尤其是在自建数据库服务向云数据库服务、自建机房向云机房、旧数据库向新数据库迁移等场景。
然而,我们需要在整个移植过程中保证其稳定性、避免数据遗失、服务宕机等情况,最常见的移植方法之一就是数据库双写移植操作

解决方案

如下图所示,这个双写移植的过程为:

  1. 原始阶段,程序只对一个旧数据库进行读写。
  2. 在现有的读写旧数据库的代码程序基础上,需要添加读写新数据库的代码。例如,在某个表中插入一条数据时,我们需要把这条数据同时插入到新旧两个数据库中。通常情况下,我们会并行执行这两个插入操作,以尽可能保持服务的原有调用处理时间。
  3. 当一个写数据库请求进来,我们将其写入旧数据库的同时,将一个很少的百分比流量写入新的数据库。
  4. 将写入新数据库的流量比缓慢提高,直到 100% 为止。在这个过程中如果出现问题,可以及时回滚,并在不影响生产环境服务的情况下进行修复。
  5. 写移植完成后,开始逐步放量从新的数据库中读取数据返回给服务,如先允许 10% 的流量在新数据库做读操作。在这个过程中测量性能的同时对比结果,如果在读操作中遇到问题,可以马上回滚新数据库的读流量,并在不影响生产环境服务的情况下进行修复。
  6. 直到在新数据库实现 100% 的读写操作一段时间没有问题后,就可以停止与旧数据库相关的代码服务了。

在实际操作过程中,不止新旧数据库的操作流量要逐渐开放,实际上新的数据库的读写代码也需要逐步的更新到生产环境服务中,以确保可迭代的稳定平滑移植。

实践方法与工具

整个过程中,除了自身系统架构的设计外,有两个特别的工具在其中起到重要环节:

  1. 负责可灵活、实时、稳定放量、回滚的 Feature Flags 服务 (FeatBit)。
  2. 在整个过程中全方位(支持无侵入和针对性埋点模式)的监测服务异常与及时报警的可观测服务 (观测云)。

使用 FeatBit 实现实时的数据库移植请求流量控制

如下代码所示,为某一个服务的数据库读取操作分流的示例伪代码:

  • 第 6 行代码,调用 _fbService.BoolVariation("read-sport-olddb") 方法获得流量控制返回值,如果为 true,则将读取旧数据库的 Query 函数添加到并行任务执行队列中。
  • 第 9 行代码,调用 _fbService.BoolVariation("read-sport-newdb")方法获得流量控制返回值,如果为 true,则将读取新数据库的 Query 函数添加到并行任务执行队列中。
  • 第 19 行代码,为使用 FeatBit Feature Flags SDK 同时运行两个数据库读取操作,并将结果进行对比验证,根据执行情况返回正确值,并向观测云发送相关异常数据。
public async Task<List<Sport>> GetSportsByCityAsync(int cityId, int pageIndex, int pageSize)
{var tasks = new List<Task<List<Sport>>>();// 当读取 Sport 相关业务的旧数据库开关返回 true 时,则添加读取任务到执行任务队列if (_fbService.BoolVariation("read-sport-olddb")){tasks.Add(GetSportsByCityQueryAsync(_oldDbContext, cityId, pageIndex, pageSize));}// 当读取 Sport 相关业务的新数据库开关返回 true 时,则添加读取任务到执行任务队列if (_fbService.BoolVariation("read-sport-newdb")){tasks.Add(GetSportsByCityQueryAsync(_newDbContext, cityId, pageIndex, pageSize));}// 同时执行两个读操作(为了避免新增数据读取增加请求时间),并将结果进行对比并返回// 如果结果不一致,则返回旧数据库读取结果,并进行记录return await _fbService.RunAndCompareDbTasksAsync(tasks,timeoutDelayForNewDB: 3000, // 设定新数据库的最长等待时间,避免不良体感(timeoutInfo) => { }, // 当新数据库调用超时,发信息至观测云(unMatchInfo) => { }, // 当返回结果不一致时,发信息至观测云(exception) => { } // 当出现异常时,发信息至观测云);
}

在把类似于上述的代码逐步的集成到我们的项目中之后,就可以通过 FeatBit 提供的 Feature Flags 控制中心来控制每一个对应的数据库移植的双写双读放量工作了。例如我们先将 feature flag read-sport-from-newdb 放量调整到 5%,若在一段时间未在观测云中观察到异常状况,增大放量百分比至 10% (如下图)。

使用观测云观测移植全过程,及时发现潜在问题

在整个的数据迁移过程中,自动化的、及时发现错误问题并回滚,是极为重要的。他可以最有效的帮我们避免诸多问题,如:

  • 新数据库操作带来巨大的系统资源消耗时,我们需要第一时间知道并通过 Feature Flags 系统立刻回滚。
  • 当某个写操作或读操出现时间操作超时数量超过预估阈值时,我们可以快速定位问题,回滚的同时进行快速的修复,提高移植的速度。
  • 当某个写操作或读操作出现信息错误时(如结果不一致、请求时间过长、程序异常等),我们可以根据观测系统具体定位错误信息,从而加速 debug 的速度。
  • 等等

实现这些,我们只需要:

  1. 根据《观测云文档:快速入门》,选择与自己业务相符的技术栈,进行小白式的在 15 分钟内完成配置和安装。
  2. 运行你已有的服务程序,开始你的数据库系统移植。
  3. 打开观测云控制台的「应用性能检测」页面,定位到链路,你将看到所有服务的运行情况。

通过「链路」与「错误追踪」快速定位移植错误

通过「链路」页面,我们发现在移植过程中,出现了一些红色项(即 Error),通过资源列可以轻松的看到我们在对新数据库的读取操作中出现了错误异常,如下所示:

点击对应的 Error,我们可以快速查看其对应的调用链路火焰图。如下图所示,根据火焰图的解释:

  1. 如下图 位置的 Span 所提示,在这个地方出现了数据库移植的 Timeout 错误,即新数据库的读取时间超出了我们可以接受的请求响应时间阈值。
  2. 如下图 位置中,指出错误发生在 Feature flag read-sport-newdb 为 true 的情况下面。也就是说我们可以快速定位可能需要回滚或关掉的 Feature Flags,从而避免移植风险。
  3. 而根据 位置 Span 可以快速定位出现超时现象的服务端 API 服务,并且根据捕捉到的 API 的参数与 Header,可以帮助我们后面去更好的调试解决问题。

通过 Feature Flags 实时将读操作回滚至无超时状态

根据上面的「链路」查找方式,我们快速定位到了出现异常的数据库读操作。那么,我们只需要回到 FeatBit 的后台界面,找到上面发现的开关 read-sport-newdb,并将其放量为 true 的百分比向后回滚即可。如下图所示,将 true 的百分比从 10% 回滚到之前未出现读数据异常的 5%的流量分配。

回滚后,下面代码所示的 _fbService.BoolVariation("read-sport-newdb") 返回值,只会将有 5% 的比率为 true。

// 当读取Sport相关业务的新数据库开关返回 true 时,则添加读取任务到执行任务队列
if (_fbService.BoolVariation("read-sport-newdb"))
{tasks.Add(GetSportsByCityQueryAsync(_newDbContext, cityId, pageIndex, pageSize));
}

总结与后续

这篇文章介绍了使用观测云与 FeatBit 通过双写双读的操作方式实现了降低数据库移植风险的基础方法。
在实际运行中,我们可能有大量的业务需要处理,人为的介入和操作会因为各种原因造成反应不及时的问题。在后续的文章中,我们将介绍更多的内容,如:

  • 使用观测云的指标服务与 FeatBit 的 Trigger 服务,实现移植时自动化实时回滚避灾与报警方案。
  • 使用观测云的指标服务与 FeatBit 的 Scheduler 服务 ,实现自动化的放量与回滚方案。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/103575.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Spring】一次性打包学透 Spring | 阿Q送书第五期

文章目录 如何竭尽可能确保大家学透Spring1. 内容全面且细致2. 主题实用且本土化3. 案例系统且完善4. 知识有趣且深刻 关于作者丁雪丰业内专家推图书热卖留言提前获赠书 不知从何时开始&#xff0c;Spring 这个词开始频繁地出现在 Java 服务端开发者的日常工作中&#xff0c;很…

BTP Integration Suite学习笔记 - (Unit4) Developing with SAP Integration Suite

详细指导还是要看官方文档 4. 云集成管理 4.1 云集成介绍 什么是云集成&#xff1f; 前三章讲了很多内容&#xff0c;但都不是最核心的&#xff0c;通常我们用CPI是让他实现原来PI/PO的功能的&#xff0c;是用来做集成的。这章才刚开始。 云集成有以下几个特性&#xff1a;…

Django进阶:DRF(Django REST framework)

什么是DRF&#xff1f; DRF即Django REST framework的缩写&#xff0c;官网上说&#xff1a;Django REST framework是一个强大而灵活的工具包&#xff0c;用于构建Web API。 简单来说&#xff1a;通过DRF创建API后&#xff0c;就可以通过HTTP请求来获取、创建、更新或删除数据(…

【SVN内网穿透】远程访问Linux SVN服务

文章目录 前言1. Ubuntu安装SVN服务2. 修改配置文件2.1 修改svnserve.conf文件2.2 修改passwd文件2.3 修改authz文件 3. 启动svn服务4. 内网穿透4.1 安装cpolar内网穿透4.2 创建隧道映射本地端口 5. 测试公网访问6. 配置固定公网TCP端口地址6.1 保留一个固定的公网TCP端口地址6…

SpringBoot整合阿里云OSS,实现图片上传

在项目中&#xff0c;将图片等文件资源上传到阿里云的OSS&#xff0c;减少服务器压力。 项目中导入阿里云的SDK <dependency><groupId>com.aliyun.oss</groupId><artifactId>aliyun-sdk-oss</artifactId><version>3.10.2</version>…

在ubuntu+cpolar+rabbitMQ环境下,实现mq服务端远程访问

文章目录 前言1.安装erlang 语言2.安装rabbitMQ3. 内网穿透3.1 安装cpolar内网穿透(支持一键自动安装脚本)3.2 创建HTTP隧道 4. 公网远程连接5.固定公网TCP地址5.1 保留一个固定的公网TCP端口地址5.2 配置固定公网TCP端口地址 前言 RabbitMQ是一个在 AMQP(高级消息队列协议)基…

开源的密码学工具库:openssl安装在docker容器环境Linux(ubuntu18.04)

OpenSSL&#xff08;Open Secure Socket Layer&#xff09;是一个开源的密码学工具库&#xff0c;它提供了一系列的加密、解密、认证和通信安全相关的功能。OpenSSL 最初是为了支持安全的网络通信而设计的&#xff0c;但后来它的功能逐渐扩展到了许多不同的领域&#xff0c;包括…

多核异构核间通信Mailbox vs rpmsg

目录 一、关键术语解释 二、Mailbox与rpmsg对比 三、rpmsg传输流程 异构核间数据通过共享内存实现数据传递&#xff0c;通过中断来触发发送、接收。 一、关键术语解释 IPC Inter-Processor Communication MailBox IP which provides queued interrupt mechanism for comm…

javaWeb第一课

前言&#xff1a; 先来说说本来写完了的聊天室的项目&#xff0c;然后后面凡尔赛不小心改错了的然后一个上午才发现的问题&#xff0c;真的很有必要总结一下&#xff0c;气死我了&#xff1a;关于要将这个ArrayList的某个类型要转换为数组&#xff0c;我刚开始这么写的&#x…

leetcode 118.杨辉三角

⭐️ 题目描述 &#x1f31f; leetcode链接&#xff1a;https://leetcode.cn/problems/pascals-triangle/description/ 代码&#xff1a; class Solution { public:vector<vector<int>> generate(int numRows) {// 先开空间vector<vector<int>> v;v.…

【数据结构】C语言实现栈(详细解读)

前言: &#x1f4a5;&#x1f388;个人主页:​​​​​​Dream_Chaser&#xff5e; &#x1f388;&#x1f4a5; ✨✨专栏:http://t.csdn.cn/oXkBa ⛳⛳本篇内容:c语言数据结构--C语言实现栈 目录 什么是栈 栈的概念及结构 实现栈的方式 链表的优缺点: 顺序表的优缺点: 栈…

AI创作助手:介绍 TensorFlow 的基本概念和使用场景

目录 背景 环境测试 入门示例 背景 TensorFlow 是一个强大的开源框架&#xff0c;用于实现深度学习和人工智能模型。它最初由 Google 开发&#xff0c;现在已经成为广泛使用的机器学习框架之一。 TensorFlow 简单来说就是一个用于创建和运行机器学习模型的库。它的核心概念…

2023年骨传导耳机推荐,一文读懂骨传导运动耳机哪个牌子好!

这几年&#xff0c;耳机圈开始流行起骨传导耳机&#xff0c;这种耳机通过贴合耳道附近的颌骨通过振动传递声音到听觉神经&#xff0c;相比较入耳式耳机来说&#xff0c;更有利于耳道卫生&#xff0c;而且在听歌同时可保持对环境声的感知&#xff0c;深受不少运动达人的喜爱。我…

LVS之keepalived

1、keepalived 概述 总结&#xff1a;Keepalived 软件就是通过VRRP协议来实现高可用功能。 应用场景&#xff1a;企业应用中&#xff0c;单台服务器承担应用存在单点故障的危险 单点故障一旦发生&#xff0c;企业服务将发生中断&#xff0c;造成极大的危害 VRRP通信原理&…

【Rust】Rust学习 第十六章无畏并发

安全且高效的处理并发编程是 Rust 的另一个主要目标。并发编程&#xff08;Concurrent programming&#xff09;&#xff0c;代表程序的不同部分相互独立的执行&#xff0c;而 并行编程&#xff08;parallel programming&#xff09;代表程序不同部分于同时执行&#xff0c;这两…

iOS逆向初探:揭开iOS App的神秘面纱

逆向是一种分析和还原应用程序的过程&#xff0c;它能够揭示应用程序内部的工作原理和代码结构。接下来我们将全面介绍iOS上的逆向&#xff0c;包括其概念、常用工具和具体实例。 1. 什么是iOS逆向&#xff1f; iOS平台逆向是将应用程序的二进制代码&#xff08;通常是经过编…

使用PyMuPDF添加PDF水印

使用Python添加PDF水印的博客文章。 C:\pythoncode\new\pdfwatermark.py 使用Python在PDF中添加水印 在日常工作中&#xff0c;我们经常需要对PDF文件进行处理。其中一项常见的需求是向PDF文件添加水印&#xff0c;以保护文件的版权或标识文件的来源。本文将介绍如何使用Py…

反向传播求变量导数

反向传播求变量导数 1. 相关习题2. 推导流程2.1 相关公式2.3 变量导数求解 3. 代码实现3.1 参数对应3.2 代码实现 以前只知道反向传播通过链式法则实现今天看书发现图片上求出来的值自己算不出来所以自己算了一下&#xff0c;记录一下&#xff0c;并运行了书中的代码相关书籍&a…

第一讲使用IDEA创建Java工程——HelloWorld

一、前言导读 为了能够让初学者更快上手Java,不会像其他书籍或者视频一样,介绍一大堆历史背景,默认大家已经知道Java这么编程语言了。本专栏只会讲解干货,直接从HelloWord入手,慢慢由浅入深,讲个各个知识点,这些知识点也是目前工作中项目使用的,而不是讲一些老的知识点…

java学习004

常用数据结构对应 php中常用的数据结构是Array数组&#xff0c;相对的在java开发中常用的数据结构是ArrayList和HashMap&#xff0c;它们可以看成是array的拆分&#xff0c;一种简单的对应关系为 PHPJAVAArray: array(1,2,3)ArrayListlArray: array(“name” > “jack”,“…