45 | 架构重构内功心法第一式:有的放矢
45 | 架构重构内功心法第一式:有的放矢
讲述:黄洲君
时长10:23大小4.75M
小结
赞 16
提建议
精选留言(46)
- 孙振超2018-10-06思考了下当前负责的系统,感觉更多的是需要优化而不是重构,主要原因是如果从新来过还是会采用当前的结构,只是功能需要进一步完善和改进。 之前做过一次缓存架构的重构(自认为的):我们的系统是3地5中心的部署架构,我们数据的写入是固定在一个机房进行单点写入,然后同步到其他的集群去,db层面的同步是通过数据库自身的主从同步机制实现的;而缓存的同步则是通过消息中间件来进行的,写入集群发送消息,其他集群接收消息而后写入到各地的缓存集群中。写入时是db写入成功就认为写入成功,返回调用方成功。这种实现方式虽然有数据同步延迟和少量的缓存db数据不一致,但对于绝大多数场景都是可以接受。 后来随着业务的发展,出现了写入后立即读的场景(读和写不在同城),并且不允许读到的数据和写入的数据不一致。在这种情况下原有的缓存更新机制就有问题了:db写入成功缓存消息处理失败或者读请求时消息还没有到达异地机房,这时都会导致缓存和db数据不一致,引起业务异常。 面对此种场景,最初提出的解决方案是让业务方在调用写服务成功后再调用读服务,如果读到的数据和写入的数据一致才进行后续的操作,但这种方案实现总体成本比较高:如果有5个调用方,5个调用方都需要这样修改,重复工作,并且做了不需要自己关注的内容;同时在调用读请求时还要考虑重试机制,实现方案也有些复杂。这个方案提出来后没有一个调用方按照这个做的。 后面进行review的时候决定还是应该自己来做这件事,对外屏蔽复杂性。因而对这一块进行了重构:将缓存内容根据缓存key按照一定的规则进行分区存储,对于实时性和一致性要求高的数据采取同步写缓存操作,如果缓存写失败,直接返回业务方本次写操作失败,由业务方重试。同时本地发送一个删除缓存的消息,异步将缓存删除,确保之后有机会从db中读取最新的数据。这样改造完成后,整体的请求耗时(因为要跨区同步写缓存)和业务失败率有所增加,但满足业务方的需求。 这个改造简要而言是将业务从pa模式改为了pc模式。展开
作者回复: 很好的案例👍
共 9 条评论70 - 吴科🍀2018-08-09系统优化,我们公司就是一个字,拆,拆数据库,拆服务,没有依赖就没有伤害
作者回复: 经典,没有依赖就没有伤害,但实际上我们依赖还是少不了,我们尽量降低依赖程度,接口依赖是比较可控的
共 2 条评论33 - 彼得.林2018-08-09总之,架构重构需要架构师既要说得动老板,也要镇得住同事;既要技术攻关,又要协调资源;既要保证业务正常发展,又要在指定时间内完成目标……总之就是十八般武艺要样样精通。 老师,这些都是架构师的软技能吧?市场上的课都偏技术,可以讲讲这些吗?谢谢展开
作者回复: 这个够开三个专栏了😄并且我也不太擅长这些软技能培训
18 - 宋岩2018-08-10老师您好,我们现在面临一个运行18年的.net业务系统,业务一刻不能停止,大约2000张oracle表,大量的存储过程函数等实现的业务逻辑,现在要用java来重构,面临的问题就是好多大表都在Oracle中,想去o就涉及到很多表关联,做不到垂直拆分,业务耦合太紧,您有什么好的建议或者我们该从哪方面切入?
作者回复: 1. 数据先不动,先拆分代码到多个子系统,然后再拆分数据 2. 重写一套新的,然后做数据割接 老板决心大的话,方案2实施更快,但风险高;老板决心不大的话,那就方案1,实施周期长,风险会小一些
共 6 条评论17 - one day2018-08-09我公司正巧在重构系统。定期3个月。电商系统。原来是dubbo 服务间调用 ,redis 缓存,mysql,模块化开发,云平台,svn。问题,关联查询太多,dubbo部署的相关模块太多,业务复杂度太高,业务调用同步慢,一搞活动,数据库就爆,业务逻辑懂的人换了一茬又一茬。目标spring cloud,docker,k8s,git,禁止关联查询即单表,解藕慢操作即异步,接口细粒度,层次调用分明,服务隔离能缓存就缓存,业务大拆解。最终会是什么样,静待。学了老师这么多,手术台上实习了,哈哈. 缓存,异步,事务消息最终一致,强制单表查询,业务边界,规范。牵一发动全身,业务等待,加班加班……展开
作者回复: 感觉这样还是没有有的放矢呢,重构不是什么问题都解决。 例如关联查询,电商业务是不可避免的,禁止关联查询,业务改动非常大,如果是关联查询导致性能问题,首先应该分析一下慢查询,80%的慢查询集中在20%的语句上。 例如慢操作改为异步,实现起来没那么容易,有的就是要同步调用,而有的可以用消息队列异步通知异步处理。
共 3 条评论16 - allen.huang2018-08-12老师,我们现在公司遇到的问题和你说的X系统很相似,现在也在逐步将那些热门业务做成微服务,拆分出去,但是涉及到的数据表,拆到其它RDS上去,涉及到的跨库查询很麻烦。现在只能做成接口了
作者回复: 这个没办法避免,短期内大家会不习惯,原来一条SQL语句搞定的事情,现在要调用接口还要改逻辑,但长远来看是好的,SQL的问题在于后续的系统越来越复杂后,很容易出现将整个系统拖垮的慢查询,业务扩展也很麻烦,因为逻辑都在SQL中了
共 2 条评论12 - 空档滑行2018-08-09当前的系统刚刚做过一次重构,当时选择重构的原因有这么几个,原系统有一个大的面向客户的web系统和多个单独的进程组成,前后端在一个war包,后端服务单机远行,两者通过db交换数据。问题有这么几个,web系统累积了5年的代码,改个bug已经随时搞挂整个web端。后端服务单点问题。数据库压力很大,一个功能的sql拖垮整个库。 重构的思路是,先将单体后端进程服务化,服务化过程中非核心数据从主表分离出来。web系统结构不动,上线一个服务就从原来的查db改成调用服务。服务梳理差不多了将web端重新实现前后端分离。做完这些后将数据库结构重新设计。总的来说跟文中的第三个例子有点像。展开
作者回复: 思路很清晰👍👍
10 - 波波安2018-09-04我们系统目前的瓶颈在数据存储,之前数据的存储都是oracle加上redis做缓存。现在活跃用户在500万左右。拿卡券业务来说,每个月产生的优惠券数量都在6000万左右,导致现在需要运维每两个月就要对表做瘦身,并且前端用户也只能查询两个月内的卡券。 目前讨论的技术方案是使用mycat做分库分表,数据库使用mysql。遇到的问题有事务控制的问题,典型的就是卡券转赠,之前在oracle就直接利用数据库事务就可以解决。现在由于转赠记录和受赠记录不会落在同一个库,所以需要程序做策略来保证最终一致性。展开
作者回复: 这样做没问题,是普遍的做法
7 - 黑小子在路上2018-08-10目前系统采用类似微服务模式。如有1后台管理,2商家pc后台,3商家app接口服务,4server,都是独立部署。前面的1 2 3都依赖4。目前的问题是1也会访问数据库,server也访问数据库,有一部分重复。2 和3 也有重复逻辑。目前一个小需求,都可能要改多个端,由多个人介入,开发成本比较高。 近期准备重构,使用多模块形式来聚合工程,提取公用服务,但会保留现有独立部署模式,以此来达到提效的目的:-O
作者回复: 多模块聚合不是好的重构手段,版本开发和测试部署一样比较麻烦,我认为你们应该将公共功能独立为服务
共 3 条评论5 - lyonger2020-03-28架构师的要求好高啊,既要对业务非常熟悉,也能精通各种技术,其次还要能hold住人心。
作者回复: 不然工资高就没理由了😂
5 - Leon Wong2018-11-05双中心如何同步数据?比如我在A中心写入了数据,此时未同步到B,并且发生了宕机,B此时是没有这个数据,还允许被再写入一次,这种场景如何避免数据不一致呢?
作者回复: 要业务上考虑兼容,底层存储无法避免。
共 2 条评论5 - 钱2019-09-05课后思考及问题 我们的系统正在重构中,并且已经搞了一年左右,重构的系统在验证中,由于老系统本身业务逻辑比较复杂又是0级系统,一旦有问题秒秒钟就会影响大批订单,所以,不完全验证OK不敢上。 重构的原因: 第一业务运维困难,特别是大促、节假日时,页面配置复杂,并且不灵活 第二系统已经运行5年+补丁太多,代码臃肿,理解、开发、测试困难,同时存在第一代及第三代的代码,原来的老代码不敢删除,各种分支判断令人眼花缭乱,有些逻辑已经不知道为啥那样写 第三有人想要更好的KPI 上不了的原因: 第一系统太过复杂,想想看一个方法像老鼠洞一样一层套一层,看完一个方法需要一两天,另外,重构的也不是一个系统,有负责页面配置的系统,有专门负责刷新缓存的系统,有专门负责对外提供服务的系统,有专门负责核心业务逻辑计算的系统,有专门负责持久化数据的系统等 第二改了逻辑但还需要覆盖原来的业务,验证困难 第三领导核心关注点在后台业务逻辑,页面也非常多和复杂,但是压根没有测试,目前业务验证自然会发现很多bug 第四主产品离职了,另外小组长也离职了,他俩级别挺高,组长听说是家庭原因,主产品比较奇怪,他不但级别高工资高而且资格老没人管,他也离职啦 第五团队氛围不佳,安排活都给你细到小时,管人的方式采用雪橇犬理论的方式 第五想一次重构结构N个问题,已不是最初的业务运维困难的痛点了,这就好像和华仔讲的相反——无的放矢 没有聚焦解决一个问题,后面问题扩大化啦 抱歉,借华仔的地盘发一下牢骚哈😄 1:本文核心观点 1-1:重构系统的基本原则——从一大堆纷繁复杂的问题中识别出真正要通过架构重构来解决的问题,集中力量快速解决,而不是想着通过架构重构来解决所有的问题 1-2:重构时架构师要做的事情——架构师需要透过问题表象看到问题本质,找出真正需要通过架构重构解决的核心问题,从而做到有的放矢,既不会耗费大量的人力和时间投入,又能够解决核心问题。 1-3:如何判断系统实现需要重构——假设我们现在需要从 0 开始设计当前系统,新架构和老架构是否类似?如果差异不大,说明采取系统优化即可;如果差异很大,那可能就要进行系统重构了。 有的放矢,如果提炼一下有两点: 第一定位出问题的真正根源是什么 第二聚焦解决主要矛盾的主要方面展开
作者回复: 现在还准备上么😂😂😂
共 6 条评论4 - 一叶2018-10-04华哥请问一下文中ab系统双中心改造,是数据分区还是两个中心都有完整数据。 1.如果是分区,那其中一个中心宕掉之后,部分人或业务在另外一个中心是没法使用的? 2.如果是完整的数据,当网络出现异常的时候,不是出现脑裂?
作者回复: 两个中心都有完整数据。 网络异常时,两个中心各自都可以服务,只有一部分用户如果先在A机房注册,再到B机房注册,可能会有重复数据产生,我们的业务用算法保证数据重复产生是一样的,因此没问题
共 2 条评论3 - 陈树义2020-05-07重构真的是一门艺术,不仅需要技术过人,还需要有经验,更要有洞察力。 专业技能到家了,但是没有经验,很可能大刀阔斧地全部重做。但这样的后果就是出问题的风险很大,并且基本上会难产。只有有经验,才知道怎么一点点去重构。另外也需要洞察哪些东西是最重要的,哪些是不重要的,挑合适的功能先一点点做。 简单概括:重构也需要小步快跑,一点点做,这样成功率更高!展开
作者回复: 是的,步子大了会扯淡😂
2 - 张玮(大圣)2018-08-09确定是不是要重构挺难的,那就等到问题频出,改到想吐的时候做重构吧, 大公司在创新,小公司也在创新,一般2.3年的系统设计不会太差吧,除非影响业务了,影响老板心情了, 归纳下:能优化的别修补,能修补的别重构,保证核心业务OK,更好的支撑创新业务线发展吧 哈哈 如果要重构,拉都拉不住,那就做好预备方案,保证新旧系统并行,时间可控,做好切换时风险控制,要不然,萌萌哒,😄展开
作者回复: 是的,架构重构是大动作,不要轻易采用,大招不要乱放😀
3 - flyCoder2020-10-23目前系统遇到一个时效性问题,在广告监测数据上传由于网络原因到库存扣减中间有很多延迟,导致超发的问题,目前想到的解决方案是提供阈值提醒的功能到阈值时扩大库存的值避免超发,或者提前将广告下线。
作者回复: 可以用采样来估算,这样就不要那么多原始数据了
共 2 条评论1 - 付锐涛2020-04-21说一下我们公司的业务管理系统,有一个业务大表单(10个子页面组装而成,使用easyui+js实现),不同的业务场景,这个大表单的元素需要动态变化(可见、必填、校验规则)。 以前的做法是大范围变化全部复制一套,小范围变化使用JavaScript做动态控制,随着业务的演进这样的表单复制了5套,对应的js文件也复制了5套并做个性化修改,当需要维护表单的时候经常要5套一起修改,经常出现错改或者漏改的情况。 这个表单是核心业务表单,随着业务的发展修改频率非常高,所以想着能不能做成可配置的,刚开始想到以下两个方案: 1.引入vue 2.在后台生成表单html 由于团队内都是后端程序员,所以vue的学习成本导致被放弃。使用第二套方案相当于要开发一套表单生成系统,而且要保证前端样式不变,难度比vue还高。 最后结合实际情况,区分出表单中可变性(可见、必填、校验规则)和不可变性(表单布局),将表单布局整理出一套模板,再在数据库中存储每个元素的可变属性,页面渲染成功之后动态调整可变性。 由于履历原因,一直没有机会参与到架构搭建和架构重构这种级别的改造中,所做的重构也都是功能级别的,正在探索架构师的玩法。展开
作者回复: 其实我觉得应该引入vue😃
共 3 条评论1 - Regis2020-03-29学习是一个漫长的过程,尤其架构这方面,需要有丰富的开发经验及开发过程中的总结才能成长起来,加油💪
作者回复: 加油,坚持就会有收获
1 - 谭方敏2020-03-15有的放矢 架构师的首要任务是从一大堆纷繁复杂的问题中识别比较真正要通过架构重构来解决的问题,集中力量快速解决,而不是想着通过架构重构来解决所有的问题。 我公司目前的开发系统需要重构,主要有两方面: 1)管理所有节点的全局服务器本身应该是单点,并且与业务无相关的,它的职责就是动态管理各个节点增删查改,以及服务器配置但是因为业务逻辑上也需要一些全局数据,比如跨网关业务,所以当初为了偷懒,就把用户在线状态丢全局服务器里了。现在因为业务耦合度,全局服务器需要频繁调整业务逻辑。 需要梳理这块业务流程,不在全局服务管理,这样才能使得全局服务器完全业务无相关。 2)数据库服务器单点,当初也是基于当时用户规模来决定的,如果数据库存在多点的话,又需要进行负载均衡,这样会加大调用方难度。所以权衡之下,在数据库方面采用集群化,这样确保数据高可用,而业务逻辑上面追求简单处理,而采用了单点处理逻辑。 3)调用方式都是采用直接调用api的方式,没有做到调用解耦,比如引入mq。展开
作者回复: 可以优化一下
1 - 宋晓明2019-01-23老师 ,如果把很大的功能拆分成多个子系统,每个子系统的功能都是独立的,这样会成为单点系统,难道单点系统不做高可用吗?
作者回复: 功能独立,不代表只能一台机器呀,肯定会做集群方案的
2