大数据平台私有化部署资源优化(省钱)方案

268 阅读8分钟

前言

写在最前面的话,土豪以及数据中心提供统一服务的朋友基本可以无视,看看热闹就好,毕竟能用钱解决的问题都不是问题

需求来源

由于各种原因,包含但不限于信息安全,方便管理,数据重用等原因,相当一部分的大数据业务产品需要进行本地化或者私有化部署,此时除了技术开销(产品成本)外,硬件开销也会成为一个头等大事,成为很多项目的重要考虑因素,所以在功能以及性能表现差不多的情况下,硬件成本更低成为产品竞争力的一个重要因素

拆分成专业术语,上述需求其实就是内存,硬盘,CPU以及带宽资源的降低与优化,在当前大数据平台性能严重依赖内存的时代(尤其是非计算密集型或者没有机器学习或者深度学习的前提下),内存资源几乎是无法削减的,除非以牺牲性能为代价,所以优化的重点将从CPU.硬盘以及带宽上下手,如果内存有富余,尽量用内存去置换其他资源,从而达到性能最大化

设计方案

平台现状

公司内部是elasticsearch,hbase以及redis的重度使用者,考虑到抓大放小,立竿见影的目标,而redis几乎只靠内存,所以硬盘以及CPU的优化目标就只有拿elasticsearch和hbase开刀了,带宽毫无疑问只能拿传输的消息开刀了,下面就从CPU,硬盘以及带宽来进行分开描述。

具体实现

CPU

提高CPU资源使用率

对于绝大多数非计算密集型的大数据平台来说,CPU在标配的服务器上一般都是富余资源,所以可以考虑使用CPU资源去置换其他资源,提高CPU使用率。

具体方案如下

  • CPU置换硬盘资源:对存储的数据进行Compression和Encoder,正巧elasticsearch和hbase(几乎所有的数据库)都支持,那就搞起吧,具体的实施原则下面介绍,这里先提一嘴
  • CPU置换带宽资源:对传输的数据选取高性能的Serialize和DeSerialize,也有助于降低带宽资源,同样下面具体介绍

减少CPU空闲量

兼顾CPU密集型应用和非CPU密集型应用的混合使用,使CPU资源充分利用,较少空闲量 针对部分场景下,如Hadoop主节点或者HBase的主节点,如果没用来存储数据,则节点负载理论上不会太高,在保证组件稳定性的前提下可以在该节点上部署部分应用来充分利用CPU以及其他资源

硬盘

数据库数据滚动存储

大数据的特点就是数据量大,但是单位数据的价值比较低,在正常的业务条件下,可以保持一定时间内的明细数据,如半年或者一年,其余的数据在经过统计分析后可以进行转储或者直接删除,毕竟很多情况下,我们不会关心几年前发生的一条明细数据的情况。

针对这种场景,hbase以及elasticsearch中的数据可以设计滚动存储,只保留最近一段时间内的数据。elasticsearch可以通过curator或者定时任务来进行数据清理;hbase可以通过ttl或者定时任务来清理数据

使用压缩以及编码策略

压缩以及编码策略是数据库节省硬盘资源的常规操作,有的默认开启了,有的未开启,有的可以优化。针对hbase以及elasticsearch有如下方案:

  • Elasticsearch使用best_compression压缩,默认情况下Elasticsearch使用的是lz4压缩,理想情况下,使用best_compression能节省大概15%-25%的存储,但是由于压缩只作用于source字段,所以如果禁用了source字段或者Field的索引量比较大,则压缩效果会大打折扣,具体以实际测试数据为准
  • 对于HBase,可以使用compression和encoder,具体参见我之前的文章# HBase数据压缩的这几种玩法你都知道吗?

优化存储结构

对于Elasticsearch来说,可以开箱即用,不建立索引也可以通过数据分析来创建索引和存储数据;对于HBase来说,由于是无shema的结构(表的配置只到列族一级),所以可以随便扩展列。这些功能再给我们带来很大便利,降低使用成本的前提下,也带来了巨大开销的代价,所以自定义存储方案,优化存储结构成为提高性能,降低硬件开销的一个重大突破口。

具体操作如下:

  • Elasticsearch对不必要的特性进行禁用,这个内容比较多,大家可以自行在网上学习,如果需要的话,我找个时间再整理一篇文档,举两个例子来说明:对于一个String类型的字段,如果不需要分词,则将field类型设置为keyword代替text;对于int型的值,如果不需要进行大小比对,仅仅是精确查询,则将field类型设置为keyword代替number类型。总而言之,禁用一切不需要的属性和索引,详细可以参考我之前的文章# 磨刀不误砍柴工-elasticsearch的schema详解
  • 在不影响查询的前提下,减少HBase列的个数,对关联性较大的字段进行统一存储,因为对于hbase来说,底层都是存储cell的,每多一列,rowkey,columnFamily,timestamp等都需要冗余存储一份,所以对于关联性较大的列建议统一存储到一列,用json,二进制对象或者protocolbuffer进行处理

带宽

带宽资源相比上面服务器资源的一次性投入,是一个持续投入的资源,对于某些数据量较大,数据敏感需要使用专线的场景,带宽费用一年动辄几十万甚至上百万,确实很吓人,哪怕在当今带宽费用已经大幅削减的前提下,费用也是不菲的。

所以针对上述情况,设计下面的两套方案进行带宽资源的削减:

使用码表转换减小消息体

  • 对于消息中重复率较高,字段体较大的部分,可以使用码表进行编码转换的方式进行传输,传输过程中使用转换了的编码,在server端和client端存放解码字典进行解码。
  • 对于部分固定类型的字段,如ip,date,time,位置信息等字段,可以转换成int或者其他更小的消息体来进行传输,在两端进行编解码。

选用高效的序列化和反序列化算法

序列化和反序列化对于网络传输来说是必需的,但是序列化和反序列化的算法确实可以优化的,笔者绝大部分使用的java,所以默认的序列化和反序列算法是java自带的defaultXXX的序列化和反序列算法,这个算法不需要额外实现或者处理就可以使用,但是缺点是性能和效果是真心的差,建议使用高效的序列化和反序列算法。

在这里笔者建议使用kyro或者protocol Buffer,大体介绍下两者的优缺点和应用场景:

  • kyro很快,压缩比很高,spark默认就是用kyro进行序列化和反序列化,但是缺点就是不兼容变化,如果元数据发生增量变化,则kyro无法进行解析,所以针对实体固定,几乎不会发生变化的场景,kyro是个很好的选择
  • protocol Buffer是google出品,所以对性能不需要有任何担心,而且可以做到兼容增量变化,但是缺点是需要手动维护一个元数据的proto文件,序列化和反序列化需要依赖该proto文件生成的实体文件,所以针对实体不固定,需要增量更新的场景,protocol Buffer是个很好地选择

具体的技术选型请大家自行学习。

结语

降低硬件和带宽资源就和系统性能优化一样,总是永无止境的。所谓性能优化一时爽,一直优化一直爽,所以大家可以根据自己的实际需求进行选取,达到一个点即可。凡事都讲投入产出比,性能优化亦是如此。

文章到这里就结束了,最后路漫漫其修远兮,大数据之路还很漫长。如果想一起大数据的小伙伴,欢迎点赞转发加关注,下次学习不迷路,我们在大数据的路上共同前进!