22 重构系统升级-实现不停服的数据迁移和用户切量

专栏的前 21 讲,从读、写以及扣减的角度介绍了三种特点各异的微服务的构建技巧,最后从微服务的共性问题出发,介绍了这些共性问题的应对技巧。

在实际工作中,你就可以参考本专栏介绍的技巧构建新的微服务,架构一个具备“三高”能力的后台服务。同时,也可以利用所学的技巧对已有的微服务进行系统升级重构,从而解决历史遗留问题。

升级重构是后台架构演化增强的一个利器,本讲将为你详细讲解如何落地对用户无感知、低 Bug 的升级重构方案。

重构常见的形式

升级重构有两种常见的形式,一种是纯代码式的升级,另外一种是包含存储和代码的升级。

纯代码的重构升级是指只针对代码中存在的一些历史遗留问题进行修复,比如代码中的慢 SQL、错误的日志打印方式、代码中未显式开启事务等问题。

注:在本讲,将存在问题的历史版本称为V1 版;修复问题后的升级重构版本称为 V2 版。纯代码的重构升级架构如下图1所示:

图 1:纯代码的升级重构对比图

包含存储和代码的重构升级是指在上述纯代码之外,将原有架构里的存储也一起升级。存储升级有两种形式。

第一种是将存储类型进行升级,比如将数据库升级为缓存,将原有的读接口从数据库切换至缓存。做此类存储类型升级的目的是提升微服务的性能,我们在模块二中曾介绍,同样的硬件配置下,缓存比数据库至少快一个量级。不同类型的存储升级架构如下图 2 所示:

图 2:不同类型的存储升级架构对比图

可以看到升级后,原有的代码从 V1 升级到 V2。同时,存储从读写都使用数据库,升级为写操作使用数据库,读操作使用缓存的架构。

第二种是将一个表结构的存储升级为同类型存储的另外一个更加合理的表结构。此类升级常见于系统构建时,为了快速满足业务需求,在时间紧张的情况下,简单快速地设计了不是特别合理的表结构。比如原有的表结构采用了一张宽表存储所有的数据,包含一对多的数据都进行冗余存储。升级重构时,需要采用更加合理的表结构存储数据,以便未来能够快速响应业务的发展。它的重构升级架构如下图 3 所示,升级后,原有微服务的读写都将切换至新的表结构的存储里。

图 3:同类型不同表结构的存储升级架构对比图

纯代码重构的切换

纯代码重构的切换比较简单,当上述 V2 版本通过测试环境和预发布环境的测试后,就可以直接在线上部署,替换原有的V1 版本。当部署的 V2 版本出现问题后,直接进行回滚即可,这是最简单、粗暴的切换方式。但同时也存在隐患,采用此种方式部署的V2如果出现问题,会影响所有的用户,影响面较大。

为了降低影响,可以采用灰度的方式。即用 V2 版本的代码替换一台或者一定比例 V1 版本的机器,比如线上有 100 台部署 V1 版本代码的机器,当 V2 版本测试完成准备上线时,可以先发布 10 台 V2 版本的代码。这样,假设 V2 版本的代码存在 Bug,也只会影响访问这 10 台部署了 V2 版本代码的用户,即 10%的线上流量,这样就缩小了影响面。假设发布了 10 台 V2 版本的代码后,没有发现任何 Bug,此时则可以继续发布,逐步进行替换。

通过此种灰度的方式,既可以做到纯代码的升级重构切换,又可以缩小因此可能带来的线上问题的影响范围。

含存储重构的切换

与上述纯代码的切换相比,含存储的重构切换有一个重要步骤便是数据迁移。不管是上述不同类型的存储还是同类型不同表结构的存储重构,都需要将原有存储中的数据全部迁移至新的存储中,才能够称为完成切换。

对于含存储重构的切换,最简单的方法便是停服,之后在无任何数据写入的情况下进行数据迁移,迁移之后再进行数据对比,对比无误之后,用重构的新版本连接新的存储对外提供服务即可。

这种方式适合于以下 2 种场景:

  • 业务有间断期或者有低峰期的场景。比如企业内网系统,下班或者周末期间几乎没有人使用;

  • 金融资产类业务,这些业务对于正确性要求极高,因为用户对资产极度敏感,如果资产出现错误,用户是无法容忍的。为了资产安全无误,有时候需要用户容忍停服的重构升级。

但对于用户量巨大,且大部分业务场景都需要提供 7*24 服务的互联网业务来说,停服切换方式,用户是不能接受。因此,就需要设计一套既不需要停服,又可以完成用户无感知的切换方案。

切换架构

为了实现不停服的重构升级,整体的新版本上线、数据迁移以及用户切量的架构如下 图 4 所示:

图 4:不停服的切换架构

上述的架构中,左边部分是老版本未重构的服务及对应的老数据存储(后续称为老存储),图中右边部分部署的是升级重构后的新版本的服务和对应的新版本存储(后续称为新存储)。这个存储可以是缓存或者是表结构不同的数据库。

在图的下方,则是数据同步模块。它主要的作用是实时进行数据同步,将老存储里的历史数据、新增的写入以及更新的数据实时地同步至新存储里。实时数据同步是实现存储升级重构不停服切换的基础。

在完成数据同步之后,便可以进行用户的灰度切量了,将用户逐步切换至升级重构的新版本上。见图 4 中最上面的部分。

下面将对图 4 中涉及的各个部分进行详细讲解。

数据同步

当升级重构后的新版本开发及测试完成后,便可以将新版本代码和存储进行线上部署了。新版本部署时,可以将新版本服务对外提供的接口的别名变更为一个新的名称,如为:new_version,具体见上图 4。因为修改了别名,即使新版本的服务上线部署并直接对外了,也不会引入老版本的流量。

通过上述方式可以实现新老版本的隔离,进而完成新版本服务的线上部署。新版本线上部署及隔离后,便可以进行数据同步了。

数据同步分为历史数据的全量同步和新增数据的实时同步。在上述“含存储重构的切换”小节里介绍过,存储重构涉及两个种类,第一种是数据库到缓存,第二种是数据库到另一种异构的表结构数据库里。这里以使用场景较多的数据库到缓存的重构举例讲解,另一种场景比较类似,你可以按此方式自己推演。如果有疑问,也可以写在留言区,我们一起讨论。

包含全量同步、增量数据的实时同步架构如下图 5所示:

图 5:全量同步和增量同步架构

上述第一步的全量同步(见图 5 的编号 1 处)是将历史数据进行一次全量初始化同步,可以采用 Worker 的方式,对老版本的数据库的数据进行遍历,遍历的 SQL 大致如下:

select 数据 from t_table where id> last_id limit 一批次的数量

从数据库遍历读取完之后,便会在同步服务模块里按缓存的格式进行数据格式的转换,转换后的数据写入缓存即可。

上述的数据同步 SQL 没有停止条件,且在未切量前,老库一直会有数据持续写入。使用上述 SQL 进行同步时,会导致全量同步一直执行,出现无法停止的情况。针对这个问题,可以根据当前数据库已有数据量、数据增长的速度以及数据同步的速度,评估在数据同步期间能够产生的数据量,并评估出这期间最多可能产生的数据 ID(截止 ID),并将上述 SQL 修改如下:

select 数据 from t_table where id> last_id and id<截止ID limit 一批次的数量

第二步的增量实时同步是在开始进行全量同步时启动的,增量同步使用的是本专栏多次介绍的Binlog 进行。通过在增量同步模块订阅老版本数据库里的数据变更,可以实时获取老版本数据库中新增和变更的数据。

需要注意的是,增量同步需要在全量同步开始前便进行Binlog的订阅。如果在全量同步结束后,再订阅 Binlog 进行增量同步,可能会丢失在全量同步期间发生变更的数据。

比如一张待同步的数据表里有 100 条数据,如果在全量同步前未开启增量同步。当同步至第 90 条数据时,第80 条数据发生了 update 操作,因为此时还没有开启增量同步,那么这第 80 条数据对应的变更就丢失了。为了防止此问题,就需要前置开启增量同步。

最后,增量同步除了需要订阅 update 和 delete 操作外,还需要订阅 insert 操作。因为全量同步在上述截止 ID 之后的数据便不会再同步了,需要增量同步处理此类操作。

数据对比验证

在完成数据迁移之后,并不是立马就能够开始用户切量。还需要做一步非常重要的事情,那便是进行测试。因为做了大规模的代码重构以及存储的切换,只靠人工测试是远远不够的,很容易出现场景遗漏。

因此就需要借助自动化的方式进行测试,我想你还记得在“第 07 讲:基于流量回放的自动化回归测试”的内容。在完成全量数据同步后,可以录制老版本服务的流量,并进行自动化测试回归,它的架构如下图 6 所示:

图 6:自动化的数据对比验证架构图

通过一定时间区间的自动化回归,可以保证场景不被遗漏,极大地减少重构切换可能导致的问题,具体如何进行自动化和发现问题,你可以参考“第 07 讲”的内容。

在自动化回归中,可能会出现的某一类问题需要特殊处理,因为增量同步延迟会导致数据对比不一致。原则上这类问题不应该存在,因为基于Binlog的主从同步延迟非常小。但如果遇到上述情况,因为增量同步的时延很小,所以我们可以等待几分钟后再次运行对比不一致的回放请求。

用户切换

完成数据对比之后,下一步需要落地的便是用户切换了。进行用户切换时,有几个原则需要遵循:

  • 切量不能一刀切,即不能一次将所有的用户全部切换至新版本服务里,需要灰度逐步地将用户从老版本切换到新版本服务里;

  • 在灰度切量时,需要尽早发现问题,而不是等到切量快完成的时候才发现问题。

对于上述的几个要求,在切量的具体落地时,可以从以下几点着手落地。

对于影响面小的要求。

首先,对于升级重构的系统涉及的所有用户进行分析并按等级划分。可以按用户的注册时间、是否为会员等进行划分。如果重构的模块是订单模块,可以将用户按历史以来的下单量、订单金额进行排序,订单量小、下单金额低的用户排在最前面。

在用户按上述的维度排序后,可以将用户分为几大批次,比如将所有用户按排序分为五等份。第一等份的用户因为单量小、下单金额少,可以最先进行切换,这样便满足前述提到的“出问题影响面少”的要求。

对于在切量时,尽可能早发现问题的要求。

对上述排序的第一等份的用户,再次进行分析和分类。我们知道,一个系统对外一般会提供多个功能点,比如用户模块会对外提供用户注册、查询用户基本信息、修改个人签名等功能。可以对第一等份里的用户进行数据分析,分析这些用户里哪些用户使用了较多的系统功能。在分析后,可以按使用功能的多少对第一等份里的用户进行排序,使用功能较多的用户排序在前面。在切量时,第一等份里使用系统功能最多的用户会优先进行切量,这也满足了前面所要求的尽可能多发现问题的要求。

本节总结

本讲介绍了系统升级重构的两种常见的类型。并分别介绍了这两种类型在升级重构后,如何实施让用户尽可能少感知的切换方案。

同时,在包含存储的系统升级重构切换方案里,借鉴了很多本专栏前面介绍过的技术方案,比如基于Binlog的数据同步、基于流量回放的自动化回归方案等。

由此可以看出,很多技术方案之间都是相互依赖的、相互连通的,甚至是成体系的。所以建议你在学习本专栏各讲的内容时,尝试寻找知识之间的联系,完善自己的知识体系,这样才能将专栏里的知识融会贯通,真正应用到实际的业务场景里。

最后,留一道思考题给你,你认为互联网大厂的 App 和后台系统的上线发版是如何灰度切流的?欢迎写在留言区,我们一起讨论。

这一讲就到这里,感谢你学习本次课程,接下来我们将学习 23 | 重构:烟囱式、平台化、中台化的架构演化

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

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

相关文章

图像处理的基本操作

一、PyCharm中安装OpenCV模块 二、读取图像 1、基本语法 OpenCV提供了用于读取图像的imread()方法&#xff0c;其语法如下&#xff1a; image cv2.imread&#xff08;filename&#xff0c;flags&#xff09; &#xff08;1&#xff09;image&#xff1a;是imread方法的返回…

前后缀分离,CF1209 C. Maximal Intersection

目录 一、题目 1、题目描述 2、输入输出 2.1输入 2.2输出 3、原题链接 二、解题报告 1、思路分析 2、复杂度 3、代码详解 一、题目 1、题目描述 2、输入输出 2.1输入 2.2输出 3、原题链接 Problem - 1029C - Codeforces 二、解题报告 1、思路分析 线段相交具有可…

预编码算法学习笔记

文章目录 1. 基本原理2. 常见应用2.1 自编码器2.2 变分自编码器2.3 稀疏自编码器 3. 学习笔记 在机器学习领域&#xff0c;预编码算法是一种强大的工具&#xff0c;用于将高维数据映射到低维表示&#xff0c;从而提取数据中的重要特征。本文将介绍预编码算法的基本原理、常见应…

分布式与一致性协议之拜占庭将军问题(三)

拜占庭将军问题 叛将先发送消息 如果是叛将楚先发送作战消息&#xff0c;干扰作战计划&#xff0c;结果会有所不同吗&#xff1f; 在第一轮作战信息协商中&#xff0c;楚向苏秦发送作战指令"进攻",向齐、燕发送作战指令"撤退"&#xff0c;如图所示(当然还…

SpringCloud 学习笔记 —— 六、Ribbon:负载均衡(基于客户端)

SpringCloud 学习笔记 —— 一、背景-CSDN博客 SpringCloud 学习笔记 —— 二、微服务与微服务架构-CSDN博客 SpringCloud 学习笔记 —— 三、SpringCloud 入门概述-CSDN博客 SpringCloud 学习笔记 —— 四、SpringCloud Rest 学习环境搭建&#xff1a;服务提供者-CSDN博客 …

Linux 的静态库和动态库

本文目录 一、静态库1. 创建静态库2. 静态库的使用 二、动态库1. 为什么要引入动态库呢&#xff1f;2. 创建动态库3. 动态库的使用4. 查看可执行文件依赖的动态库 一、静态库 在编译程序的链接阶段&#xff0c;会将源码汇编生成的目标文件.o与引用到的库&#xff08;包括静态库…

对话访谈——五问RAG与搜索引擎:探索知识检索的未来

记一次关于RAG和搜索引擎在知识检索方面的对话访谈&#xff0c;针对 RAG 与传统搜索引擎的异同,以及它们在知识检索领域的优劣势进行了深入的探讨。 Q&#xff1a;传统搜索引擎吗&#xff0c;通过召回-排序的两阶段模式&#xff0c;实现搜索逻辑的实现&#xff0c;当前RAG技术也…

数字旅游:通过科技赋能,创新旅游服务模式,提供智能化、个性化的旅游服务,满足游客多元化、个性化的旅游需求

目录 一、数字旅游的概念与内涵 二、科技赋能数字旅游的创新实践 1、大数据技术的应用 2、人工智能技术的应用 3、物联网技术的应用 4、云计算技术的应用 三、智能化、个性化旅游服务的实现路径 1、提升旅游服务的智能化水平 2、实现旅游服务的个性化定制 四、数字旅…

想要接触网络安全,应该怎么入门学习?

作为一个网络安全新手&#xff0c;首先你要明确以下几点&#xff1a; 我刚入门网络安全&#xff0c;该怎么学&#xff1f;要学哪些东西&#xff1f;有哪些方向&#xff1f;怎么选&#xff1f;这一行职业前景如何&#xff1f; 其次&#xff0c;如果你现在不清楚学什么的话&…

vim的IDE进阶之路

一 ctags 1 安装 安装ctags比较简单&#xff0c;我用的是vim-plug&#xff0c;网络上随便一搜应该就有很多教程&#xff0c;而且没有什么坑 2 使用 vim之函数跳转功能_nvim函数跳转-CSDN博客https://blog.csdn.net/ballack_linux/article/details/71036072不过针对cuda程序…

Java基础_集合类_List

List Collection、List接口1、继承结构2、方法 Collection实现类1、继承结构2、相关类&#xff08;1&#xff09;AbstractCollection&#xff08;2&#xff09;AbstractListAbstractSequentialList&#xff08;子类&#xff09; 其它接口RandomAccess【java.util】Cloneable【j…

【LAMMPS学习】八、基础知识(5.3)Body particles体粒子

8. 基础知识 此部分描述了如何使用 LAMMPS 为用户和开发人员执行各种任务。术语表页面还列出了 MD 术语&#xff0c;以及相应 LAMMPS 手册页的链接。 LAMMPS 源代码分发的 examples 目录中包含的示例输入脚本以及示例脚本页面上突出显示的示例输入脚本还展示了如何设置和运行各…

Go 学习笔记

Go 学习相关笔记 Go 官方的教学文档顺序不怎么友好&#xff0c;这里根据我自己的学习曲线来记录文档的查看顺序 基础知识 文档预备 新手先要看 Go 的模块管理介绍&#xff0c;这样才知道基础 Go 怎么导入外部包和进行本地的包管理 https://go.dev/doc/modules/managing-dep…

【快速入门】数据库的增删改查与结构讲解

文章的操作都是基于小皮php study的MySQL5.7.26进行演示 what 数据库是能长期存储在计算机内&#xff0c;有组织的&#xff0c;可共享的大量数据的集合。数据库中的数据按照一定的数据模型存储&#xff0c;具有较小的冗余性&#xff0c;较高的独立性和易扩展性&#xff0c;并为…

本地CPU搭建知识库大模型来体验学习Prompt Engineering/RAG/Agent/Text2sql

目录 1.环境 2.效果 3.概念解析 4.架构图 5. AI畅想 6.涉及到的技术方案 7. db-gpt的提示词 1.环境 基于一台16c 32G的纯CPU的机器来搭建 纯docker 打造 2.效果 3.概念解析 Prompt Engineering &#xff1a; 提示词工程 RAG&#xff1a; 检索增强生成&#xff1b; …

CTFHub-Web-SQL注入

CTFHub-SQL注入-WP 1.整数型注入 1.题目说输入1&#xff0c;先将1输入查看结果 2.接着输入4-1&#xff0c;发现输出的结果为4-1&#xff0c;判定存在整数型注入 3.查询字段数&#xff0c;出现了回显&#xff0c;判断这里的字段数为2 1 order by 24.判断注入点在2的位置&…

复杂度(3)

目录 1.二分查找的时间复杂度 2.斐波那契数列及其优化 3.空间复杂度 1.二分查找的时间复杂度 我们熟知的二分查找绝对是一种很厉害的算法&#xff0c;因为这个算法每进行一次都会砍掉一半的数据&#xff0c;相当于是指数级增长&#xff0c;假设我们刚开始的时候数据的个数是…

MS8241/MS8242高速、高输出电流、电压反馈放大器

产品简述 MS8241/MS8242 是一颗高速的电压反馈放大器&#xff0c;具有电流 反馈放大器的高速转换特性&#xff0c;可以应用在所有传统的电压反馈运 放应用方案中。 MS8241/MS8242 能够稳定工作在低增益环路下 &#xff08;增益为 2 和 -1 &#xff09;&#xff0c;仅消耗…

Java项目:基于SSM框架实现的实践项目管理系统(ssm+B/S架构+源码+数据库+毕业论文+开题报告)

一、项目简介 本项目是一套基于SSM框架实现的实践项目管理系统&#xff0c;主要针对计算机相关专业的正在做毕设的学生与需要项目实战练习的Java学习者。 包含&#xff1a;项目源码、数据库脚本等&#xff0c;该项目附带全部源码可作为毕设使用。 项目都经过严格调试&#xff…

【算法】【贪心算法】【leetcode】870. 优势洗牌

题目地址&#xff1a;https://leetcode.cn/problems/advantage-shuffle/description/ 题目描述&#xff1a; 给定两个长度相等的数组 nums1 和 nums2&#xff0c;nums1 相对于 nums2 的优势可以用满足 nums1[i] > nums2[i] 的索引 i 的数目来描述。 返回 nums1 的任意排列&…