有读者问我:你认为一个程序员要具备什么样的能力才能算得上是一个好程序员?我的回答:有解决问题能力的程序员。这个回答好像有点抽象,没关系,你看了下面的文章就会慢慢明白了。图片来自Pexels解决问题的能力很多年前,我还是菜鸟的时候,领导经常跟我说,解决问题的时候,不要局限于技术本身,还给我举了个例子,如图。有一次,两个程序员一直在讨论如何判断两台服务器之间的网络是否正常,吵了很久。旁边一个测试说,你ping个不就知道了吗?就这样,他们用Java代码实现了Ping操作,解决了这个问题。多年后,我仍然认为以前的测试人员很聪明,尽管我知道有更优雅的方法可以解决这个问题。一年后我们继续打交道,她真的很能干,相当于小公司产品经理+测试的职能。需要跟大家说明的是:解决问题的能力和技术能力是两个能力范围。我见过很多程序员把玩源码,但是在生产中出现问题的时候,还是不知道怎么解决。当生产出现问题时,是对一个程序员最高水平的考验。面对高强度、高压,动作不变形,能冷静思考、分析、解决问题的程序员才能达到这个境界。这在古代是可以供奉的。为将军。我一直喜欢能快速解决问题的程序员,也愿意在各种制作中出现问题时第一时间研究分析。说白了,好的程序员都是在解决问题方面训练出来的,尤其是在生产环境出现问题的时候能够站出来的程序员。凌晨迁移数据引发重大事故给大家分享一个发生在半夜的技术故事。老平台和新平台公司有旧系统和新系统。老系统用了很多年,早已经超出了它所能支持的极限。这个系统在2013年刚上线的时候,估计每天的交易量是1亿、2亿。事实上,它已经超过每天40亿。交易量。从2013年到2017年,技术团队付出了很多努力。旧系统使用Oracle数据库。为了支持最大的交易量,实现了读写分离、分库分表+各种最强大的硬件;系统拆分重构,多次优化,仍不能满足公司不断增长的交易量。说实话,把一个老系统弄成这个样子,团队真的不容易。最初的建筑设计不合理,缝补终究解决不了大问题。开发新平台成为公司发展的必然。新平台一期设计可以支持日交易量100亿,最重要的是,后期可以支持1000亿的扩容。经过兄弟们的努力,新平台终于上线了。新平台上线只是成功的一小部分,后续的数据迁移才是重中之重。运行了几年的老系统,采用传统的垂直架构(架构演进可以参考这篇文章:从架构演进的角度谈谈SpringCloud做了什么?),各种业务,政策,活动,风控全部揉在一起。新平台采用微服务架构,拥有上百个微服务,数据库MySQLHA。两个系统的架构设计相隔了一代。为了兼容旧系统的部分功能,在设计时进行了一些冗余设计。反正这两个系统不是一个时代的产物。迁移要求是从旧平台迁移到新平台时,不能影响商户的正常交易。打个比方,就相当于在高速公路上开着车,边开车边换轮子,而且这个过程得让你在车里什么都感觉不到。所以我们开发了一个迁移系统。本来我们打算一个个一个个的迁移到新平台,一次交易量1亿或者2亿。我们慢慢看效果再按节奏进行。然而,一个突如其来的政策(活动)打乱了这种节奏。新政策带来的变化对于第三方支付企业来说,往往会根据市场环境推出一些新的政策(活动)。有些政策相对简单,但大多数政策很复杂,往往需要大量的开发工作。当时新平台已经切换了一段时间,大家也逐渐对新平台有了一些信心,所以决定在新平台上执行这个新政策。计划在政策实施当晚,将其中一个旧平台上的剩余商户全部迁移至新平台。方案敲定后,各部门开始各司其职,运营中心对外发布通知,元旦要搞大动作,可能会有什么变化;营销中心负责联系各座席进行批量培训;部门开始下发公司的红头文件,分发到各分公司。我们提前与客服、运营部门沟通,针对可能出现的问题提前做好预案;公众号、公司官网、App、邮件对外通知政策变更,并公布开始实施日期;产品中心负责梳理政策实施要求,研发中心负责制定新政策确定的项目。最重要的是确保剩余的数百万商户能够在除夕之夜一次性顺利迁移到新平台。迁移程序已经执行了很多次,半夜才开始迁移,所以大家对此比较放心,但还是多次和主要负责迁移的同事确认过。开发环境需要提前两周测试,UAT环境需要在迁移前一周测试。测试完成后,对研发和测试进行双重验证。直到迁移前三天,我特地找到负责迁移的程序员了解进度,询问有没有在生产中进行模拟测试。确认没有问题后,根据负责人的反馈,估计三到四个小时可以完成迁移,所以凌晨1:00完成迁移,4:00之间完成-5:00AM。在实际迁移的前一天,我们与各部门召开了沟通会。我们讨论了可能出现的各种情况以及各部门需要留守的人员。会后,大家心情都不错,静候今晚的大战!当晚,十几个开发人员和两个测试人员,还有一些其他部门的同事,大概20个人,有说有笑,不到12点,打游戏,等待凌晨1:00的迁移,因为恰好是元旦。办公室感觉就像一个节日。时间过得真快,北京凌晨1:00,窗外星光灿烂,办公室里一片紧张。十几位同事围着主要负责迁移的程序员,看得出来程序员压力很大(哈哈,估计这种事情谁都会有压力)。不过,他还是熟练地按照前面的测试,多次核对数据,点击了迁移按钮。首先在生产环境迁移一个agent,看看数据是否正确。执行完成后,相关人员开始核对数据。运维人员查看日志,开发人员确认相关节点正常,数据库工程师查看迁移数据;测试人员在操作平台查询数据校验,测试POS刷卡情况,一切正常!试过两种代理,都没有问题。接下来,我们将为AllIn做准备。商户数以百万计,代理商数以千计。负责迁移的程序员将所有代理号配置到执行程序中,点击执行按钮,查看生产日志,一切正常。留几个人监控数据,其他人就散了。迁移完成后,将进行后续工作。我也回到了自己的工作岗位,点了根烟,心想今晚会比较顺利。突如其来的意外清晨的夜晚,颇有些困意。当我点上第三根烟时,负责迁移的程序员急匆匆的来找我。“强哥,出事了!”他一惊,吸了一口烟,熄灭,连忙问道:“有什么问题吗?”原来,迁移程序执行后,程序员一直在跟踪迁移过程。progress,发现迁移10万商户用了半个小时,老平台一共有几百万商户。按照这个速度,需要几天的时间才能施行完毕。这是一个大问题!如果这不是在上午8:00之前完成,那就完全是意外。先不说新旧平台数据分离如何处理。如果公司政策延迟执行,如何在如此短的时间内通知数百万商户和数以千计的代理商,是一个不可能完成的工作量。可以想象第二天会发生什么样的情况。客服400电话被打爆,运营人员沟通到吐血,公司的损失可能是政策延迟执行造成的,代理人的赔偿行为……如果这个问题如果我们没有一个小时之内解决,需要第一时间汇报给公司的副总经理,然后估计联业公司的所有管理层都需要来公司开会,商讨后续的解决方案.虽然脑子里闪过迁移失败的严重后果,但还是要把所有的念头都压下去,问题先出现,有没有什么降级方案或者补救措施。①分析原因通过查询日志和查资料,基本找到了原因。开发人员在生产测试时,都是使用中小代理商进行的测试。然而,它忽略了公司不同代理商规模之间的巨大差异。最大核心代理的数据可能占平台整体交易量的5%-6%。所以,基于中小代理的评估时间肯定是不准确的。现在先不说是谁的问题。如何快速解决问题是下一步的关键。大家一起想办法。有什么办法可以使迁移更快。②补救措施,如先同步核心数据,其他内容后处理,先保证次日的交易。例如,我们可以使用手动表来处理所有这些吗?数据库工程师听到这个方案,差点哭晕过去。一千多张表,关系极其复杂;各种方案……说优化方案的时候发现迁移程序的主进程并没有使用多线程进行迁移。迁移程序提供了一个接口。每次迁移时,开发者都会在页面填写需要迁移的代理号。后台收到页面传过来的参数后,会启动for循环执行迁移。虽然代理下的商户使用的是多线程迁移,但是代理迁移的主程序入口并没有使用多线程,所以大家就在想代理要不要使用多线程来加快迁移速度。讨论完人为多线程救援,大家觉得agent的多线程迁移应该是目前比较好的解决方案,但是如果现场写的话,会直接执行,没有测试,风险还是比较大的。那么有没有什么可以在不改变程序的情况下实现代理并发迁移的效果呢?确实有!大家都知道,在我们平时开发的web应用中,前台到后台的每一个请求都会分配一个Servlet来处理响应。这个Servlet其实就是一个独立的线程。然后每次多开几个页面,同时执行迁移请求,不就实现了多线程迁移代理的效果了吗?干就是了,停止之前的迁移程序,选择十几个agent进行多线程迁移测试,同时打开4个页面,每个页面输入不同的agent,开始迁移测试,测试后发现一切正常.我开始加大测试量,用了几十个代理,在不同页面输入后依次点击迁移程序。第二次并发迁移过程中,突然发现时不时会报一些错误。停止迁移程序并开始查找原因。根据报错原因,发现有共享数据。我们知道Servlet不是线程安全的。多线程访问时,如果有全局共享变量,就会出现线程安全问题。这个问题很容易解决,直接用ThreadLocal修改即可,ThreadLocal为每个使用变量的线程提供独立的变量副本。所以每个线程都可以独立的改变自己的副本而不影响其他线程对应的副本。这个问题解决后,继续开多个页面执行,但是当同一个tomcat有6个以上线程并行时,机器负载会比较高,因为每个线程都会再次调用另一个线程池来处理商户,Salesman的迁移逻辑。于是我立即安排运维人员在生产环境中找了10台服务器,将迁移后的masterscheduler全部部署在了这10台服务器上。为了防止开发者握手导致问题,我请求运维给我权限。于是在我的电脑上(我用的是多屏),分别打开10台服务器上的迁移程序页面,每次把需要迁移的agent分成15组,每次迁移Agent时在1个页面进入1组,并且这个循环开始依次迁移每台服务器上的代理。当我执行循环6次时,数据库工程师检测到数据的迁移速度明显加快了,所以我花了2个小时在页面上分别迁移了所有的代理。凌晨4:00左右,我的工作基本完成,剩下的程序就慢慢跑;凌晨5:00,大部分商户数据迁移完毕,仅剩2台服务器保持运行;到早上6:00,所有10台服务器的迁移过程都已完成。安排好将所有相关资料一一核对后,众人都松了口气。早上7:00我们一起下楼吃早餐的时候,大家还在谈昨晚差点熬夜的感觉。开玩笑说,如果我们凌晨两三点给老板打电话,老板会怎么想。当时想,出了这么大的事故,老板开除我们也是小事一桩,我们最关心的是如何收场。如果你失去了工作,你可以重新找到它。无论发生什么,我们都需要解决它。上午9:00交易开启后,陆续出现了一些小问题,但都是小问题,不影响交易。有问题就回去睡觉。事后回想起来,所有人都觉得自己渡过了难关。事件回顾之后,我们开复会的时候,总结了很多这里省略的地方,但这些都不是本文的重点。让我们回到文章开头,什么是伟大的程序员?可以看到这个问题并不是特别复杂,处理它需要的技术手段也比较简单,但是最重要的是解决当时最紧迫的问题。因此,技术没有高低之分。学习技术的本质是解决各种问题。不要对技术迷有信心。最好使用它。技术人要学会享受压力,因为压力就是动力,压力就是让你成长的动力。越早遇到它,你就会成长得越快。在高压、高强度的环境下,即使是简单的动作也可能变形,从而引发更大的二次事故。在高强度、高压的环境中,保持一颗冷静分析的心。只有静下心来,才能真正发现问题,解决问题。很多技术人,出问题的时候,你看他在忙,其实他根本没有心思去那里操作。静下心来,仔细分析整个链条,想象可能哪里出了问题,然后查看日志或相关命令,一步步排查验证问题的根源。只有当你真正找到问题的根源时,你才能自信地解决它。当晚留守迁移的程序员都是我们公司的核心程序员,但是谁有上进的本事,谁有下行的本事,这一晚就一目了然了,优秀的程序员就像金子一样,关键时刻会发光。很多人遇到问题自然会往后退几步,有的人遇到问题喜欢往前冲。不管你的源码研究得多么好,PPT写得多么好,公司需要的是遇到问题能挺身而出解决问题的人。凡是能在关键时刻挺身而出的程序员,以后走上管理岗位基本上都是轻而易举的事。其实人与人之间的信任是通过不断的磨合建立起来的。一个领导选择提拔一个员工,主要考虑的是他能不能把这件事托付给你。所以平时研究技术的时候,千万不要误入歧途。源代码和设计模式应该研究,但是你应该考虑的是研究之后如何应用它们,并且更侧重于实践知识。这些东西可以在关键时刻拯救你。生活(工作场所)。如何成为一个有能力的程序员那么作为一个程序员,如何培养自己解决问题的能力呢?实践!实践!实践!平时的技术学习,只是一种强输入。如果不练习,这些能力会很快丧失。那么怎么实践呢,多做项目,如果公司的项目没有用到这个技术,可以空余时间写代码自己debug。此外,当同事有问题时,他们也经常帮忙解决。当公司出现问题时,他们会主动帮助解决问题。解决各种问题是提升能力最快的途径。练习完成后,最好进行回顾总结,将总结的内容记录为日志或博客。录制的内容将成为您的知识宝库。以后遇到类似问题,可以搜索解决,不断丰富解决问题的经验。最后祝你成为真正的技术高手!
