今晚与老大和同事的讨论,让我学到了很多。
主要讨论的问题是,随着线上每日发送量的增长,如何改善现有的分表方案。
最后的结论是:先写文件,再入库。
为什么要采用写文件的方式?写文件难道不是更慢嘛!
没错,写文件是会更慢!
但,慢即是快,舍即是得。
有点哲学内味儿了啊哈。
单表容量限制
系统后台的架构,演化到现在,主要的瓶颈是在单表容量限制上。
目前的分表方案是,每天20张表,每个账号有一个标识,范围就是0~19。
如果某个账号的标识是0,那么这个账号的话单都会固定写到0表。
问题就出现在这里。举个例子,当有3个账号的数据都是写入0表,而这3个账号的量又比较大,那么这张表的记录数就会特别多。
目前最多一次,单表6000万的数据量。
虽然MySQL单表存储1亿的数据都是没问题的,但我们还想查的更快一点。
另外实时统计也依赖MySQL。
引入Elasticsearch
查询、统计都依赖MySQL,如果无法实时写MySQL,那么系统整体就受限制。
为此,我们引入了Elasticsearch,在写入MySQL的同时,也写一份数据到ES。ES只保存最近一周的数据,用来做实时查询。
如果系统并发持续上涨,Elasticsearch我们可以扩容,写入不存在限制。但写MySQL目前最多只能达到6000TPS。
所以,如果写不进MySQL,那么写Elasticsearch也受到影响。
主要矛盾
其实仔细想下,实时写MySQL是有限制的,业务高峰期,写MySQL一定没办法满足实时这个条件,那为什么还一定要实时写MySQL呢。
如果不实时写MySQL,会有什么问题?
没办法查到实时下发数据,不是有Elasticsearch嘛。
没办法做实时统计分析和告警监控,不是有Elasticsearch嘛。
所以这是,实时任务(实时查询和实时统计)与非实时任务(业务高峰期无法满足实时写MySQL)之间的矛盾。
将实时任务和非实时任务区分开
将实时写MySQL改成写本地话单文件,比如10分钟写一个文件,比如1万条写一个文件等等。
然后再通过入库程序,读取文件内容,批量入库。
实时查询、实时统计、实时告警监控,通过Elasticsearch计算。
其实,比较简单一点纬度的实时统计、实时告警监控,也可以在内存里计算。
比如,10秒内回执率、5分钟成功率,就可以在内存中计算。