记一次线上Redis资源优化

闲话

最近在开发一个数据仓库的小版本,因为自己的疏忽(误以为一个重要的流程可以复用,实际不可以)导致工期估计很少而坑了自己,一周的时间都在加班搞这个事情。幸好还是扛下来,少不了同事老毕的帮助,还是很感激有这样的同事的。版本进入测试阶段,终于有时间可以来开始写写博客。这个等版本上线之后可以在来复盘一下。

今天呢,主要是想仔细来梳理一下之前做的一个版本优化,主要是针对线上的一块大流量业务做的Redis资源优化,优化之后这块业务内存资源节约超过65%。在不影响性能的情况下,缓存时间从1天提高到7天。话不多说,下次开始吧。

项目背景

公司有广告数据上报的业务,峰值在1200w+每天,均值600w+。为了应对复杂的归因流程,以及归因回调,需要将这部分数据放入缓存,以免给数据库造成太大的压力。回调相关的参数数据也是放在缓存当中的,缓存保留时间是1天。

需求变更

为了提高归因率,现需要把缓存时间从1天提升到7天。这意味着缓存数据量是原来的7倍,并且增加两种匹配机制,数据量又增加30%。
(我们线上的Redis内存最大容量是16G,12G为告警阈值,按照现有的机制增加的话理论计算上面就已经超过阈值了,因此肯定是要优化的)

前期调研

为了清楚现有业务内存的占用情况,分别对涉及到的7种匹配机制进行调研。在本地分别测试10W数据的内存大小。间隔5天取近两个月的数据总量进行统计,取均值和峰值以及8倍峰值数据量,分别计算理论情况下,各个匹配机制所需要的Redis内存大小。

优化思路

业务层面来说,用户点击广告不一定会下载激活游戏来玩,这一层级的转化其实是有很大损失的,因此匹配回调的数据可以和点击数据剥离。考虑到不同渠道的数据格式和参数个数,检测数据类型不一样的原因,为了便于往后扩展,这里考虑使用MongoDB来存储这部分的数据。

为了不降低归因的效率,我们提供一个主键来允许其他系统业务定位到具体的点击数据。自然的Redis中我们就直接缓存这个主键,而不在缓存原始数据了。归因匹配上了,我们在直接通过原始数据来构造回调参数。这样即使增加了匹配机制类型,但是总的数据量还是减少了很大一部分。
(对于日均量来说,减少了78.3%,对于峰值来说减少了58.7%)

至此还有,最后一个问题没有解决。如何处理7天缓存的这个问题呢。从业务上面分析,对于超过一天的这部分数据,是指一个用户点击了广告,但是呢在一天之后才激活,当然这其中也存在异常激活的情况,但是比较少。

为了这个少部分的数据, 而且不是热点的数据,来缓存如此庞大的数据是非常不优雅的。为此,我们使用到MongoDB的另外一个特性来解决这个问题。

对于MongoDB来说,可以设置文档的自动过期时间,虽然它的精确度不是特别高,但是对于7天来说可以忽略。你是不是已经知道我要干什么了。对的,我们把超过一天缓存的数据都写到MongoDB当中,设置过期时间为7天,我们也只存储它的索引,用于定位,这个缓存库设置分片。

这样整个优化,在理论上就可行了,接下来就是动手实践的时候。具体实施的过程还是踩了一些坑,但都是可以实战解决的。

复盘总结

对于这次优化而言,其实没有特别大的技术点,要点还是在于业务的剖析,能够准确定位哪些是热点数据,哪些是半热数据,哪些是冷数据。从而针对不同类型的数据做文章,分割开来用不同的手段处理。当然对于业务规模的前期调研以及后期扩展的展望也是非常重要的,能够让我们清晰的知道现有系统的健康状况,能不能支撑我们做迭代,以及相对长期的迭代。

我相信这还只是一个开始,未来的路还很长。Storm,砥砺前行!