百度手机助手存储资源优化实践
导读:本文主要总结一下笔者之前做的关于业务存储资源优化的整个过程,正所谓前事不忘,后事之师,希望以文中的例子为引,能够总结出一些如何避免坑以及如何填坑的方法论。
全文 19135 字,预计阅读时间 26 分钟
一、业务介绍
为了更好的理解下面介绍的点,先对业务的一些概念进行简单介绍。
「百度手机助手」:百度手机助手是在 Android 系统上的手机应用分发平台,管理开发者上传的 Android 应用,经过转存等处理后将应用分发到 C 端。
「增量更新(省流量更新)」:如上面的业务框图所示,开发者将应用传到开发者平台(app.baidu.com), 为了保障下载的稳定性以及速度,助手会将开发者的应用会转存到百度内部的存储服务上,叫做 BOS(Baidu Object Storage)。为了节约用户下载的流量,助手启动了增量更新的能力。增量更新是指新版相对旧版生成差异包(下文叫 patch 包),在更新软件时,将旧版本的包与差异包合并成为最新版本的过程。相对全量更新更省流量,降低了用户更新软件的流量成本。
二、为什么优化
在优化的时间点,整个助手的存储占用已经达到了几 P 的量,每年的预算费用近千万。从业务上进行数据分析,通过分析对应业务场景的 mysql 库,库中会记录对应应用的大小。分析后的大致数据如下:
这里面会发现应用 patch 包的占用非常大,同时发现存储总量-已知存储后,仍有 P 级别的存储是未知的。这里应用 patch 包的存储占用是否符合预期需要看一下。
所以,为什么优化就有了几个合理的理由:
高预算消耗
寻找存储去哪了的执著
把无用数据清理掉的强迫症
下面就展开整个清理的过程。
三、分析
优化的第一步就是分析要怎么优化,把闲置的存储找出来,然后优化它。用普通话来说就是猜。此处的闲置,可以定义为消耗的存储带来的价值不符合预期。存储的价值是什么?分几部分来说。
「应用存储」
统一转存到百度,首先安全,如果使用第三方的服务,存在被偷梁换柱的风险;其次稳定,可以自己对存储以及下载进行优化;最后可以基于内部存储做一下定制化的能力,比如动态追加数据等。应用存储在百度的价值无可替代,简单来说是钱花得值。
「应用 patch 包」
对这部分的价值定义,在用户节省下载流量的场景下有价值,否则没有价值。即如果我们生成了 patch 包,占用了存储,但用户却没有升级该版本,那么就是没有价值。
「不知道去哪了的存储」
当然要挖出来,看看是哪家妖怪。
有了初步的方向后,要进行更准确的确认,判断收益空间。从下面两个角度进行验证。
「存储占比」
整个存储的 object 在优化之前差不多亿+条,没有短时间内快速获取全部 object 的方式,采用了抽样的方法,拉取了线上 30W 条数据进行初步分析,下面是存储空间占用的分布
▲存储空间分布
「更新流量的分布」
▲更新流量分布
有了上面的数据,可以从基本面看出,省流量更新的存储消耗更大,但是实际的流量价值却很低,基于此可以确定要对省流量更新的 patch 包下手了。
四、优化思路
就像把大象装进冰箱一样,开门-放大象进去-关门。优化也不是上来就动手把存储清除,整个过程参考大象装冰箱的思路,分为三步:
4.1 复原全貌
正所谓 “知己知彼百战百胜”,做一件事情降低风险的第一要领,应该是把事情摸清楚。对于存在几年的老业务,如何去摸底,总结下来有几点经验。
「内部文档」无论是技术文档还是需求文档,尽量都去看一遍,同时带着问题看,把自己代入到写文档的视角里,多思考下为什么文档是这样的,这样可以尽可能多的挖掘出一些疑问点。
「代码」
核心的代码逻辑一定要过一遍,时间越长的代码,补丁可能越多,一些边界的场景都隐藏在代码的小角落。
「人」
找到相关的同学 或者 不相关的同学(第三者视角),带着基于文档和代码的疑问进行沟通、询问、刨根问底,补全思维偏差。
「产品」
基于产品功能进行回归,将文档和代码进行串联,形成清晰的代码地图。
最后,基于全面的信息梳理,完成基于数据流的业务流程图。整个过程有点像是
《长夜难明》的探案过程,抓住每一个线索,完成最后的拼图。
拼图 1-增量更新场景的数据流
从图中,可以看到主要的存储分为三部分,「开发者应用,客户安装应用,省流量 patch 包」。其中 patch 包的生成步骤为:
获取开发者已安装应用
生成 开发者已安装的应用 和 高版本应用的 patch 包
拼图 2-用户安装应用收集
拼图 3-增量更新处理
核心的数据处理流程如下:
4.2 制定方案
由于是进行存储优化,那就主要关注梳理出的数据流程各个环节是否可以优化 以及 是否要进行优化。首先,磨刀不误砍柴工,从 BOS 处通过 api 导出全量列表,由于历史积累,共亿+条 object 数据。然后基于原来的增量更新策略 制定出了对应的优化策略。
在梳理方案的过程中,深感项目的评估以及持续跟进的重要性。下面举几个例子简单说明下。
最初处理的时候,为了快速解决用户的增量更新的目标,设计时对全部应用一股脑的生成增量 patch 包,但是并没有考虑到用户是否会进行更新的场景,也就是实际的 ROI。实际上只覆盖 top300 更新的应用,就已经能够占比 93%的更新请求,但是能够减少 95%的存储占用,是非常明显的对比。
在初版的策略里并没有考虑业务特性,原始的策略是取 top10 版本号的包和用户手机安装的包来进行生成 patch,但忽略了同一版本号下会同时存在多个包(客户为了推广,同一版本的包会生成 N 个渠道包上传管理),也就是 1 对 N 的场景。
原来设计的初衷可能是仅生成最高 10 个版本的 patch 就好了,实际上会放大到生成几百个包,也是非常大的存储消耗。还有原来的 top10 的考虑是为了由于 Android SDK 的一些限制,某些低端机型可能无法安装高版本应用,但随着千元机的普及,这个策略也可以成为历史了。
在处理的过程发现上文提到的未知的 P 级别空间,发现是原来物理机迁移,自运维的数据库未迁移,导致之前的增量包虽然占用了 BOS 存储,但是没有在 db 中发现,评估对业务没有实际用途了,最后一股脑清理掉了(非常爽)。
4.3 执行方案
这是最轻松的过程,核心要注意的是要设计好验证方式和回滚方案。此处不细说了。整个效果从高峰的 P 级别降到了百 T 级别,排除毒素,一身轻松。
五、总结
以习惯的五问法做一个回顾,总结下整个过程学习到的东西。
5.1 为什么会产生这么大量的无效存储?
程序没有清除,研发反馈产品设计并未考虑历史存量问题
5.2 谁应该考虑?
研发,个人认为产品和研发的和谐边界是,产品给出要完成的用户功能,技术给出解决方案。产品不用关心存储存多久,只需要提出用户的省流量更新需要在什么场景时效,研发基于产品功能来判断 patch 包是否可以归档删除。
5.3 原系统缺少什么?
文档积累 & 监控 & REVIEW。要做好文档积累,方便有一天需要对系统优化的时候能看到为什么系统是这个样子;要完善监控,做到心里有数;要定期 review,同一个业务逻辑随着产品的演进有可能就会从因地制宜的设计变成历史包袱,保持开放心态,放眼过去,着眼未来。
5.4 该如何避免?
靠你的经验,同时考虑对立面。事情都有对立面,很多时候我们考虑问题都只会着眼于眼前看到的点,阳光之下必有阴影相伴,作为研发可以多思考问题的背面是什么,这样可以更全面的考虑问题,少留一些技术债。
5.5 如何做的更好?
系统永远是为产品服务的,但是研发要考虑投入产出,不仅要考虑研发的投入产出,同时要帮助产品一起考虑产品的 ROI。换个角度去看问题,会发现不一样的技术方案,也许就会 do better。
推荐阅读:
---------- END ----------
百度 Geek 说
百度官方技术公众号上线啦!
技术干货 · 行业资讯 · 线上沙龙 · 行业大会
招聘信息 · 内推信息 · 技术书籍 · 百度周边
评论