大数据服务规划
我个人做实验分配了5台虚拟机,每台20G内存,150G存储,应该可以玩会了。
业务集群规划
一般而言,一个集群上很少只跑一个业务,大多数情况都是多个业务共享集群,实际上就是共享系统软硬件资源。这里通常涉及两大问题,其一是业务之间资源隔离问题,就是将各个业务在逻辑上隔离开来,互相不受影响,这个问题产生于业务共享场景下一旦某一业务一段时间内流量猛增必然会因为过度消耗系统资源而影响其他业务;其二就是共享情况下如何使得系统资源利用率最高,理想情况下当然希望集群中所有软硬件资源都得到最大程度利用。
此次针对是后者进行阐述:使得集群系统资源最大化利用,那首先要看业务对系统资源的需求情况。经过对线上业务的梳理,通常可将这些业务分为如下几类:
- 硬盘容量敏感型业务:这类业务对读写延迟以及吞吐量都没有很大的要求,唯一的需要就是硬盘容量。比如大多数离线读写分析业务,上层应用一般每隔一段时间批量写入大量数据,然后读取也是定期批量读取大量数据。特点:离线写、离线读,需求硬盘容量
- 带宽敏感型业务:这类业务大多数写入吞吐量很大,但对读取吞吐量没有什么要求。比如日志实时存储业务,上层应用通过kafka将海量日志实时传输过来,要求能够实时写入,而读取场景一般是离线分析或者在上次业务遇到异常的时候对日志进行检索。特点:在线写、离线读,需求带宽
- IO敏感型业务:相比前面两类业务来说,IO敏感型业务一般都是较为核心的业务。这类业务对读写延迟要求较高,尤其对于读取延迟通常在100ms以内,部分业务可能要求更高。比如在线消息存储系统、历史订单系统、实时推荐系统等。特点:在(离)线写、在线读,需求内存、高IOPS介质
- 对于CPU资源,HBase本身就是CPU敏感型系统,主要用于数据块的压缩/解压缩,所有业务都对CPU有共同的需求,而HDFS对CPU要求不高
一个集群想要资源利用率最大化,一个思路就是各个业务之间‘扬长避短’,合理搭配,各取所需。实际上就是上述几种类型的业务能够混合分布,建议不要将同一种类型的业务太多分布在同一个集群。因此一个集群理论上资源利用率比较高效的配置为:硬盘敏感型业务 + 带宽敏感型业务 + IO敏感型业务。
另外,集群业务规划的时候除了考虑资源使用率最大化这个问题之外,还需要考虑实际运维的需求。建议将核心业务和非核心业务分布在同一个集群,强烈建议不要将太多核心业务同时分布在同一个集群。这主要有两方面的考虑:
- 一方面是因为核心业务共享资源必然会产生竞争,一旦出现竞争无论哪个业务出现问题都不是我们愿意看到的;
- 另一方面在特殊场景下方便运维童鞋进行降级处理,比如类似于淘宝双十一这类大促活动,某个核心业务预期会有很大的流量涌入,为了保证核心业务的平稳,在资源共享的情况下只能牺牲其他非核心业务,在和非核心业务方充分交流沟通的基础上限制这些业务的资源使用,在流量极限的时候甚至可以直接停掉这些非核心业务。试想,如果是很多核心业务共享集群的话,哪个核心业务愿意轻易让路?
例子:
那有些同学针对HBase就说了:如果按照你这样设计,那岂不是会产生很多小集群。的确,这种设计会产生很多小集群,相信如果没有资源隔离的话,小集群是没法避免的。有些使用'rsgroup'进行业务资源隔离的集群会做的很大,大集群通过隔离会将业务独立分布到很多独立的RS上,这样实际上就产生了很多逻辑上的小集群,那么,这些小集群同样适用上面提出的规划思路。
真实集群规划
Yarn
resource manager:1g-2g
node manager:根据实际情况调整,内存和cpu数量
container:可使用的最大内存大小、初始化内存大小(默认为2G)
jobHistory server:500M-1G
Zookeeper
对于zookeeper来说,如果在运行过程中,需要和其它应用程序来竞争磁盘、CPU、网络、内存资源,那么整体性能将会大打折扣。我们在使用zookeeper初期尝试将zookeeper与其他应用公用机器,在系统流量上涨后,由于IO及CPU被其他应用使用很大,造成zookeeper的session经常超时甚至应用与zookeeper的连接断开。因此,建议zookeeper与其他应用分开部署。如果内存设置太大,会让内存与磁盘进行交换,这将使ZK的性能大打折扣。例如一个4G内存的机器,如果你把JVM的堆大小设置为4G或更大,那么会使频繁发生内存与磁盘空间的交换,通常设置成3G就可以了。
对Zookeeper要求不高的情况下,500M-1G均可。
Kafka、Flume
数量1万条/s情况下,1G内存足够用。一天数据量100006460*24=9 2160 0000
Hive、Hue、Oozie
500M-1G
Kudu、Impala
内存越大越好
ClouderaManager
Server:内存最小2G,cpu0.5核
Agent:内存最多1G,cpu几乎不消耗
Event Server:50M
Host Monitor:500M
Service Monitor:500M
Alert Publisher:50M
HDFS
从架构设计上看,元数据大致分成两个层次:
Namespace管理层:负责管理文件系统中的树状目录结构以及文件与数据块的映射关系。
块管理层:负责管理文件系统中文件的物理块与实际存储位置的映射关系BlocksMap。
Namespace管理的元数据除内存常驻外,也会周期Flush到持久化设备上FsImage文件;
BlocksMap元数据只在内存中存在;当NameNode发生重启,首先从持久化设备中(磁盘)读取FsImage构建Namespace,之后根据DataNode的汇报信息重新构造BlocksMap。
这两部分数据结构是占据了NameNode大部分JVM Heap空间。
补充:
NetworkTopology:维护机架拓扑及DataNode信息,机架感知的基础。
集群中包括2000个DataNode节点,假设HDFS目录和文件数总量为1亿(140M),Block总量在1亿(160M)情况下,NN JVM为72G,内存使用情况:
NetworkTopology
NameNode维护数据结构信息需要占用的内存总量:
(64 + 114 + 56 + 109 * 16) * 2000 = ~4MB
NameNode维护拓扑结构中内部节点信息需要占用的内存总量:
(44 + 48) * 80 + 8 * 2000 = ~25KB
Namespace
(24 + 96 + 44 + 48) * 70M(dir)+ 8 * 140M(all)+ (24 + 96 + 48) * 70M(file) + 8 * 160M = ~27GB
BlocksMap
16 + 24 + 2% * 72GB +( 40 + 128 ) * 160M = ~26GB
二者组合结果53GB,结果与监控数据显示常驻内存52GB基本相同,符合实际情况。
NN的内存
50个以下的小集群,NN内存1G足以,DN也是1G。
HBase
CPU
CPU资源:HBase是一个CPU敏感型业务,无论数据写入读取,都会因为大量的压缩解压操作,特别耗费计算资源。因此对于HBase来说,CPU越多越好。
Region
官方文档给出的一个推荐范围region个数在20~200之间,而单个Region大小控制在10G~30G。
大量小Region
优点:
-
更加有利于集群之间负载分布
-
有利于高效平稳的Compaction,这是因为小Region中HFile相对较小,Compaction代价小
缺点:
- 最直接的影响:在某台RegionServer异常宕机或者重启的情况下大量小Region重分配以及迁移是一个很耗时的操作,一般一个Region迁移需要1.5s~2.5s左右,Region个数越多,迁移时间越长。直接导致failover时间很长。
- 大量小Region有可能会产生更加频繁的flush,产生很多小文件,进而引起不必要的Compaction。特殊场景下,一旦Region数超过一个阈值,将会导致整个RegionServer级别的flush,严重阻塞用户读写。
- RegionServer管理维护开销很大
少量大region
优点:
- 有利于RegionServer的快速重启以及宕机恢复
- 可以减少总的RCP数量
- 有利于产生更少的、更大的flush
缺点:
- Compaction效果很差,会引起较大的数据写入抖动,稳定性较差
- 不利于集群之间负载均衡
然而,HBase并不能直接配置一台RegionServer上的Region数,Region数最直接取决于RegionSize的大小配置hbase.hregion.max.filesize,HBase认为,一旦某个Region的大小大于配置值,就会进行分裂。
hbase.hregion.max.filesize默认为10G,如果一台RegionServer预期运行100个Region,那单台RegionServer上数据量预估值就为:10G * 100 * 3 = 3T。反过来想,如果一台RegionServer上想存储12T数据量,那按照单Region为10G计算,就会分裂出400个Region,很显然不合理。
此时就需要调整参数hbase.hregion.max.filesize,将此值适度调大,调整为20G或者30G。而实际上当下单台物理机所能配置的硬盘越来越大,比如36T已经很普遍,如果想把所有容量都用来存储数据,依然假设一台RegionServer上分布100个Region,那么每个Region的大小将会达到可怕的120G,一旦执行Compaction将会是一个灾难。
可见,对于当下的HBase,如果想让HBase工作的更加平稳(Region个数控制在20~200之间,单Region大小控制在10G~30G之间),最多可以存储的数据量差不多为200 * 30G * 3= 18T。如果存储的数据量超过18T,必然会引起或多或少的性能问题。所以说,从Region规模这个角度讲,当前单台RegionServer能够合理利用起来的硬盘容量上限基本为18T。
然而随着硬件成本的不断下降,单台RegionServer可以轻松配置40T+的硬盘容量,如果按照上述说法,越来越多的硬盘其实只是'镜中月,水中花'。社区也意识到了这样的问题,在当前Region的概念下提出了Sub-Region的概念,可以简单理解为将当前的Region切分为很多逻辑上小的Sub-Region。Region还是以前的Region,只是所有之前以Region为单位进行的Compaction将会以更小的Sub-Region粒度执行。这样,单Region就可以配置的很大,比如50G、100G,此时单台RegionServer上也就可以存储更多的数据。个人认为Sub-Region功能将会是HBase开发的一个重点。
网卡
因为HBase在大量scan以及高吞吐量写入的时候特别耗费网络带宽资源,强烈建议HBase集群部署在万兆交换机机房,单台机器最好也是万兆网卡+bond。如果特殊情况交换机是千兆网卡,一定要保证所有的RegionServer机器部署在同一个交换机下,跨交换机会导致写入延迟很大,严重影响业务写入性能。
磁盘与内存的对应
公式,从region的角度进行推导计算:
Disk Size / Java Heap = RegionSize / (MemstoreSize * ReplicationFactor * HeapFractionForMemstore )
公式由来
硬盘容量纬度下Region个数:Disk Size / (RegionSize *ReplicationFactor)
Java Heap纬度下Region个数:Java Heap * HeapFractionForMemstore / MemstoreSize
参数配置
对应HBase/HDFS配置参数:
hbase.hregion.max.filesize/(hbase.hregion.memstore.flush.size *dfs.replication * hbase.regionserver.global.memstore.lowerLimit)
示例
● 10GB regions
● 128M memstores
● HDFS replication factor of 3
● RegionServer中所有MemStore存在JVM内存中的比例上限 0.4
得到10GB/128MB30.4 = 1010241024/(128*1024) * 3 * 0.4 = 96bytes(1bytes的内存需要96bytes中硬盘空间),通常内存32G,cpu为8核,就可满足每日数据量5000万。
但是在实际情况下,内存的大小和磁盘的大小是不匹配的,所以我们需要根据实际情况进行调整,多余的内存资源分配给HBase读缓存BlockCache,这样就可以保证Java Heap并没有实际浪费。