三年架构设计:从0到10亿的Java高增长实战路径
|
去年二月那会儿,接口超时告警跟疯了一样弹——我原以为又是缓存击穿,结果一看堆栈,好家伙,是定时任务扫表把数据库连接池打爆了。当时运维在群里喊“谁在工位上打电话谈房租?别占着公司网络下载电影了”,我盯着监控大盘上那条绿色的线一直在抖,突然就想起三年前刚接手这项目时,前端说“这接口要支持未来十年所有业务”,我差点把咖啡喷在键盘上——十年?那时候我们连十万用户都没有。 那时候的架构,说白了就是“能跑就行”。表结构里有个字段叫“extra_info”,类型是VARCHAR(255),前端说“反正现在用不到,先留着”——结果去年双十一前夜,产品突然说“要在这个字段里存用户行为链,大概每条5K”,我盯着日志里“Data too long for column”的错误,机箱嗡嗡响得像要起飞,最后连夜改字段类型,改完发现索引全失效,慢查询堆了一屏幕。 但你说这三年怎么从0到10亿的?我觉得最狠的就是“优胜劣汰”——不是架构师淘汰技术,是业务自己淘汰架构。比如我们第一版用了Redis做热点缓存,结果QPS涨到百万级时,缓存穿透把Redis打挂了三次。后来换成本地缓存+LRU,结果又遇到多实例数据不一致——那时候测试妹子天天在群里发“脏数据又出现了”,我差点把她拉黑。最后怎么办?直接上Caffeine,配合分布式锁,虽然性能降了10%,但至少没再丢过数据。
文章配图,仅供参考 咖啡机坏了那周,我们灰度发布新版本。运维说“这次绝对稳”,结果上线两小时,订单接口超时率从0.1%飙到5%。我冲进会议室,发现前端在改接口返回字段——他居然把“order_status”从String改成了Enum,后端没做兼容,直接抛了IllegalArgumentException。更绝的是,这哥们改完没通知任何人,连测试用例都没更——他说“我以为你们会看Git提交记录”,我盯着他工位隔断上贴的“今日事今日毕”便签,卷了边的纸角在空调风里晃,突然就笑了。慢查询那事儿更离谱。记不清是哪次了,反正是某个周五下午,数据库慢查询日志突然暴增。我原以为是新上线的推荐算法太复杂,结果查了半天,发现是某个定时任务在扫全表——而这个任务,是三年前一个离职同事写的,注释里写着“临时方案,待优化”。更搞笑的是,这任务居然没加限流,扫到一半把数据库连接池打满了,所有接口都超时。最后怎么解决的?直接kill了那个进程,然后让运维把慢查询阈值从1秒调到5秒——产品说“用户能接受5秒的等待”,我盯着他手里的奶茶,心想“你倒是能接受,可我的KPI接受不了啊”。 说到KPI,去年Q4那会儿,老板说“要支持10亿级数据量”。我算了下,按当时的增长速度,大概还有半年。结果产品突然改需求,要在用户表里加个“last_login_device”字段——这字段要存设备类型、版本号、IP地址,单条记录至少200字节。我原以为直接加字段就行,结果发现表已经200G了,加字段要锁表,而锁表时间跟数据量成正比——200G的表,锁表至少半小时,期间所有写操作都得挂。最后怎么办?先建个新表,用触发器同步数据,等流量低峰期再切换——那晚我盯着监控,外卖筷子掉在地上都没察觉,直到运维说“切换完成”,才发现后背全湿了。 跑题说个祖传逻辑。我们有个老系统,表结构里有个“is_deleted”字段,类型是TINYINT,1表示删除,0表示未删除。三年前我刚接手时,发现这字段居然没建索引——问老同事,他说“以前数据量少,全表扫也快”。结果去年数据量破亿后,删除操作的SQL执行时间从10ms涨到2秒,直接触发超时告警。我加索引时,发现这字段的值全是0或1,根本没其他值——原来从系统上线到现在,没人用过删除功能,都是直接标记为“已失效”。我盯着这个字段,突然就想起产品说的“未来十年所有业务”——有时候,架构的瓶颈不是技术,是业务根本没走到那一步。 回到“优胜劣汰”这事儿。我觉得架构设计就像种树——你不能一开始就种参天大树,得先种小树苗,等它长到一定高度,再砍掉旁枝,换更粗的树干。比如我们第一版用Spring Boot+MyBatis,后来换成Spring Cloud+JPA,再后来又引入Service Mesh——每次换架构,都是因为前一种方案撑不住了。但你说这些换架构的决策,有多少是“最优解”?我觉得没有——都是被业务逼的,是“不得不换”。就像去年双十一前,我们为了撑住峰值QPS,把所有接口都加了限流,结果正常流量时也被限了10%——产品骂我们“自废武功”,可要是没这10%的限流,系统早挂了。 现在回头看,这三年最正确的决定,不是用了什么新技术,而是“敢砍”。砍掉不用的字段,砍掉冗余的接口,砍掉过时的架构——就像去年我们砍掉那个三年没用的定时任务时,运维说“这任务在日志里跑了三年,突然没了,我有点不适应”。我说“不适应就对了,架构的进步,就是从‘不适应’开始的”。 当然,我也有很多局限。比如现在10亿级的数据量,我们还在用MySQL分库分表,而竞争对手已经用TiDB了——不是不想换,是换的成本太高,业务等不起。所以有时候我也在想,所谓的“高增长路径”,是不是就是“在业务能容忍的范围内,用最土但最稳的方案”?就像那个“extra_info”字段,从VARCHAR(255)改成TEXT,再改成JSON,最后改成单独的表——每次改都骂娘,但每次改完,都能撑过下一个阶段。 最后说个真事。上周五下班前,测试妹子说“我发现个问题,用户表的主键是自增ID,要是哪天用完了怎么办?”我盯着她手里的奶茶,心想“这姑娘刚入职三个月,居然开始考虑十年后的事了”。我说“用完了就改用UUID,或者雪花算法——但现在,咱们连10亿都没到,先别操这心”。她哦了一声,转身走了。我盯着她的背影,突然就笑了——架构师的焦虑,大概就是这样,永远在为“可能发生”的事准备,而业务,永远在推着你去解决“已经发生”的事。 (编辑:站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |


App卡顿元凶:控制架构设计失当