一、日常问题
1)MySQL归档
当前我们组管理着一套审核系统,除了数据源是服务端提供的,其余后台管理都是由我们组在维护。
这个系统就是将APP中的各类社交信息送到后台,然后有专门的审核人员来判断信息是否合规,当然在送到后台之前已经让机器审核了一遍。
在去年8月份上线后,日积月累,有张数据表变得比较庞大,截止到目前将近5800W条,数据容量31.21G,每条记录大概是582B。
由于数据量庞大,在检索时也将模糊查询撤掉,并且为了便于查询,还加了很多索引,目前的索引容量都达到了12.2G,审核人员也经常反馈系统使用起来很卡。
在了解到他们的诉求后,我们也展开了优化方案。首先想到的分表,第一种横向分表,也就是将数据以日或月为单位,目前一天的量在20W条左右,一个月的话在600W条左右。
但是这么分的话,在维护上就比较复杂,例如查询时,假设正好遇到跨天或跨月的条件,那么数据组织就比较繁琐了。
第二种分表是利用MySQL的语法:分区表,就是让MySQL来做分表这个粗活,对我们这些使用者来说该怎么查还是怎么查。
但是有网友说,随着数据量的增加,分区表也会有性能问题,具体达到多少量会有显著的性能问题,我没有深入研究,但是量上去了,总归还是会有点问题的。
分表的方案就这么废弃了,然后想到将数据同步到 ElasticSearch 中,这样的话,检索就毫无压力了,不过数据是需要频繁的更新的,不知道会不会影响ES的性能。
并且改造成本也是巨大的,要改动很多地方,而目前最紧缺的就是人力资源了,即使我们花大力气改造好了,当前测试组也抽不出人手做质量保障。
匆忙上线势必会影响审核人员的使用,虽然系统有这个那个的小毛病,但至少还能稳定的在运行中,也就作罢了。
在仔细思考后,又想到了另一个改造成本最小的方案:MySQL归档。所谓归档就是将大表中的一组数据迁移到另一张表中。
与审核人员一对一沟通后,了解到,其实他们会用到的数据也就是半个月内的,半个月之前的数据很少会用到。
也就是说表中存在很明显地冷热数据,并且冷数据被操作的概率非常低,几乎不会访问。
那我只要每天将这部分冷数据迁移出去,就能保障审核记录表的容量,也就能避免性能问题。
2)压力测试
运营最近想发50W的推送,推广一个匿名聊天的功能,那么就得提前做一轮压力测试,好知道这个功能承受多少的用户量。
压测的任务交给了QA去完成,自己对此也蛮在意的,所以也了解了一下压测的流程,找到了JMeter这个工具。
捣鼓了半天,才发现我本机使用JMeter只能打开4000个线程,这远远无法满足压测需求,又去寻找方案,才找到了JMeter的分布式测试。
这个过程跌宕起伏,我特地做了一个记录。QA既用此软件,还使用了websocket-bench,用代码来模拟访问。
在用JMeter开启1.2W个线程1分钟内访问页面后,生成了一组报告,信息非常多,我认得的就是错误率,发现并不多,还有很多响应时间、TPS等数据。
详细的分析我还不是很专业,后续我得去系统的学习一下性能测试的方方面面。
以当前的结果看,情况不是很糟,但是那个阈值还没找到,得让QA帮忙找下了。
其实我在查看服务器的一些参数的时候,就发现很多值都达到了百万,例如文件打开数,QA通过WIKI也发现了之前的压测记录,这说明之前也做过此类测试。
3)版本迭代的疑惑
每次APP的版本迭代从开发到提审都要持续一个月以上,我本来以为是因为需求太多导致的,但和产品沟通后,发现原因并没这么简单。
确切的说应该是多方面的,这里就从产品的角度来说说其中的一个缘由。
公司在一个版本提测后,就会抽时间开个初审会议,说明下一个版本的需求。
而产品的初衷是希望给开发更多的时间来理解需求,评估需求的合理性、开发时间以及技术细节。
理想很丰满,现实很骨感。让开发边修BUG,边思考需求,实际操作中并没有同步。
开发并不会提前阅读产品需求,只会在确定要开始做的时候才看。这就会导致一个问题。
那就是做到某一个需求,发现自己的理解与产品不同,然后开始讨论补救方案,打补丁,因为如果做了很多功能,不能一下子全砍了。
这样一来一回就会浪费很多不必要的时间,降低开发效率,双方还会闹的有点不愉快。
其实之前在我们组内推行了设计方案,可以很大程度的规避需求理解和技术细节的问题。
但在我们组内还没出现令人信服的数据和案例,所以现在推广也不太现实。
之前和服务端的同学沟通过,他说他很多时候并不是在做需求,而是将很多时间花在修线上BUG上了,祖传代码坑很多。
并且有些逻辑都无人维护了,一旦出问题,就要调试半天,这应该也是影响开发进度的一个原因。
我个人感觉每次将这些功能调试完后,就该留下点文档记录,无论是技术细节还是业务细节,都可以留存,下次再遇到就能游刃有余了。
4)关联功能的遗漏
对于那些有时间范围的活动,不会有这个问题。
而对于那些长期维护的功能,就会有这个隐患,因为这些功能互相之间相互关联,而当前没有很好的方式来表明他们之间的关系。
虽然没有牵一发而动全身这么夸张,但是动局部还是很有可能的,最近就遇到几个这样的坑。
服务端对支付改版,新增了一张订单表,售后服务关联的是老表,没有人知道要适配新表,直到客服上报问题才发现。
推荐管理增加中英繁语言字段,在改完后,运营使用时发现有个标签字段无法显示了,开发排查发现是提交旁边有个定时任务的按钮,其中的逻辑没有更新,导致问题发生。大家都不知道原来还有这个玩意儿,包括QA也没注意到。
这类问题,该如何预防,目前只能被动的接收业务人员的反馈,主动出击的问题是没有目标和参考资料,难以划定受影响的范围。
若是画一张巨大的关系图,我又担心维护成本巨大,没有那么多资源来支撑。
虽然这个不行那个不行,但是若是遇到了这个业务的问题,那么就有必要针对此业务将边边角角的流程梳理干净。
例如售后服务,就拉上产品、财务和客服一起开个会议,在和她们沟通后,就发现她们的日常操作和我们预期的并不同。
于是让她们记录当前流程,在此基础上做针对性的适配优化。
5)数据库优化
最近几天,从周六开始,管理后台在早上9点至10点会发生挂起,每次客服就会找到我。
周末也无法细看,只能重发代码临时解决,本来以为只是个偶发现象,没想到并不是。
过了几天频发,引起了我们的注意,运维也查到有段时间的服务器CPU异常,突然飙升。
经过曲折的探索后,定位到一些SQL语句查询非常慢,阻塞了数据库处理。
执行 EXPLAIN 命令,发现命中的是一个时间索引,影响的行数要300多万条。
而那个时间限制是特定时期才需要的,现在只是个冗余条件,完全可以移除,移除后,查询效率飙升。
MySQL为什么会选错索引,这里面蛮有学问的,得学学索引的运行原理,一句两句讲不清。
顺便说一句,最近还对MongoDB中的一张表也加了个时间索引,表的数据量有3亿多条。
未加索引之前,查询几条记录要十几分钟,加了索引后,可以在几毫秒中得到结果。
二、工作优化
1)推广单元测试
其实在很早之前就已经在组内分享过单元测试的种种好处。
并且在当前使用的代码结构中,已经集成了单元测试的框架,包括 mocha.js、chai.js 和 sinon.js,并且附加了多种场景下的测试用例。
组内成员只要根据自己的实际情况,编写测试用例即可,但使用率仍旧不是很理想,分析下来可能是以下几个问题导致的。
首先就是团队成员会质疑单元测试的价值,需要给出证明单元测试确实有效可行的方法和证据。
其次是团队成员缺乏主动测试的意识,目前有大量的测试代码,不知道从哪里开始测试,并且花费额外的精力来维护单元测试的代码。
还有就是编写单元测试大概会花费日常开发的 10% 以上的时间,而项目时间总是比较紧,无法留出充裕的测试时间。
最近自己工作的重点是项目的质量保障,想了一下后,觉得有必要再次将单元测试提到议程,特地做了些准备,根据两本单元测试的书籍编写了一篇简易的教程,希望能降低单元测试的门槛。
2)Code Review再议
我们团队在遇到重要活动时会做Code Review,虽然频率不高,每次执行的时间也就半小时左右,但效果显著。
我们Code Review时的气氛非常和谐,大家并不是为了找茬而来的,都是为了找出其中的代码或设计缺陷而来的。
我们不会拘泥于注释、空格个数等细节,主要还是专注于业务理解和逻辑思路。
大家坐在一张桌子上,将自己的代码展示出来,诉说自己的思路和想法,有时候就会发现协作的两人在接口使用或某个参数含义上发生了偏差。
一旦发现就能当场或会后及时修正,以免在测试,甚至线上出事故时才发现,既节省了时间,也避免了公司损失。
对于某段代码写的过于繁琐或抽象不够时,大家也会提出自己的改进意见,从而就能做到互相进步。
在会议中,有时候也会发现页面的性能问题,例如有个活动在初始化时调用了一个内部逻辑过于复杂的接口,其实完全可以将其拆成两个接口。
这样就能快速渲染页面整个结构,避免白屏时间过长。
其实还有很多好处,大家只要带着目的去尝试一下,就会发现新大陆的。
3)前端岗位的三点思考
如果你觉得我的理解有偏差,欢迎评论区留言。
- 前端离用户最近
用户在浏览网站时,最先看到的就是页面,从这个层面来说,前端的确离用户最近。
但用户浏览网站是有目的地,可能是阅读文字信息,也可能是购物,还可能是提交表单等等。
这些数据就全部转移给了后端,让后端来处理,而此时,后端才是离用户最近的。
前端从某种意义上来说,只是做了一层桥接,为用户和后端提供了一座沟通的桥梁。
由于用户看到的都是界面,那么一旦有问题,首先联系的也将是前端。
此时前端将会排查问题,当查到后端问题,前端再转移问题到他们名下,日常工作中,前端经常要做这些琐碎的事情。
- 前端涉足很广的领域
前端的触手已经伸到了客户端(Flutter、React Native等)、服务端(Node.js)和桌面端(Electron),可以说无所不能。
但也仅仅是伸到而已,大部分情况下,是难以有机会实践的。
一个原因是术业有专攻,客户端和服务端到底在他们各自领域会来的专业点。
第二个原因是公司资源,大部分公司不会让一个人做这么多事情,都是会分工的,做太多反而不精,容易误事。
前端这么多年发展下来,其实主要的工作仍然是表现和交互,工作形式以页面制作为主。小程序也是页面,只是运行环境不同。
现代的制作方法也越来越讲究,越来越科学,例如流行的React、Vue基于组件的开发思路,还有各种工程化利器,在提效的同时,也提升了编程体验。
我还记得当年被IE6支配的黑暗年代,做什么创新都得为IE6多准备一套兼容方案,工作量都耗在了IE6的适配上。
- 前端能帮助大家做的更好
之前说到前端涉及了非常广的领域,如果想着替代那些岗位,其实意义不大,职责分工还是蛮科学的。
我感觉可以融合现有的这些技术,创造出能帮助解决业务痛点或提升工作效率的工具。
例如测些不太懂redis命令,那么就做套可视化的缓存界面供他们操作,节省测试时间。
还例如运营活动比较常规,那将共性抽象出来,做成一套可配置化的系统,只要输入些参数,就能实现他们所需的功能,压缩开发周期。
网上还看到有些团队的前端做了一套报表系统,供产品和运营查看,解放了服务端的生产力。
前端被赋予了很多能力,发挥想象,可以做的事情还有很多,不用局限于那一亩三分地。