stuff(winkyy~

I have but one purpose in this life, seeking the nature of the world.

0%

[单排日记][ccd打工纪实]

简介

我都不知道这篇文章到底该叫什么XD了,主要是总结了在前几个月里做的一些工作:

做了一个crud功能模块但是这里不讲;做了一个竞价排名系统,但是重点甚至不在其本身,而在于改进旧项目;做了一部分项目重构。

旧项目

竞价需求

需要排名的是1000+个对象(后续需要能实时添加),在未竞价时本身有一套排序体系,从多个维度比较,维度有优先级,这里代称为A、B,对象1.A大于对象2.A时,对象1排在前面,如果A相等,再比较B,以此类推。而竞价本身也作为一个维度,优先级最高,但是只选出前N名排在前面,超过N的退钱,并且按未竞价的情况排名。

竞价需要设置每次点击扣费额以及总次数。每次扣费额作为排名依据,总次数点击完了之后不再扣费,同时排名重新按原来的体系排序。竞价成功后,到期没用完的次数直接参与下一轮竞价。

产品原本的要求是竞价后即时排序,点击数用完后即时下撤。经过大TL和小TL的共同努力,在与产品进行友好沟通后,改成了每10分钟统一换一次榜。(竞价本来是大TL的工作XD)

难点

排个序问题本身不大,这个数量级都轮不到自己写排序算法。

还是稍稍介绍一下主项目本身吧。是自研的一个Node 6下的web框架;启动时将一部分不经常改变的数据,外加一些基于这部分数据计算的数据,直接存放在全局变量里,名曰“静态数据”;有很多自定义的全局函数;mysql全局封装,不支持事务;redis全局封装,只能写get和set方法;没有守护进程;没有负载均衡或多副本;一部分数据每月更新,主项目需要冷重启,停服两小时。

一个问题在于属性A、B说着挺简单,但是实际上是不固定的,并且是一个分库的统计字段。修改需要结合另一个项目手动跑脚本改数据库再统计,主项目再冷重启。

再一个10分钟排一次,中间还要可以加价,并且还要保存每次的竞价结果,客户端需要能查看本人的时序结果,后台既要看到单人的时序、又要看到每个时间节点全部的时序,保留至少30天。我这里只写了A、B属性,实际上维度有很多,数据量是一个值得考虑的问题。

解决方案

应用无状态化

考虑到冷启动是经常的,也不应该有所谓“静态数据”这种东西,首先要将“静态数据”放在redis;这些数据一般只在另一个手动脚本运行时才发生改变,因此这些数据统统交给这个脚本维护。这样主项目即时冷重启,也只会读redis里维护好的数据,而非重写读数据库重算。这部分的工作将Node主进程占用900MB的内存降低到了200MB左右,也便于后续做多副本。

之所以仍然要用这套数据,还是因为这套东西过于基础,项目里到处都在用。这么改才具有可行性。后期的话直接重写的。如果没有这种历史包袱的话,预期不会变的数据,比如平台名、项目名,直接写在config.js里;任意预期会改变的东西,不管改得是否频繁,都应该写在数据库里。

守护进程+负载均衡

这个和同事配合着做,主进程用pm2管理;负载均衡直接用阿里云的,切好端口、重新配置好证书即可。后期终于迎来了一位运维小哥哥,感恩。

OSS储存记录

没别的原因,便宜点。只保留30天,就按日覆盖文件夹,时序数据和全局数据直接生成json。要是前端配合的话可以直接在前端做oss权限验证,数据都不走服务器美滋滋(可惜前端框架也是上面同一批人自研的XD)。

重写和一些感想

重写最重要的原因,是这个框架是真的沉疴难愈了……哪来那么多中华田园架构师写自研……

这部分是Node组配合一起做的,我需要将我之前开发的crud模块和一部分相关模块用egg重写。

啊,新鲜完整的mysql的香味,久违了。旧项目支付体系之所以从来不出问题,完全归功于客户量少,没有出现过并发场景。但这不代表一个技术仔内心没有受到煎熬。你(市场)可以不行,我不可以不行。万一哪天付款客户真的多到高并发了呢?

重写的要点在于尽可能按产品说明好好写测试样例,遗憾的是这的确会拖慢很多开发进度。我听过太多次“时间紧,赶赶吧”,在开发质量和效率间,TL和老板选择效率,即时我一再强调,也不曾思考过“后续维护欠债”的后果。

我现在已经从前公司离职了,我认真思考过了,我做得再快一点,产品会有起色吗?

我觉得不行。

老板是销售出身,很会说,也有一些人脉。但是产品是要用真金白银买的,你的产品创造的东西有没有价值,有多大价值,是需要用事实说话,而非花里胡哨数特性优点、攀关系来的。你说你的产品能帮我省钱,帮我赚钱,告诉我有ABCD一大堆优点作为理由,我看的不是ABCD,我看的是到底是不是帮我省钱赚钱。

以上。