TalkingData用数据诠释感性的改变,同一个世界,同一个语言。世界运转,社会发展,移动互联,再到人们生活的点点滴滴,我们用数据的语言沟通,用数据的思维改变。 以大数据的思维,改变对精确性的苛求,转而追求混杂性;改变对因果关系的追问,转而追求相关性。真正的革命并不在于分析数据的机器,而在于数据本身和我们如何运用数据。一旦思维转变过来,数据就能被巧妙地用来激发无限创新。
架构创新哲学没有最好只有更好。其实还有一句话就是没有最好的只有最适合的。在我们做软件架构的时候,其实适合的就是最好的。
接下来分享的内容就是基于这一点,首先是背景介绍,再来是针对性的解决方案。然后讲到今天的主题——分布式计算框架,最后是通过实践来验证框架的可靠性。
项目背景
简单介绍一下,我们的团队专注于做TalkingData移动运营平台企业版的开发,所服务客户的App日活小的有不到10万,大的可以达到数千万。我们团队致力于让移动运营平台企业版能够弹性地支持小、中、大型等企业客户,系统稳定且易于维护。
2015年,我们团队负责移动运营平台企业版V3.0及后续版本迭代,当时的设计目标是支撑500w日活。2015年9月到2016年8月交付给客户运行,事实证明能够满足绝大多数企业客户的需求,能够稳定地支撑他们的业务。
但是,到了2016年9月,一个客户上线了几个日活量较大的App,系统的整体日活达到了2000万。这时候问题发生了,运维人员反映MySQL的binlog增长迅速,快把剩余磁盘空间占满了。
问题分析
为什么会有这样的问题?
我们可以把昨天的活跃值算出来,但是这样有一个缺陷就是无法实时,而我们客户一般都是要求有实时的指标。另外一方面,T+1这种方式的指标不够灵活,比如说客户希望某一个时间段的活跃度,如果这样计算的话有不同的指标。如果说是灵活的时间选择的话,用T+1不是很好计算,可能要耗费大量的资源。
我们利用bitmap技术做数据的排查。什么是bitmap呢,大家应该知道。当设备进入系统,我们会给它分配一个序列号,这个序号从1往上累加。计算活跃用户时,某一天从零点开始,所有设备的初始状态都为0;假定到了当天8点10分,设备3和设备N-1访问了App;到了9点20,设备2和N-1访问了App,我们把设备N-1两次都设为1,计算活跃用户时我们数一下有多少个1就可以了,我们看最终的bitmap计算的活跃用户为3而不是4,这样我们就做到了数据的排重。
我们看这张图,我们将bitmap存储到MySQL数据库里。当要更新某个维度的bitmap,比如说今天的活跃用户。我们会先从数据库中查询出未更新前的bitmap,可以看到bitmap大概是1到3MB左右,然后更新某些设备的值为1,最后回写到MySQL中,MySQL因为做了备份会写binlog到磁盘里面去。这就是我们计算框架大概的处理过程。
每个bitmap对象的大小从数百KB到数MB不等,如果某个客户的多个 App加起来做到两千万日活,最终bitmap的大小平均是3MB左右。
使用bitmap这种数据模型有利有弊,前面提到我们使用MySQL存储bitmap索引,因为MySQL稳定且易于运维。但大块(1M~5M)的二进制对象(约30w个bitmap对象)频繁读写,导致网络IO、磁盘IO等资源耗费巨大,MySQL binlog增长过快导致存储空间不够与浪费。
解决方案探索
出了问题就要解决,而我们的解决方案需要满足下面三点:
数据备份
性能高
易于维护
为了解决这个问题,我们有三个候选解决方案:
方案一:替换MySQL,使用druid/rockdb等大数据组件。这种做法没问题,我们可以自主研发插件,实现刚才的数据搭配。但是,就当时的情况来说,这个方案还不是很成熟,因为对运维要求比较高。
方案二:在MySQL前面引入redis缓存层,定时同步到MySQL。redis宣称一秒钟可以处理数十万的数据,当我们用基于上百K甚至是数MB的数据来做的话,做不到这么大的并发,只能支持每秒上千条数据。
方案三:调研使用Apache lgnite组件。我们做了大量的测试,在大数据上面使用就会使用数据备份,如果说压力测试值比较大,就会造成异常。
随后我们得出了一个结论,这三种侯选方案都不合适我们的场景,不能完全解决我们产品的问题。
权衡下来,我们决定实现一套分布式内存计算框架,代号Blade,意在像锐利的刀锋一样有效解决企业产品的问题。
分布式内存计算框架
Blade
Blade简介
和之前相比,增加了“Blade”这一块。它会把bitmap索引缓存在内存中,数据处理程序只需要告诉Blade修改哪个bit,无需把整条bitmap索引从DB拉取到本地更新后再写回DB,Blade会负责内存中的bitmap索引与MySQL的同步。在缓存方面有几个重要的特性,过期和踢出功能,保证我们的缓存在达到一定的限量时,能够通知我们做数据的更新。
Blade的优势
Blade能够减少更新MySQL中bitmap索引数据的频率,彻底解决大活跃客户出现的问题,对比之前提出的三种候选解决方案,它主要有如下优势:
基于成熟的组件(Ehcache、redis、zookeeper、jetty),易于维护;
对比单纯使用redis,不需要处理达2到3MB的bitmap索引数据,系统稳定,高并发有保证;
能够实现Apache Ignite的Expired、Eviction等缓存功能,频繁更新时不会出现OOM问题。
Blade主要模块及架构
Blade系统有几个主要模块,一个是客户端,一个是集群,然后是数据同步,最后是集群管理。
Blade Client客户端:
Blade Client是一个Jar,应用程序用这个Jar的API发起对BladeCluster的调用。Blade Client在启动时,会从ZK上获取到整个Blade Cluster的运行情况。它会监听ZK事件,当Primary Node宕机或新的Secondary Node启动了,它可以立刻得到通知。Blade Client使用一致性Hash算法,把Key尽量均匀分布在整个Blade Cluster的所有ReplicaGroup 上。
Blade Server服务端:
Blade server可以有三种架构,我们选择第二种,即一个Blade Server包含一个Jetty和一个Redis。
Jetty和Redis部署在一个节点上,能够保证在不占用系统带宽的情况下实现对bitmap索引的高速存取。Redis只作为一个大缓存使用,Redis本身的分片、集群、主备等功能全部都不使用,因为Blade本身架构就已经实现了这些功能。
Replica Group 复制组:
主要用于防止单节点Blade Server宕机后,丢失缓存对象信息,同一个复制组中的Blade Server缓存对象会保持一致。
Data Sync 数据同步:
刚才也说过,会定时把数据挖出来,进行合并和运算,把最终的数据存到数据库中去。
Blade Admin 集群管理:
主要用于监控整个Blade Cluster 的情况,包括每个Blade Server的情况、Replica Group的情况、Blade Data Sync的同步情况。
Blade Admin 还提供启动某个ReplicaGroup 的Primary Node、SecondaryNode之间的同步,以及启动Blade Data Sync的同步这样的管理功能。
压力测试:
压力测试在我们这里是很重要的一个环节。
压力测试的环境是,基于2000万日活,每个用户产生20条日志,每条日志大小约为12KB,总计约4.8TB数据每天。
机器配置方面,除了一些报表数据,真正做数据处理的有10台左右。
我们测试要做对比,不使用这个框架,我们就会有2TB左右binlog,真正处理4.8T数据需要70个小时,不能支撑处理2000万日活数据的实时运算。
压力测试的结果是,在使用Blade框架之后:
MySQL binlog 50GB 左右
处理4.8T数据约需要20小时
能够支撑处理2000万日活数据
针对前面提到的某客户,我们上线了分布式内存计算框架,彻底解决了前文提到的问题。分析对比如下:
binlog减少了大概40倍左右,存储空间控制住了,运维也不会报警了。
浏览5936次
浏览1633次
浏览10763次
浏览7244次
浏览2185次
浏览5701次
2025-01-08 昆明
2025-06-20 深圳
2025-04-19 南京
2025-08-15 上海
打开微信扫一扫,分享到朋友圈