对一个程序员来说,世界上最痛苦的事情是什么呢?
但我要说,这些痛苦其实都不算什么,要么是多花点时间去解决(比如说改需求、看代码),要么是多花点心思(比如说找另一半、定位疑难bug),而我接下来说的这个事情才是最痛苦的, 既要说得动老板,也要镇得住同行;既要技术攻关,又要协调资源;既要保证业务正常发展,又要在指定时间内完成目标 。总之就是十八般武艺要样样精通。
这个事情就是“架构重构”,比“架构重构”还要痛苦的就是“边做业务边架构重构”!我们的产品形象的形容为“给飞驰的法拉利跑车换引擎”,为何这样说呢?
首先,业务不能停,不能为了架构重构而终止业务的开发,将法拉利停下来换引擎,别人都跑远了;
其次,业务不能出问题,不能因为架构重构导致业务无法运行,法拉利修出问题跑不了,别人也跑远了;
第三,要根本解决问题,而不是修修补补,不是给法拉利引擎加点油,清洁一下就可以了,而是要换上新的引擎。
巧合的是,我加入UC后到现在已经做了3个系统的架构重构了(戏称“救火队长”),而且每个系统的特点都不一样,过程中各种各样的问题都遇到过,坑也踩过,也积累了一些经验。接下来就给大家分享一下。
我接手的第一个系统是一个后台系统,负责管理整个阿里游戏的游戏相关的数据(以下简称M系统), 重构的主要原因是 因为系统耦合了P业务独有的数据和所有业务公用的数据,导致可扩展性比较差。其大概架构如下:
举一个最简单的例子:数据库中的某张表,一部分字段是所有业务公用的“游戏数据”,一部分字段是“P业务系统”独有的数据,开发的时候如果要改这张表,代码和逻辑都很复杂,改起来效率很低。
针对M系统存在的问题,我们的重构目标就是将游戏数据和业务数据拆分,解开两者的耦合,使得两个系统都能够独立快速发展。
重构后的效果非常明显,重构后的M系统和P业务后台系统每月上线版本数是重构前的4倍!
我接手的第二个系统,是负责游戏接入的核心系统(以下简称S系统)。S系统是游戏接入的核心系统,一旦S系统故障,大量游戏玩家就不能登录游戏,而S系统并不具备多中心的能力,一旦主机房宕机,整个S系统业务就不可用了。其大概架构如下,可以看出数据库主库是全局单点,一旦数据库主库不可用,两个集群的写业务都不可用了:
针对S系统存在的问题,我们的重构目标就是实现双中心,使得任意一个机房都能够提供完整的服务,在某个机房故障的时候,另外一个机房能够全部接管所有业务。
重构后系统的可用性从3个9提升到4个9,重构前最夸张的一个月有4次较大的线上故障,重构后虽然也经历了机房交换机宕机、运营商线路故障、机柜断电等问题,但对业务都没有什么大的影响。
我接手的第三个业务系统,是属于创新业务(以下简称X业务)。由于是创新业务,之前的业务快速尝试和快速发展期间,怎么方便怎么操作,怎么快速怎么做,系统设计并未投入太多精力和时间,很多东西都塞到同一个系统中,导致到了现在已经改不动了,做一个新功能或者新业务,需要花费大量的时间来讨论和梳理各种业务逻辑,一不小心就踩个大坑。X系统的架构如下:
X系统的问题看起来和M系统比较类似,都是可扩展性存在问题,但其实根本原因不一样:M系统是因为耦合了不同业务的数据导致系统可扩展性不足,而X系统是因为将业务相关的所有功能都放在同一个系统中,导致系统可扩展性不足;同时,所有功能都在一个系统中,也可能导致一个功能出问题,导致整站不可用。比如说某个功能把数据库拖慢了,整站所有业务跟着都慢了。
针对X系统存在的问题,我们的重构目标是将各个功能拆分到不同的子系统中去,降低单个系统的复杂度。重构后的架构如下(仅仅是示例,实际架构远比下图复杂):
重构后各个系统之间通过接口交互,虽然看似增加了接口的工作量,但整体来说,各系统的发展和开发速度比原来快了很多,系统也相对更加简单,也不会出现某个子系统有问题,所有业务都有问题。
这三个系统重构的方案,现在回过头来看,感觉是理所当然的,但实际上当时做分析和决策的时候,远远没有这么简单。
以M系统为例,当时我们接手后遇到的问题有很多,例如:
从这么多问题中识别出重构的目标,并不是一目了然的;而如果想一下全部解决所有的这些问题,人力和时间又不够!
所以 架构重构首要的任务是从一大堆纷繁复杂的问题中识别出真正要通过架构重构来解决的问题,集中力量快速解决,而不是想着通过架构重构来解决所有的问题。 否则的话,就会陷入人少事多头绪乱的情况,团队累死累活弄个大半年,最后发现好像什么都做了,但每个问题都依然存在。尤其是对于刚接手一个新系统的架构师或者技术主管来说,一定要控制住“新官上任三把火”的冲动,避免摊大饼式或者运动式的重构和优化,谨记“步子大了会扯到蛋”的教训 !
那原来发现的那些问题怎么办呢?当然不能放任不管。以M系统为例,我们在重构完成后,又启动了多个优化的项目去优化这些问题,但此时的优化主要是团队内部完成即可,和其它团队没有太多关联,优化的速度是很快的。如果没有重构就进行优化的话,每次优化都要拉一大堆关联业务的团队来讨论方案,效率非常低下!
架构重构是大动作,持续时间比较长,而且会占用一定的研发资源,包括开发和测试,因此不可避免的会影响业务功能的开发。因此,要想真正推动一个架构重构项目启动,需要花费大量的精力进行游说和沟通。注意这里我不是指要谈办公室政治,而是指要和利益相关方沟通好,让大家对于重构能够达成一致共识,避免重构过程中不必要的反复和争执。
一般的技术同学谈到架构重构的时候,就会搬出一大堆技术术语:可扩展性、可靠性、性能、耦合、代码很乱。但以我的实际经验来看,如果和非技术同学这样沟通,效果如同鸡同鸭讲,没有技术背景的同学很难理解,甚至有可能担心我们是在忽悠TA。例如:
技术同学说:我们系统现在的可扩展性太差了,改都改不动!
产品同学想:咦,可扩展性,和扩胸运动有关么?扩展什么呢,怎么会改不动呢,不就是找个地方写代码嘛。
技术同学说:我们的可靠性太差,现在才3个9,业界都是4个9!
项目经理想:啥是3个9,三九感冒灵?。4个9和3个9不就是差个9嘛,和可靠有什么关系。
技术同学说:我们系统设计不合理,A业务和B业务耦合!
运营同学想:咦,耦合,莲藕还是藕断丝连?A业务和B业务本来就是互相依赖的呀。耦合为什么不合理呢?
以上的样例并无嘲笑产品运营和项目同学不懂技术的意思,而是说明有的技术术语并不是很好理解,在跨领域沟通的时候,很难达成一致共识。
除此以外,在沟通时还经常遇到的一个问题是凭感觉而不是凭数据说话。比如说:技术同学说“系统耦合导致我们的开发效率很低”,但是没有数据,也没有样例,单纯这样说,其他同学很难有直观的印象。
所以在沟通协调的时候,将技术语言转换为通俗语言,以事实说话,以数据说话,是沟通的关键!
以M系统为例,我们把“可扩展性”转换为“版本开发速度很慢,每次设计都要考虑是否对门户有影响,是否要考虑对其它业务有影响”,然后我们还收集了1个月里面的版本情况,发现有几个版本设计阶段讨论1周甚至2周时间,但开发只有2天时间;而且一个月才做了4个版本,最极端的一个版本,讨论2周,开发2天,然后等了1个月才和门户系统一起上线,项目经理和产品经理一听都被吓到了。
以S系统为例,我们并没有直接说可靠性是几个9,而是整理线上故障的次数、每次影响的时长,影响的用户,客服的反馈意见等。。。。。。然后再拿其它系统的数据一对比,无论是产品还是项目还是运营,明显就看出系统的可靠性有问题了。
当然, 如果以上技巧还不奏效,或者遇到极端情况,那就要考虑一些更加有效的手段了 !比如说我们遇到一个产品人员,他认为技术优化和架构重构是研发的事情,他不关注,安排开发资源的时候也不考虑重构和优化的投入,要研发自己解决!没办法,只能上升到上级领导层面协调,甚至我们都放出狠话“如果你不同意安排资源进行优化,下次出故障我们就说产品不给人力进行优化和重构”。
除了以上讨论的和上下游沟通协调外,有的重构还需要和其它相关或者配合的系统的沟通协调。由于大家都是做技术的,有比较多的共同语言,所以这部分的沟通协调其实相对来说要容易一些,但也不是说想推动就能推动的,主要的阻力来自“这对我有什么好处”和“这部分我这边现在不急”。
对于“这对我有什么好处”这个问题,有的人会简单理解为这是自私的表现,认为对方不顾大局,于是沟通的时候将问题人为拔高,例如“你应该站在部门的角度来考虑这个问题”、“这对公司整体利益有帮助”等等。这种沟通效果其实很差,首先是这种拔高一般都比较虚,没法明确,不同的人理解不一样,无法达成共识;其次是如果对公司和部门有利,但对某个小组没用甚至不利,那么可能是因为目前的方案不够好,还可以考虑另外的方案。
那如何才能有效的推动呢?我们的策略是“换位思考、合作双赢、关注长期”。简单来说就是站在对方的角度思考,重构对他有什么好处,能够帮他解决什么问题,带来什么收益。
以M系统为例,当时有另外一个C系统和M系统通过数据库直连共用数据库,我们的重构方案是要去掉两个系统同时在底层操作数据库,改为C系统通过调用M系统接口来写入数据库。这个方案对C系统来说,很明显的一点就是C系统短期的改动比较大,要将10几个读写数据库的地方改为接口调用,刚开始C系统也是觉得重构对他们没有什么作用,后来我们经过分析和沟通,了解到C系统其实也深受目前这种架构之苦,主要体现在“数据经常出错要排查”(因为C系统和M系统都在写同一个数据库,逻辑很难保证完全一致),“要跟着M系统同步开发”(因为M系统增加表或者字段,C系统要从数据库自己读取出来,还要理解逻辑)、“C系统要连两个数据库,出问题不好查”(因为C系统自己还有数据库)。
这些问题其实在M系统重构后都可以解决,虽然短期内C系统有一定的开发工作量,但从中长期来看,C系统肯定可以省很多事情,例如:数据问题排查主要是M系统的事情了,通过M系统的接口获取数据,无需关注数据相关的业务逻辑等等。通过这种方式沟通协调,C系统很乐意跟我们一起做重构,而且事实也证明重构后对C系统和M系统都有很大好处。
当然如果真的出现了对公司或者部门有利,对某个小组不利的情况,那可能需要协调更高层级的管理者才能够推动,平级推动是比较难的。
对于“这部分我们现在不急”这个问题,有的人可能会认为这是在找借口问题,我也不排除这种可能性。但就算真的是找借口,那也是因为大家没有达成一致意见,可能对方不好意思直接拒绝。所以这种情况就可以参考上面“这对我有什么好处”这个问题的处理方法来处理。
如果对方真的是因为有其它更重要的业务,此时勉为其难也不好,还是那句话:“ 换位思考 ”!因为大部分重构的系统并不是到了火烧眉毛非常紧急的时候才开始启动的,而是有一定前瞻性的规划,如果对方真的有其它更加重要的事情,采取等待的策略也未尝不可,但要明确正式启动的时间,例如3个月后开始、6月份开始,千万不能说“以后”、“等不忙的时候”这种无法明确的时间点。
除了计划上灵活一点,方案上也可以灵活一点:我们可以先不做这个系统相关的重构,先把其它需要重构的做完。因为大部分需要重构的系统,需要做的事情很多,分阶段处理,在风险规避、计划安排等方面更加灵活可控。
文/李运华
原文出处——聊聊架构微信公共号