故障描述:
某张业务数据表中使用了blob类型字段,该字段会被频繁的更新,导致MySQL产生大量的bin log,最终将服务器硬盘写满,导致该机器上其它的业务受到影响
详细原因:
导致这个问题的业务是一个基数统计程序,基于storm开发。算法上采用了HyperLogLog,为了能够统计每小时的活跃用户数量,每小时对应一条HyperLogLog结构。每当数据到达后会更新对应时间段的HLL结构(为了使用MinK算法做差集,还保存了其它数据,最终一个结构大概40KB)。因此这个字段的更新是很频繁的,每次更新需要的数据量也非常大。最终的结果就是这个storm拓扑上线运行了几天之后,某台业务服务器上运行着MySQL从服务器,MySQL bin log将磁盘写满,导致业务故障。
总结和分析:
比较郁闷的是,在决定把HyperLogLog保存到MySQL的时候,也做过一些考量:数据表大小的增长只和时间有关,和用户数无关,在可预见的时间内大小是没问题的;为了应对将开的可能的数据迁移,表结构的设计极其简单,只有主键ID和blob两个字段。可是万万没想到流量对bin log的影响,结果上线不到10天就出问题了。好在知道是MySQL bin log占用了磁盘空间之后,瞬间就怀疑到是统计程序这边的问题。
解决方案:
个人觉得理想的方案是将HLL 存到HBase或者Redis中,不过眼下没有稳定的可用的HBase和Redis集群,MySQL是目前能够使用的最靠谱的存储。
so,目前的计划方案是将Redis作为缓存用。HLL数据的更新,数据直接写到redis中, 再定时更新到mysql中。优先将“不活跃”的数据写入mysql(理论上一条HLL数据,在创建后的几小时内会被频繁更新,时间越久被更新的可能性越小)