战争从来都是拼后勤拼平台支撑的,天猫双十一这一天对于我们搜索事业部来说,就是一场高强度的数字化战争。为了这一天,各兄弟业务线的战友们已经摩拳擦掌,纷纷亮出各种新式武器,而我们原有的离线系统平台却渐渐显出疲态,慢慢被来自各业务线的不断提升的
战争从来都是拼后勤拼平台支撑的,天猫双十一这一天对于我们搜索事业部来说,就是一场高强度的数字化战争。为了这一天,各兄弟业务线的战友们已经摩拳擦掌,纷纷亮出各种新式武器,而我们原有的离线系统平台却渐渐显出疲态,慢慢被来自各业务线的不断提升的压力需求搞得捉襟见肘了。个性化搜索实时数据处理平台(Pora)在双十一将正式亮相,当时我们预计会有数以十亿计的新增HBase读写请求,如果不进行升级优化,原有的离线集群预计将无法承受这一前所未有的压力;天猫业务线的增量在双十一更是重中之重,届时预计会有数倍甚至十多倍的增长,不断流,不延迟对于原有的离线集群来说也是巨大的考验;主搜、国际站等业务线也都对底层平台提出了越来越高的要求,凌晨全量的时间极其有限,不能出现任何闪失。如何有效应对以上这些复杂且艰巨的挑战就成为我们离线系统团队最紧迫最核心的课题。HBase-0.98版本就是我们就对挑战的新型“核动力航母”,在这个平台上,我们有效地支撑各相关业务的发展,最终有惊无险地度过了双十一,顺利通过了考验。
Hadoop/HBase技术被引入阿里的搜索体系是在2010年夏天,初始版本号是hadoop-0.20.2和hbase-0.20.5。当时的导购搜索项目急需寻找一种高可靠高性能的分布式存储系统,用于存储导购相关的网页、价格和图片等信息,同时需要进行大量的随机读写和批量扫描、数据挖掘等工作。2011年,我们的HBase升级到0.90版本;2012年初,HBase再次升级至0.92版本;再后来,2013年初,主搜和Etao的离线集群都进入了Hadoop-2.0和HBase-0.94时代。从那以后,我们有一年半的时间没有对集群进行过大的版本升级,直到2014年8月初,etao离线集群率先升级至HBase-0.98版本,紧接着,主搜cm8集群也在10月初步入HBase-0.98时代。计算模型方面,我们基于hadoop全新的YARN框架开发出了iStream实时流计算模型,从而形成了全量、增量加实时的分布式计算+存储一体化的解决方案。在主搜cm8集群中,全量、增量及实时计算的资源(CPU和内存)占比分别是50%,13%和37%;而Etao离线集群三项的占比分别是39%,3%和58%。集群的机器数量也从2010年最初的单一集群40台节点,一步一步进化到现在,形成了一个主搜cm8近700台,etao近500台,整体上近1200台节点的搜索离线集群。
HBase-0.98版本的前期技术调研始于2014年初,当时的调研结果是非常令人满意的,以下几个大的变化让我们充满期待:
除了技术调研和基本的性能评测以外,我们还要将自己在HBase-0.94中增加的各种patch移植到新版本中去,例如:
另外,我们还发现了社区版本中的一些小bug,及时地提交patch并被接受。
HBase-0.98版本的前景很令人期待,但升级的过程还是比较坎坷的。Etao离线集群作为主搜cm8集群的backup集群,首先来承担了HBase-0.98的升级演练及功能、性能验证工作。这个过程我们踩了不少的“坑”,例如:我们的集群中使用了Phoenix项目(集群资源统计系统HStats以及新版的HistoryServer都依赖于它),相关的一些表中就使用了Phoenix定制的Coprocessor,而这些Coprocessor在HBase升级时,会保留一些旧版本的java package类名,这些类却不在新版本phoenix的jar中,导致hbase启动后加载这些带有phoenix定制coprocessor的表时出现失败,集群无法启动。最终我们是通过改hbase源代码加逻辑绕过这些表才恢复的。接下来,由于升级前后那段时间,公司对生产网机器都增加采用了长域名访问机制(以”tbsite.net”结尾),而之前我们集群中各种相关配置都是短域名,造成了HBase集群运维过程中的一些不一致现象,后来我们是通过统一采用长域名来解决的。还有一点,为了给集群版本升级降低压力,我们在升级前24小时(具体时间是根据集群实际规模及数据量来确定的),对HBase集群所有的表进行一次major_compaction,最大限度地减少体积,从而间接减少HBase启、停时间;另外,升级前24小时也要通知业务方清理HDFS上面的所有无用目录及文件,为hdfs减轻启、停压力。
在etao离线集群升级HBase-0.98完成后,我们立即就开始进行各主要功能点的验证工作,为主搜cm8集群的升级铺平道路。
在经历了一番波折解决了前面的问题后,我们本以为可以高枕无忧了,因此,今年10月初,就急切地把主搜cm8集群也升级到HBase-0.98版本。大大出乎我们的意料的是,升级后的主搜离线集群性能及稳定性居然还不如升级之前!双十一日益临近,没有回头路的我们开始了新一轮的调优和改进。
关于cm8集群的稳定性问题,其实最重要的就是一点:每天上午总会连续挂掉数十台RS。去查它们的HBase日志,基本上都是GC太忙,OutOfMemory挂掉的。但由于都是直接进程消失,没有其他痕迹,导致我们无从查起,只能根据发生的时间来判断应该与上午的某个job的读写有关。幸运地是,我们在逐台“验尸”时,发现一台机器保留了hprof文件,把当时RS的内存完整保留了下来。经过profiling分析发现,原来是在cm8集群hbase中,有一张odin_stat的统计用的表,它里面中存放了不合理的数据,一次scan操作时,扫出的某单条数据row的size超过1G,另外还有几条size达到数百M的row,导致RS无法短时间内消化掉,最终OOM了。在我们停掉了这张表对应的扫表job后,连续挂RS的情况再也没有出现。后续我们推动业务方改用OpenTSDB这种系统来存储时间序列日志。
主搜cm8离线集群升级后,很多的job跑得比升级前还慢,而且网络打满、IO集中的问题非常明显。刚开始我们都以为是yarn的调度问题是主因,后来一查发现,很多大表的region在集群上分布很不均匀,有些RS上十几个,有些RS上根本就没有。后来查了一下源码才知道原来是0.98把一个bytable的balance参数默认值给改了,0.94时bytable默认是true,也就是按table做均匀,每个table的region在集群上要均匀分布,而到了0.98时,这个参数默认变成了false,而且这个参数并没有出现在配置文件中,只静静地藏在源代码里。我们更新了配置并重新balance了一下,各表region恢复均匀,大部分job的运行时间恢复升级前水平,网络打满及IO压力集中的问题也得到了缓解。之前之所以在etao集群没有发现这个问题,原因是etao集群中有一个占据了集群资源超过80%的大表pagebase,这张表由于历史原因并不是presharding的,导致在集群的分布就不是很均衡,出现网络打满和IO压力大的情况也相对较常见,是它把balance不均的问题给掩盖了;而主搜cm8集群的表基本上都是presharding的,一旦region分布不均就会非常明显。
主搜及b2b业务线中大量使用bulkload来导入数据,针对这些操作,我们进行了多个细节的优化:一方面,降低bulkload生成的HFile文件个数,让每个Family每次只增加一个HFile,这样就减少了bulkload之后立即触发的compaction的次数,降低了磁盘IO和网络压力;之后,增加了bulkload前的压缩和encoding,使HFile尽量小一些,同样是为了降低网络和IO压力;最后,我们在bulkload前生成HFile的阶段增加了逻辑,让它能按照Region的locality状态来写HFile,这样就能使bulkload的文件直接就放到region本地,使接下来的扫表job能够更高效地运行。
为了应对Pora的高压写操作,我们让业务方把相关的istream进程配置上了autoFlush=false的参数,也就是批量异步写HTable,最多延迟1秒,用时间换吞吐率。运行一段时间后发现集群中很多机器出现线程数过高导致进程强制退出的情况。通过ganglia看到线程的增长的主要贡献者就是pora,jstack了一下相关进程发现,多出来的线程都来自于autoFlush时使用的异步写线程。在etao离线集群稳定使用了两年多的autoFlush功能为什么会出现线程泄漏的问题呢?原来是HTablePool搞的鬼。Pora中普遍使用hbase源码中的HTablePool来获取HTable对象,这个结构本身并不保证HTable结束后会close掉,有些情况下会直接丢弃不close,而我们的autoFlush的异步写线程只有在HTable的close阶段才会关闭的,因此才导致的线程泄漏。HBase-0.98本身其实也有解决方案,就是使用HConnection来替换HTablePool,那里的线程池是安全可靠的。Pora团队已经将此项优化列入日程,预计双十二之后上线。
由于历史原因,主搜cm8集群的很多HTable的参数都是有问题的,这次优化也对其进行了调整。有一部分表的MAX_FILESIZE参数设置得过小,导致HTable在偶尔会意外分裂,从而影响上层应用访问时的均匀和稳定;DATA_BLOCK_ENCODING配置成DIFF能节约一些空间,从而间接减少网络和IO的消耗;COMPRESSION方面,SNAPPY相对于主搜常用的LZO来说,压缩率差不多,但会省cpu,速度还稍快一点点;对于数据可靠性要求并不是特别高的HTable来说,可以把写WAL的方式改为异步的,从而提升了写性能,降低磁盘IO压力。另外,很多b2b的流程中常常需要重建hbase表,以前是直接在代码配置中去完成表参数的构建,现在推荐他们使用类似hbase shell中的truncate_preserve的方式来重建,这样就使业务方应用与HTable具体结构参数彻底脱离依赖关系,既方便集群运维管理,也简化了应用的逻辑。
上述优化改进完成后,通过Ganglia各项监控指标对比,主搜离线集群整体开始超越升级前水平,稳定性也优于之前版本。
从集群角度看:
从应用角度看:
“核动力航母”已经起航,技术发展永无止境,我们接下来还有更多的事情要去做……
原文地址:从未降级的搜索技术 – HBase集群升级与优化, 感谢原作者分享。