Chinaunix首页 | 论坛 | 博客
  • 博客访问: 186499
  • 博文数量: 13
  • 博客积分: 1660
  • 博客等级: 上尉
  • 技术积分: 688
  • 用 户 组: 普通用户
  • 注册时间: 2008-08-04 16:38
文章分类
文章存档

2014年(2)

2013年(11)

分类: 大数据

2013-09-11 17:10:03

接触这块将近3个月左右,期间给自己的定位也是业务层开发。对平台级的产品没有太深入的理解和研究,所以也不能大谈特谈什么storm架构之类的了。
说说业务中碰到流式计算问题吧:


1.还是要介绍下简要的架构(原谅我不会画图)

流式数据接入层------------------->流式数据处理层------------------->结果数据归档层
                                                        ||
                                                        ||
                                                        ||
                                                        V
                                               中间数据存储层


所有的数据通过接入层源源不断地进入到这个系统, 在数据处理层得到相应的计算存储, 最后将结果写入到归档层,供下一个系统查询或作他用。

系统相比于数据仓库,数据库等系统的不同:
1.数据是一个个到来,下一个时段的数据是未知的
2.数据到来的速度也是无法控制的
3.数据是有实效性的,必须及时处理
4.数据从采集系统到达接入层的顺序是不能保证的
5.任务永无止境


如果将其和hadoop的map-reducer任务对比,区别在于:
map和reduce一直在运行,map源源不断的发送数据,reducer也不停地处理数据,没有任务执行完的概念。


2.系统需要实现的业务逻辑
对于常见的数据业务,有如下几点,对数据库比较熟悉,就拿sql的几个操作对比了:
select ---------------------------固定数据查询(异常或者脏数据处理),
max/min/avg-------------------最大最小值
count/sum----------------------求和或次数统计(比如pv等)
count(distinct)------------------去重计数(典型的如UV)
order by------------------------排序(取近访问的用户)
group by + 聚类函数 + order by-----聚类后排序(如访问次数最多的topN商品)

3.具体的实现方式:
3.1 指定查询
这是流式系统里最简单的处理方式,一般而言进入系统的一个元素是一个个字符串对,(arg1,arg2,arg3,……)
那么指定查询,就是比较下arg的值,符合要求即做下一步的处理,等到需要时统计结果。
数据读取次数:读0写1

3.2 最大最小值,平均值----------中间变量
在中间存储器上保存一个中间变量,每次仅需取出来,进行计算后更新即可。
数据读取次数:读1写1

3.3 TopN排序----------------最大最小堆
同3.2,稍有不同的是,需要保存一个数据结构堆。每次更新也需要有相应的插入删除实现。
数据读取次数:读1写1

3.4 窗口内计数--------------------DGIM算法
这里先要谈一下时间窗口:其实可以理解成一个队列,包含两个操作,add和remove。
同时还要考虑的是,时间并不是进入系统的时间,有可能是自带的日志时间,这个是会乱序到来。
这里谈计数,就还包含了一个操作,isContainsKey和get。



3.4 去重计数----------hash表,搜索树,FM算法,组合估计
四种方式的逻辑是一致的:一要保存历史数据,二是要压缩历史数据,三是要方便查询(判断是不是存在了,且任意时刻都能汇总结果)。
而空间,时间,准确性三个指标又是不能全部顾忌的(是不是有点像cap定理了?),你不能要求占用空间有小,判断时间短,同时又准确。

一般而言我们是选择牺牲准确性(但也要保证一定级别的准确,差一个量级的话,那就荒唐了),毕竟任何系统都没有要求UV这种数据准确到个位数。
这里建议看下FM算法的实现。

3.5 特殊指标过滤--------bloom filter
bloom filter 真是个古老而又流行的东西。目前接触过的系统,如果用到过滤,大部分都第一时间考虑bloom filter过滤。
他其实是一个泛化的hash(多个hash函数),节省空间,时间,同时准确性保证了一般(会漏,但是不会误判)。

3.6 热度统计------------指定时间窗口统计
首先确认你的统计粒度。是流水记录级别的,还是分钟级别,还是小时级别。
对应到时间窗口,那就是你时间指针滑动的最基本单位。

例如 你计算 最近一天的热销排行榜,那么你窗口的长度是24小时,同时你的粒度是5分钟级别的。
那么:
你一共需要保存288条时间粒度的数据,每一条表示5分钟内商品的相关信息,我们记为函数t(timeID)
weight = f(productID) = K1 * t(1)+ …… + K2*t(288)

ps:如果存储系统能够支持,将288条时间数据合并到一条key里,对性能又很大的提高。

3.7 排行榜-----------------随时间衰减。
这里一般性的问题在3.6里会处理,但有一个却无法解决。
如果你是一家论坛性质的网站,有十大热门贴,我们记为t1,t2,t3,……,t10。如果有访问,或者新的记录过来的话,我们更新即可。

但是还有一种情况是,在半夜长达几个小时的情况下,是有可能没有任何访问的。那么顺序还是原来的那个顺序吗?
不一定,以为每个时间片段的权重不一样。可能顺序会是:  t3,t1,t2,t10……

这时候我们的方法是:自己构造一些定时调度的数据,例如5分钟一次空数据,触发计算过程,重新更新3.6节里的weight值。


4.高级分析函数的处理
再高级一点,设计到不同维度的数据计算,有这么一些:
where--------------------------指定统计范围
group by + having-------------细分不同维度的统计
join + union--------------------多个数据合并

至于rollup,cube等高级分析函数就不说,实质上由于你可以拿到最明细的数据,什么计算方式都能处理过来的。

5. 性能问题-----------抽样与近似
万一数据量大到你的系统实在是处理不过来了怎么办?如果不需要准确值,那就抽样吧!
抽样是解决数据量大的最好办法,可以极大程度减少计算量,其实很多情况下我们并非需要那么准确的计算值。
比如推荐需要的是一个商品排序,用户排序(当然网站统计的需求基本就不能抽样了,老老实实想别的办法吧)。

这里需要注意的是,要非常了解数据的分布,比如你求平均值,抽样却漏掉了极少数的极值,那样误差就大了。

阅读(15407) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~