hive经典面试题5--近实时数据处理方案

背景:
Flink在各大社区、技术类博客活跃的背景下,其实很多小公司并不会花很多时间去尝试实时处理数据,反而更加倾向于近实时处理数据。你可能会说,这个公司真传统。如果站在数据稳定、数据质量高、迭代快、上手容易的角度来说,近实时也是很好的解决方案。

近实时:

利用spark-sql内存计算,10分钟、30分钟、60分钟的频率去更新数据,分为分时数据,分时累计数据。为什么最小的频率是10分钟,因为打点日志的更新频率是10分钟,flume每10分钟上传前10分钟数据文件到hdfs(每个公司的业务不一样,频率也不同)。这样就有一个问题,凌晨切数据的时候,当日分区的里面,可能会有前一天的数据,也有可能会有后一天的数据,这种数据量很小,只可能有10分钟左右的数据,并不会影响我们总体的统计。

如图,上面为昨日分时数据和分时累计数据,下面为今日分时数据和分时累计数据:
图一,最上面为分时累计数据,截止到24:00点的汇总数据(即昨日完整数据,累计到24:00),下面为每10分一个点的分时数据(每10分钟一段):
昨日分时数据和分时累计数据
图二,最上面为分时累计数据,截止到10:30分的汇总数据(即截止到10:30分累计数据),下面为每10分一个点的分时数据(每10分钟一段):
今日分时数据和分时累计数据

那问题来了:
问题1:数据跨天问题

这种在凌晨有前一天的数据或者有后一天的数据,我们怎么处理呢?是怎么去归类数据呢?
如果在当日分区里面有前一天的数据,我们会算到凌晨00:00-00:10分这个时间段。
如果在当日分区里面有后一天的数据,我们会算到凌晨23:50-23:59分这个时间段。

处理代码如下:
spark-sql> with test_data as
         > (select 1639238286 as dateline,'20211212' as dt
         > union all
         > select 1639324686 as dateline,'20211212' as dt
         > union all
         > select 1639274286 as dateline,'20211212' as dt
         > union all
         > select 1639325166 as dateline,'20211212' as dt
         > )
         > select
         >   dateline,
         >   dateline_format,
         >   from_unixtime(dateline,'yyyy-MM-dd HH:mm:ss'),
         >   from_unixtime(dateline_format,'yyyy-MM-dd HH:mm:ss')
         > from 
         > (select 
         >   case when dateline<unix_timestamp(dt,'yyyyMMdd') then dateline+600 
         >   when dateline>unix_timestamp(dt,'yyyyMMdd') and (dateline-unix_timestamp(dt,'yyyyMMdd'))>=86400 then dateline-600 
         >   else dateline end as dateline_format,
         >   dateline
         > from test_data) t1;
1639238286      1639238886      2021-12-11 23:58:06     2021-12-12 00:08:06     
1639324686		1639324686		2021-12-12 23:58:06		2021-12-12 23:58:06
1639274286		1639274286		2021-12-12 09:58:06		2021-12-12 09:58:06
1639325166		1639324566		2021-12-13 00:06:06		2021-12-12 23:56:06
Time taken: 3.891 seconds, Fetched 4 row(s)
问题2:分时数据点归类问题

00:00-00:10、00:10-00:20…23:50-23:59这之间的分时数据算到那个点上呢?
合理一点的归类如下:
00:00-00:10之间的数据归到00:10这个点上
00:10-00:20之间的数据归到00:20这个点上

23:50-23:59之间的数据归到24:00这个点上,
统一都归到后面的点上

处理代码如下:
spark-sql> with test_data as
         > (select 1639238286 as dateline,'20211212' as dt
         > union all
         > select 1639324686 as dateline,'20211212' as dt
         > union all
         > select 1639274286 as dateline,'20211212' as dt
         > union all
         > select 1639239486 as dateline,'20211212' as dt
         > union all
         > select 1639325166 as dateline,'20211212' as dt
         > )
         > select
         >   dateline, --原始时间戳
         >   dateline_format, --加工后的时间戳
         >   dateline_hh, --格式化时分秒
         >   dateline_format_hh, --加工后的格式化时分秒
         >   case when hh='00:00' then '24:00' else hh end as hh
         > from 
         > (select
         >   dateline,
         >   dateline_format,
         >   from_unixtime(dateline,'yyyy-MM-dd HH:mm:ss') as dateline_hh,
         >   from_unixtime(dateline_format,'yyyy-MM-dd HH:mm:ss') dateline_format_hh,
         >   concat(
         >     date_format(from_unixtime(substr(dateline_format,1,10)+600),'HH'),
         >     ':',
         >     concat(floor(date_format(from_unixtime(substr(dateline_format,1,10)+600),'mm')/10),'0')
         >   ) as hh
         > from 
         > (select 
         >   case when dateline<unix_timestamp(dt,'yyyyMMdd') then dateline+600 
         >   when dateline>unix_timestamp(dt,'yyyyMMdd') and (dateline-unix_timestamp(dt,'yyyyMMdd'))>=86400 then dateline-600 
         >   else dateline end as dateline_format,
         >   dateline
         > from test_data) t1) t2
         > order by hh;
1639238286      1639238886      2021-12-11 23:58:06     2021-12-12 00:08:06     00:10
1639239486		1639239486		2021-12-12 00:18:06		2021-12-12 00:18:06		00:20
1639274286		1639274286		2021-12-12 09:58:06		2021-12-12 09:58:06		10:00
1639324686		1639324686		2021-12-12 23:58:06		2021-12-12 23:58:06		24:00
1639325166		1639324566		2021-12-13 00:06:06		2021-12-12 23:56:06		24:00
Time taken: 28.822 seconds, Fetched 5 row(s)
问题3:数据完整性问题

怎么保证我们的数据点都是完整的?例如到00:20,那要保证我们的数据要大于等于00:20的数据

处理代码如下:

我们以调度频率为每10分和40分去执行任务:
每10分和40分去执行任务时,保证了我们在整点和点半的数据
如果我们的脚本执行时间超过30min怎么办?
如果20min容错还解决不了,那干脆1h执行一次。
如果由于某个点集群资源卡,执行时间超过当前的小时,注意要加hh和mm的限制条件
下面是容错20min内的代码:

varcurdate=`date +%F\ %T`
hour=`date '+%H'`
minutes=`date '+%M'`

if [[ "${minutes}" > "40" ]] && [[ "${minutes}" < "59" ]]; then
  varexetime=${varcurdate:0:11}" ${hour}:30:00"
elif [[ "${minutes}" > "10" ]] && [[ "${minutes}" < "30" ]]; then
  #hour=`date -d "${varcurdate} 1 hour ago" '+%H'`
  varexetime=${varcurdate:0:11}" ${hour}:00:00"
else 
  varexetime=`date +%F\ %T`
fi

varcurtime=`date -d "${varexetime}" +%s`

在sql代码中,限定substr(dateline,1,10)<=varcurtime,保证页面的数据是整点和点半

问题4:分时累计数据点归类问题

根据上面问题3,,我们限定了数据时间戳的时候,我们累计的时间点其实也出来了。

select
  sum(expend_amount) as expend_amount,
  dt,
  'varexetime' as hh
from test.test_expend
where dt='vardate' and substr(dateline,1,10)<=varcurtime
group by dt
问题5:每日补数据问
  1. 实时的执行任务,数据只到23:40分,还有20分的数据怎么办?通过每日的脚本重新刷一下昨日分时数据和24:00点的累计数据
  2. 如果实时执行的脚本中,某一个分时累计点有问题,那我们需要通过每日的脚本去补这个点的数据。

有任何问题,可以下方评论留言,欢迎探讨各类解决方案!!!

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值