最近一直没有写博客,一方面是懒,一方面是感觉没什么可写的,还是懒吧。
近期的工作都是出各种报告,大多是添加统计指标,比如请求数,ip,uv等。因为事先有老大写的代码可以参考,上手还算快。这里不得不提的是老大自己写的任务调度系统,线上的各种报告,实时计算,离线计算都是通过这个系统来调度的,在我来之前整个系统在我来之间就已经很完善了,有报警、任务依赖。代码简单明了,作为java新手的我还是可以看懂的。后面这个项目交给我来开发、维护,就这样我走上来java的路。

java or scala

这3个多月时间一直在写java,没有动过scala,使用下来觉得java更好,虽然有些地方挺冗余的,代码平平无奇,没有scala那样的lambda漫天乱飞,monad随便用。java代码在你几个月之后看还是可以很快熟悉的,而scala却不行,我都有些后怕当初写的scala代码让后面的人怎么维护。 几个月的工作大概摸清了实时计算和离线计算是怎么回事,当然是比较狭隘的理解,仅限于工作中接触到的。

实时计算

实时计算的数据是流动的,一直变化的,你的代码得一直在那里跑着,不断地处理过来的数据,对代码对可靠性要求比较高,大公司的话,代码一般会部署在多个地方,同时跑数据。处理数据的代码最好不要有什么状态在里面,保证幂等性最好。我现在做的实时计算都是以下流程:

消息 -->  redis  --> mysql

代码将消息处理完之后产生的数据放到redis,再通过任务调度系统隔几分钟将数据导入mysql,其他系统再读取mysql的数据,拿到稍有延迟的数据。那为什么不是用spark,storm这些来做实时计算呢?因为用不起,内存开销太大,云服务器花费会一下子上去。

离线计算

离线计算都是由mapreduce来完成的,生成的数据会通过sqoop这个工具导入到mysql。

离线计算有这样几种情况:

  1. 数据需要重算
  2. 实时计算到话太耗费cpu和内存
  3. 以小时或天为单位的报告

离线计算因为数据量很大,有时候会内存不够,当然设置map和reduce阶段的内存只能缓解一下。我曾经碰到过一个这样的问题。在reduce阶段的时候将数据都写入了一个map,在cleanup的时候才将数据写入磁盘。很容易确定就是map把内存占光的,后面加大reduce的内存还是不行,最后老大拿出了他的经验,让我把map再map一下,因为一个大map在申请内存的时候,申请的内存和本身的内存一样大,这样即便机器还有内存,但当达不到申请的数量的时候就会报这个错,嵌套map的话就可以避免大内存大申请,增加的代码量也不是很多。

曾经在mapreduce里写过一段很华丽的代码,使用了一些设计模式,每次调用都会new很多数据,很容易造成内存不足,因为事先不能确定数据的大小来分配内存。最后还是把这段代码砍掉了。平平凡凡才是真。

有时候一个mapreduce不能把整个工作做完就需要分割一下,分成多个mapreduce来跑。

统计指标

  1. 可累加的:pv,cli等
  2. 记个数的:uv,ip。还可以把ip先hash成几块,然后分别统计每块的ip数,在将每块的ip数加起来。

数据倾斜

这种情况暂时还没碰到过,在一个技术群里有人提到过这样一个问题。比较明显的特征就是多台机器跑的时候每次只有一台机器出问题,其他都没事。解决方法就是重点关照往机器灌数据的代码了,自己没什么经验就不多说了。