自从我接手公司的时候,公司的数据库基本就是单点,为了省钱,一律低配,那个时候的数据库和现在用的一样,对于业务库,我们还是用的阿里云的RDS(MYSQL)。
我记得当时线上就一个core库,core库就是存放一切业务数据,做了读写分离。
当时为什么这么做呢,简单来说就是方便快捷,因为业务简单,最多的一张表的数据当时也就100多万吧就是当时的报名单的一个子表,那时候还做了个事儿,报名单有个查询,就算加了索引速度也提不起来,当时这个表的宽度巨宽,各种字符集都在这张表里;查询一次基本要在1S以上,当时的解决方案就是把这个表的引擎改成myisam了,查询立马降低在120ms的样子。
后来,随着业务的发展,业务拆的越来越细,流量也越来越大,core库已经不堪重负了,于是,开始拆分数据库,同时把服务化也做了进一步的拆分,工程也独立出来了(之前所有的项目都在一个project下,打个包这个酸爽),这样也做到了各个数据库的隔离,但带来的问题是,很多级联查询查不到了,运营的很多数据统计都做不了,怎么办嘞?
我们把core库的核心业务独立出来,分离出商户、用户、兼职、报名单,并且把dubbo的服务化体系一个个和这几个库对齐,做到一个工程对应一个DB,而core库则是历史老坑遗留地,没有人敢碰,一碰就沾包。
但因为成本的问题,2017年的时候,我们还是一分分钱的省下来过日子的,非常节俭;除了core库之外,其他的RDS都是单点的,并非高可用,也不支持读写分离;可能这时候有些人说,你这么做太危险了,这玩意数据库跪了的话,这段时间业务就受很大影响了。实际上这事儿还真发生了,我记得当时我们有一个库,整整挂了有5分钟,5分钟后才恢复的;但5分钟对于当年的公司来说,影响还没有到承受不了的程度,因此,单点数据库在很长时间内,都是支撑业务的主要战力。
随着公司的发展,产品运营越来越多,运营后台的需求与数据需求与日俱增,于是我们为他们专门重构了一个运营后台(简称YY后台);那数据需求是怎么解决的呢,很简单,让运营们直接去生产库上去查,当然用户敏感信息我们还是保密的;但如果让运营去线上去查,如果胡乱执行sql,那不是要对线上库产生较大的影响了吗?于是我们有了以下的改进
我们通过dts将每个库合成一个大库third库,他自身也是个rds,负责和所有的业务库做线上同步,这个库本身就相当于我们的一个线上的备库,对他进行查询操作,不会对线上造成影响。
随着公司的进一步发展,数据量越来越大,并且也出现了埋点的数据,因此,我们建立了另一条埋点链路,这套链路最终会进入离线计算maxcompute;另外,业务数据也要进入maxcompute里。
上图的业务我们大概跑了有一整年,在这一整年了,出现了一个问题,也就是出现在业务库向third库通过DTS这个环节的问题;当我们业务库出现了表级的操作,比如alter语句的时候,会触发大量的binlog产生,dts收到大量binlog后,会向third进行同步;而third库因为要同时接收所有端的数据,他的写入能力遭遇瓶颈,因此会阻塞在DTS上,导致third库严重延时,maxcompute也出现严重超时。我曾经为了解决这个问题,去寻找高性能写的数据库的时候,会发现市面上大多数据库都不满足我这个场景及,高性能的rmdb,又要支持海量数据;目前我所知道的基本就是oceanbase和tidb这两者。tidb不考虑,坑太多,oceanbase目前在公测,不支持内网,也不考虑;那后来采取的策略是,让运营迁移到maxcompute上去查询,虽然时效性不好,但也是一个长期的方案,总不能让运营一直去在线上数据库是随便玩耍呀,于是这个方案就变成这样了,此时mysql的各个实例已经进化到了高可用,支持读写分离。
我们通过maxcompute来直接从只读库拉取数据,主要是依赖于maxcompute的高性能写,并且只读库在同步binlog下,比dts的性能要高出一个数量级,具体为什么可以去看一下dts的实现;另外,这个只读库一定不要做读写分离,因为在maxcompute去拉取数据库的时候,这个时候mysql的iops可能是很高的,如果这个时候有线上的请求过来,是会造成请求阻塞延时的,因此,只读库一定不能作为读写分离的实例。
到这里为止,和我们目前的架构就基本一样了,可能这里面缺少ES、Redis等一些存储,这些主要是为业务服务的,我这里主要是侧重讲关于数据的持久化方案的演进。
——————————华丽的分割线————————————
那么我开始讲一下我们后面要做的事情,随着数据量越来越大,公司对数据的实时性越来越高,maxcompute的离线处理,已经不能满足我们的需求;线上很多业务要做流式处理,实时推荐;比如,一个用户浏览了某些兼职,但没有点击报名,这说明这个用户对这类兼职是不感兴趣的,同时我们要把用户行为实时发送到流式处理里,给用户推送其他的类目。我们采用行业标杆FLINK做流式处理,用redis保存一些数据统计结果集;我们也会有一些数据UI界面的产品,通过访问redis来拿到实施的结果,比如,每天的日活、收入、使用时长等。
网关的加入,我们会把记录访问的所有链路日志,通过网关做鉴权、限流、输出日志、黑白名单校验、灰度等功能,那在这张图中,网关主要是把访问的所有日志,上传到KAFKA中,再转交到FLINK中,通过FLINK来做用户的数据做清洗,再将结构化数据导入到安全中心。而安全中心要做的就是所有的风控判断,最后把数据沉淀到maxcompute里做机器学习,不断优化风控规则。