流计算技术实战 - 超大维表问题

维度表,作为数据仓库里面的概念,是维度属性的集合,比如时间维、地点维;

但这里要讨论流计算中的维度表问题,

流计算中维表问题和数据仓库中有所不同,往往是因为通过agent采集到的数据比较有限,在做数据业务的时候,需要先实时的把这些维度信息给补全;

这个问题其实就是,主数据流和多个静态表或半静态表之间的join问题。

在flink中称为side input问题,https://cwiki.apache.org/confluence/display/FLINK/FLIP-17+Side+Inputs+for+DataStream+API

解决维表问题考虑到点,

a. 对元数据库的读压力;如果分析程序有1000并发,是否需要读1000次

b. 读维表数据不能拖慢主数据流的throughput,每秒千万条数据量

c. 动态维表更新问题和一致性问题;元数据是不断变化的,如何把更新同步到各个并发上

d. 冷启动问题,如何保证主数据流流过的时候,维表数据已经ready,否则会出现数据无法处理

e. 超大维表数据会导致流量抖动和频繁gc,比如几十万条的实例数据,可能上百兆

下面谈谈我们解决这个问题的思路,

1. 最简单的版本,每个进程都会独立的去从元数据里面读取元数据;

这样的优点是简单,c,d问题天然解决;但只能适用于数据量较小的场景,否则并发太大,a,肯定就无法满足

2. 随着业务量的扩大,处理程序的并发越来越大,1,很快会达到瓶颈

我们就采用新的方案,这个方案是在Jstorm环境实现的,用一个spout读,然后广播给所有的处理进程

这个方案主要解决a,c的问题,
但是也引入了d,e的问题,

解决d,Jstorm支持让某个spout在job启动后等待一段时间,所以可以让主数据流spout等待几分钟再开始读数据,这样保证数据到的时候,维表数据已经ready;这个解法每次重启job都要等好几分钟,体验挺差的,但是勉强可以work

e问题,一个spout广播超大维表到几百并发的线程,首先就是会队列满,因为jstorm发一份数据到所有并发的时候,是需要产生几百份真实数据在队列中的;然后GC也会很严重,因为大量的临时对象会产生释放,在传输和进程cache过程中,会导致业务抖动

这个问题只能增加内存和worker数来解决,否则job有可能会完全hang死

我们也用Chronicle Map(https://github.com/OpenHFT/Chronicle-Map)来尝试解决内存使用和gc的问题

BTW,有同学问,如果让数据和维表数据都 shuffle by key,是不是可以缓解这个问题
如果数据量比较小,可以考虑,但是对于我们的主数据流的数据量,是没法shuffle的,所以需要在每个并发上保留全量的维表信息

2.1 用Flink带替换Jstorm

Flink虽然在window,乱序,一致性等方面做了很大的改进,但是在这个问题上仍然没有很好的解,上面提到的side input也没有实现出来;

并且Flink随着更多的高层的封装,程序员的开发自由度是降低的,和JStorm比,所以如果用Flink解决上面的问题,没有本质变化,可能JStorm更麻烦;

需要用ConnectedStreams去joine数据流和side input流,
对于d问题,没法直接解决
对于e问题,因为flink对内存管理做的比较好,gc问题有所缓解,但是job抖动的问题还是会存在

因为广播这么大的数据,会中断主数据流的数据处理,也会大大增加checkpoint的时间,如下图,可以看到30分钟一次的同步

BTW,Flink保障一致性,提供checkpoint机制,但也增加复杂性,这个地方处理不好会有很多问题
比如,如果在source中同步读数据库数据,如果读库的时间比较长,就会hang住主数据流,因为其他operator都会等它完成checkpoint,写JStorm的程序员需要注意这点,Flink需要更精细的控制,任何operator,任何并发的hang都会导致整个任务hang

我个人尝试使用flink本身的机制,statebackend,rocksdb等来更优雅的解决这个问题,但是没有发现比较好的方法,或者实现过于复杂

3. Redis版本

这其实是把1,2方法做了综合

使用redis来做cache,只用一个job,负责从元数据库同步数据到redis,这样就解决a,c

然后所有的并发都从redis直接查询需要的元数据,这样就解决d

对于b,在并发上做local cache,只有第一次需要真正查询redis,后续定期异步更新就好,不会影响到主数据流

对于e,因为现在不需要一下全量的读取维表数据到内存,用到的时候才去读,分摊了负载,也可以得到缓解

该方案当前线上跑着,还算比较稳定

这个方案最大的缺点是增加依赖,对于需要全球多region大规模部署的应用,增加依赖是成本极高的
同时要额外保障redis和同步job的稳定性

BTW,这里不建议local cache用LRU,因为要考虑到当redis挂掉或同步job挂掉的时候,不能影响主数据流,所以我只会异步的更新local cache,但不去做过期,这样就算redis挂了,也只是影响更新的实例,大大降低故障发生概率

总结,

分享一下自己的一些实战经验,希望可以抛砖引玉,找到更合理,优雅的方案

时间: 2024-10-10 10:35:15

流计算技术实战 - 超大维表问题的相关文章

层次结构和二维表的关系数据存储

摘:Storing Hierarchical Data in a Database Article(翻译版本) 原文链接:http://shiningray.cn/hierarchical-data-database.html 作者:Gijs Van Tulder 翻译:ShiningRay @ NirvanaStudio 无论你要构建自己的论坛,在你的网站上发布消息还是书写自己的CMS程序,你都会遇到要在数据库中存储层次数据的情况.同时,除非你使用一种像XML的数据库,否则关系数据库中的表都不

Excel Power Query经典应用之二维表转一维表

Excel Power Query经典应用之二维表转一维表 将一个二维表格转为一维表格,是我们经常要做的事,目的是为了将数据做更好的分析.但Excel普通的转换的方式却比较麻烦.不过不用担心.利用Excel的Power Query功能,可以实现秒转. 了解更多新技能,扫描关注微信公众号 大话office

采用jsp页面与java代码分离的方式写一个简单的二维表

前提:在我们做程序时追求的是高内聚,低耦合,但是如果我们把jsp页面的的代码和java的代码都放在了jsp的代码编写中,使java和jsp高耦合这样的话不仅使jsp代码页面显得很复杂,而且也特别让不利于以后的维护,所以我们有了一个不成文的规范就是分层架构,把javad代码与jsp的代码分离开来,使jsp代码页中更加干净整洁. 下面我将于用jsp和java代码分离的方法做出这样的一个二维表(做一个jsp页面动态显示信息表) 第一步:首先我们需要一个实体类用于存放一个人的一整条信息(根据表格信息有编

mysql关系(二维表)的设计规范,范式

范式,NF,normal format,就是指对表的结构的要求! 目的:1,规范结构!2,减少数据冗余! 第一范式,1NF,字段原子性 要求字段不能再分,要求字段的原子性 第二范式,2NF,非部分依赖 增加唯一主键即可!ID 范式的要求,是逐渐递增! 在满足 了 第一范式的前提下,不能出现部分依赖! 部分依赖指的是:普通字段对 主键 是完全依赖的,而不应该是依赖主键的一部分! 依赖:可以通过那个字段去决定另一个字段 因此,出现主键部分依赖的前提是,出现复合主键! 其中代课时间,开始和结束时间,没

维表设计

时间维表 统计时间一般被分为日.周.月,其中天都能通过时间可直接截取成某一天20141125,月份也可配截取成20141001 或者 201410,但是周在一年中的开始和结束不一定都是完整的,建议2015W01为新年的第一天到新年第一个周日结束(20140101-20140104),最后一周为2015年的最后一个周一到新年最后一天(20151228-20151231) 函数方式:可以自定义函数来获取这一天所在的 年.月.周 function get_week_of_year(start_date

BIEE 维表

(1)       在物理层给表创建别名(表——>新建对象——>别名) (1)       在业务层创建维度(表——>创建逻辑维——>基于级别层次的维) 钻取是维本身的功能 一般信息中 名称:部门 关键字 作用:确定唯一值和确定显示内容 聚合方式:选择一个表中的字段,双击,选择聚合,里面聚合规则根据自己需求选 聚合:是对换算的统称 (3)在表示层把表名改成中文的,并且加上“Dim”更好的表明此表是维表,标记“FO”的是事实表 (4)登录BIEE后台地址   BIEE中没有上钻

数据库中的二维表—巧借Excel

一维表和二维表的区别         一维表也常称为流水线表格,它和二维表做出的数据透视表最大的区别在于"行总计".判断数据是一维表格还是二维表格的一个最简单的办法,就是看其列的内容--每一列是否是一个独立的参数.如果每一列都是独立的参数那就是一维表,如果每一列都是同类参数那就是二维表. 二维表的建立     开始在网上一直查找如何在数据库中建立二维表,查了很多资料大多是什么静态和动态的sql语句建立,看了看也不是很清楚但是在查询的时候总是出来Excel如何如何,于是便想是否可以在Ex

BI事实上的和维表定义

一个典型的例子是,逻辑业务相比立方体,产品尺寸.时间维度.位置尺寸,分别作为不同的轴.轴的交点是一个详细的事实.这一事实表是多维度的交叉点的一个表.维表是事实的分析的一种形式. 首先介绍下数据库结构中的星型结构,该结构在位于结构中心的单个事实数据表中维护数据,其他维度数据存储在维度表中.每一个维度表与事实数据表直接相关,且通常通过一个键联接到事实数据表中. 星型架构是数据仓库比較流向的一种架构. 事实表是数据仓库结构中的中央表,它包括联系事实与维度表的数字度量值和键.事实数据表包括描写叙述业务(

Lua 多维表的遍历中的赋值

说到Lua的遍历将要使用到循环:先说遍历再说循环: 遇到这样类似结构的一个table Data={ [102]={p1=1,pa={1,2,3}}, [103]={p1=2,pa={2,3,4}}, [105]={p1=4,pa={3,4,5}} } 目的获得key 值与pa的一个表,实现下 1 -- 使用table.insert方法插入到新表中 2 for k,v in pairs(Data) do 3 print(k,v) 4 Data2[k]={}; 5 table.insert(Data