一时重构一时爽,一直重构一直爽

news2024/11/28 9:40:26

笔者(后台技术汇)恭祝各位大佬:2023年春节快乐,兔年祥瑞。

d0ccafbe1282cfb410a715468d156a0a.png

距离上次更新,已经过去5个月有余了,有小伙伴疑惑笔者是不是删库跑路了..

其实不是,这段时间是在参加一次比较大的项目重构(目前已经基本完成了功能灰度,节后可以实现全面覆盖)。这期间的工作量简直“让人发指”,历史包袱非常巨大,重构过程更是触目惊心,我只能暂时放下键盘,回去搬砖了..

在春节难得的私人时间里,以及往后空余时间,我会继续高质量文章输出的,非常感谢大家一直以来的支持。

0d2e1dc819787e4b75caafea29270aef.png

业务重构做了什么

为了避险,下面已对信息进行脱敏处理,这里先提及一下背景:

  1. 我们的业务系统是个大而全的应用单体系统。

  2. 部门此前经历了应用上云,更使用了先进的K8S进行容器资源编排管理;

  3. 生产环境的应用仍旧偶发性出现OOM,进而出现容器调度重启的情况,导致接口超时或500,在业务低峰期甚至直接影响SLA;

  4. 另外一个促使我们进行业务重构的原因,则是生产环境的DB资源面临着巨大压力,经常有定位到是DB导致的业务问题(部门在数据库资源的投入一直是非常慷慨的,基本观点是:如果堆资源能解决的问题,决不轻易重构业务),这里举几个例子说明:DB主从库延时导致的业务一致性问题、慢SQL问题、并发SQL。

业界对系统重构的态度一向是非常谨慎的,一般情况下不建议对老系统进行重构,毕竟重构是有代价的。

箭在弦上不得不发,严峻的SLA挑战和不断闪烁的告警,让组内领导下定了决心:必须进行业务重构!

接下来就是确定目标:我们组内开了很多次会议,根据产品形态和需求关联,圈出业务迁移的影响范围。其实这块跟业务息息相关了,是没法在一篇文章里面详细说尽的,尤其是技术文,尽可能的做到脱离业务需求,专注技术层面。

用一句话总结业务重构就是:将原本单体业务里的耗时逻辑优化重构、对DB单库的大表拆分、对过去设计不合理的表结构进一步重构聚合,最后以微服务形态进行落地,达到业务重构拆分的目的。

最后就是人力排期:

- 这次重构拆分的工作量巨大,几乎动员了所有需求相关的前后台开发同事;

- 重构过程里,由于存在复杂的API调用链,我们开了数次会议,拉通上下游部门进行协同开发;

27e39e3efeda866060d77ec3209c71df.png

83a44a0e42714ab015657cbc6fa3610d.png

遇到难题了,怎么办?

在重构过程里,团队每个成员分工负责自己所负责的模块内容,以周例会形式,把问题抛出来讨论,最终把同类问题归类解决。

- 项目管理问题

由于这次重构是偏向后台系统的,所以PM是我们的一位后台开发大佬。“时间紧任务重”是整个过程的基调,加班加点是经常的事情,不过花了很多时间,却仍然没能全部规避掉人力冲突问题。

比如,最大的冲突就是,在重构过程中,组长确定了迭代要歇一段时间,但产品一直催促上某个迭代改动,这种情况研发就比较被动了。但也不是没有解决办法..

49c9d5c740b79ff03edfba50a0df9e6e.jpeg

- 业务方案问题

老项目是2017年开发的,当时基于SpringMVC开发了前后端,很多页面渲染逻辑都是在JSP里,因此这次重构遇到了前后端分离的问题;

1、API向上兼容是最常见的问题。

在业务性很强的服务来说,在业务开始之前需要有复杂的校验,如果在这个服务中支持多种业务类型,还需要根据不同的业务类型来选择不同的校验逻辑,因此在服务中将校验栈独立出来。

下面讲述一个简单场景:业务拆分会把原来的订单库,按业务维度分为电商订单和物流订单,并进行数据分库处理;这就导致原来查出两种类型数据的API,要两边查库返回同个模型的数据。

这里我们简单使用了装饰器模式,对Dao层进行增强处理。

所有DB的增删改查,都统一走Decorator:

- 未灰度的API,返回Dao1的分页数据;

- 灰度的API,返回Dao2的分页数据。

c09a92f18cebb69d808da32704e5afc8.png

2、跨库分页检索数据一直是个难题,我们借助了ES来实现,这里其实没有太多可以展开说的了,都是纯业务的内容。但也有2个地方值得注意:

【2.1】一个是数据同步方案(Mysql -> ES)的优化;

【旧方案】Maxwell 监听 binlog + kafka数据订阅 + Es写入

855bbbb88d20af177994d23f18e92e28.png

不足:日常容灾演练,会随时断掉了maxwell对主库DB的监听,此时影响到下游ES消费。如果要对 maxwell 拓展维护主从切换,难免增加了部署维护的昂贵使用成本。

【新方案】基于腾讯云DTS 的数据订阅能力+ Es写入

b12c55611f7134e17692285de84e8aed.png

参考公开资料:https://www.shangyun51.com/productdetail?id=358

【2.2】ES分页方案

【1】from&size 分页越深,查询越慢

【2】search_after 方案,深度分页效率高

【3】scroll api方案

三种方案都有其优劣,按照业务对深度分页的强烈与否,去决定使用哪一种方案比较合适。

  • from/size方案的优点是简单,缺点是在深度分页的场景下系统开销比较大,占用较多内存。

  • search after基于ES内部排序好的游标,可以实时高效的进行分页查询,但是它只能做下一页这样的查询场景,不能随机的指定页数查询。

  • scroll方案也很高效,但是它基于快照,不能用在实时性高的业务场景,建议用在类似报表导出,或者ES内部的reindex等场景。

结论:最终我们使用了from/size方案,因为数据深度分页的场景,用户的需求并不强烈;更加强烈的是对数据同步的敏感度。

3、微服务内部RPC限流

在微服务体系下,针对ES读写我们分别采用不同的锁方案,读操作使用了客户端限流,写操作使用了单机限流。

由于业务的读写操作在服务层面就做了隔离,因此可以直接对服务A和服务C进行不同策略的限流方案。

- 由于读操作QPS比写操作QPS高出几个量级,因此使用客户端限流(基于Guava的工具类实现),后续即使进行了容器扩缩容,也不至于hold不住。

- 由于写操作仅发生在服务B(这是无状态服务),一般不会随意扩缩容,因此可以通过简单的锁同步(比如Semepohore)即可实现限流。

c25cac231b017c4df0c6cc49afc8054f.png

64cfb41460bea306871709363b3400c9.png

总结

3dd6a32f9b115600f237b37b07be57d6.gif

以上只是一点点的浅浅回顾,还有很多知识点来不及分享(性能监控、指标梳理等),只能后续抽空继续写文章了。

总结一下,我们在重构前要有足够的业务思考,重构中要备份足够的技术深度和业务复杂度解决方案,重构后的上线更是非常复杂。

后续主要分下面几个模块来细说:

1、项目脚手架:抽象业务公共能力

2、Mybatis的插件编写:解决SQL的租户id注入和语法检测

3、线程池环境下的ThreadLocal内存泄漏问题

4、性能监控工具

往期推荐

《互联网技术峰会》

《ArchSummit:从珍爱微服务框架看架构演进》

《ArchSummit_2022_全球架构峰会》

《2021年深圳ArchSummit全球架构师峰会》

《经典书籍》

《Java并发编程实战:第1章 多线程安全性与风险》

《Java并发编程实战:第2章 影响线程安全性的原子性和加锁机制》

《Java并发编程实战:第3章 助于线程安全的三剑客:final & volatile & 线程封闭》

《服务端技术栈》

《Docker 核心设计理念》

《Kafka原理总结》

《HTTP的前世今生》

《算法系列》

《读懂排序算法(一):冒泡&直接插入&选择比较》

《读懂排序算法(二):希尔排序算法》

《读懂排序算法(三):堆排序算法》

《读懂排序算法(四):归并算法》

《读懂排序算法(五):快速排序算法》

《读懂排序算法(六):二分查找算法》

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

学习笔记 —— python代码耗时及内存占用测试方法

1、手写耗时测试 先看结果; 主要有三种方法,各自的时钟间隔如下: time.time() timeit time.time_ns() ( time is outputted in ns!). 可见方法2,即timeit 的时钟间隔最短。 注:最后一个是以ns为单位的,前两个是…

二叉树的概念与结构

文章目录前言一、树的概念及结构1.树的概念2.树的相关概念3.树的表示4. 树在实际中的运用二、二叉树概念及结构1.概念2.特殊的二叉树5.二叉树的性质6.二叉树的存储结构(1).顺序存储(2).链式存储结语前言 因为二叉树的知识点太多,一篇文章讲不…

《真象还原》读书笔记——第一章 部署工作环境

环境: 由于平时使用 windows 系统 所以 linux 环境 使用了 linux子系统。 $ cat /proc/version Linux version 4.4.0-22000-Microsoft (MicrosoftMicrosoft.com) (gcc version 5.4.0 (GCC) )1.1 工欲善其事 必先利其器 操作环境很重要呀。 1.2 编译器 GCC: gc…

Java 23种设计模式(8.结构型模式-桥接模式)

结构型模式-桥接模式 代码分析 类图 代码 public interface Implementor {void operation(); }public class ConcreteImplementorA implements Implementor{Overridepublic void operation() {System.out.println("A");} }public class ConcreteImplementorB imple…

(Java高级教程)第四章必备前端基础知识-第二节3:CSS盒模型和浮动

文章目录一:盒模型(1)border(2)padding(3)margin二:flex布局一:盒模型 盒模型:在HTML中,每个标签(或元素)相当于是一个盒…

DaVinci:色彩匹配

z调色页面:色彩匹配Color:Color Match色彩匹配 Color Match调板是专业的一级调色工具,专门用于对视频图像进行精准的校色还原。色彩匹配时,先定位到视频中持有色卡的画面。在检视器左下角快捷菜单中选择“色卡” Color Chart工具&…

C 语言零基础入门教程(十二)

C enum(枚举) 枚举是 C 语言中的一种基本数据类型,它可以让数据更简洁,更易读。 枚举语法定义格式为: enum 枚举名 {枚举元素1,枚举元素2,……};接下来我们举个例子,比如:一星期有 7 天,如果不用枚举&…

【Linux】vim编辑器的使用

文章目录vim的基本概念vim指令集复制粘贴撤销、剪切光标定位vim的基本概念 vim是一款多模式的编辑器,在我们常用的模式有3~5种。分别是命令模式(command mode)、插入模式(Insert mode)和底行模式( last lin…

【PHP 随记】—— ThinkPHP 配置数据库

👉总目录👈\large\colorbox{skyblue}{👉总目录👈}👉总目录👈​ 文章目录1、数据库连接及导入① 数据库连接② 数据库导入2、配置 ThinkPHP 数据库连接信息① 配置连接信息1、数据库连接及导入 ① 数据库连…

大数据分析案例-基于随机森林算法构建人口普查分析模型

🤵‍♂️ 个人主页:艾派森的个人主页 ✍🏻作者简介:Python学习者 🐋 希望大家多多支持,我们一起进步!😄 如果文章对你有帮助的话, 欢迎评论 💬点赞&#x1f4…

Datawhale 202301 设计模式 | 人工智能 现代方法 习题

Exercise 1 绪论 Q:用您自己的话来定义:(a)智能,(b)人工智能,(c)智能体,(d)理性,(e)逻…

【大数据趋势】1月24日 流动、固定汇率和货币政策独立性三者的三者选二,A股持续的会上涨。

前言:昨天写的被朋友看到,认为我写的太水,故意不提日常讨论的那个关键指标,所以下午重新修改了一下。 确定欧美大势市场形态1 - 美元指数 关键位置大概率不会一次就破,有较强反弹可能,带动美股反弹 作为长…

MH-100X微波运动传感器介绍

MH-100X微波运动传感器简介微波运动传感器是利用多普勒雷达原理设计的微波移动物体探测器。不同于一般的红外探测器,微波传感器通过通过检测物体反射的微波来探测物体的运动状况,检测对象将并不会局限于人体,还有很多其他的事物。微波传感器不…

java基础语法——条件判断与循环语句

目录 一、流程控制语句 流程控制语句分类 二、顺序结构 顺序结构概述 顺序结构图 三、选择结构 选择结构概述 选择结构(if语句1) 选择执行图1 选择结构(if语句2) 选择执行图2 选择结构(if语句3) 选择执行图3 选择结构(switch语句) switch语句执行流程图 四、 循环…

剪映电脑版超简单使用教程Mac

相机 我主要用到的两个键 点击开始创作导入本地视频 导入本地视频 将素材拖拽到时间线上 时间线面板操作 撤销、恢复、分割 撤销上一次操作也可以用快捷键 command z 定格、倒放、镜像、裁剪 剃刀 点击菜单的分割可以出来一个剃刀,分割更方便 选择模式 …

代码随想录算法训练营第十二天|239. 滑动窗口最大值| ● 347.前 K 个高频元素

239 滑动窗口最大值 看完题后的思路 这是一道典型的单调队列的题,如果不是之前刷过一遍,对这道题没有一点头绪。即使刷过,也只是留了个印象。 解题思路 对于本道题来说,到窗口右移,如果一个新元素a进入窗口&#x…

【Maven】分模块开发与设计与依赖管理

目录 一、分模块开发与设计 1. 分模块开发的意义 2. 分模块开发(模块拆分) 二、依赖管理 1. 依赖传递 2. 可选依赖 3. 排除依赖 4 可选依赖和排除依赖的区别 一、分模块开发与设计 1. 分模块开发的意义 问题导入 分模块开发对工程有什么好处…

ChatGPT - 横看成岭侧成峰

定义 ChatGPT 是什么? ChatGPT是由OpenAI开发的一个人工智能聊天机器人程序,由 OpenAI 公司于2022年11月推出。该程序使用基于GPT-3.5架构的大型语言模型并通过强化学习进行训练。 ChatGPT以对话方式进行交互,可以用于包括自动文本生成、自…

一起自学SLAM算法:8.3 LOAM算法

连载文章,长期更新,欢迎关注: 不管是Gmapping还是Cartographer,通常都是采用单线激光雷达作为输入并且只能在室内环境运行。虽然Cartographer支持2D建图和3D建图模式,但是Cartographer采用3D建图模式构建出来的地图格式…

微信小程序 java失物招领系统uniAPP设计

开发语言:Java 框架:ssm JDK版本:JDK1.8 服务器:tomcat7 数据库:mysql 5.7 数据库工具:Navicat11 开发软件:eclipse/myeclipse/idea Maven包:Maven3.3.9 基于微信小程序的失物招领系…