深圳乐安居网站谁做的,舟山网站建设推荐,wordpress全文搜索,网站描述怎么写比较好作者#xff1a;来自 vivo 互联网服务器团队-Leng Jianyu、Huang Haitao HBase是一款开源高可靠性、扩展性、高性能和灵活性的分布式非关系型数据库#xff0c;本文围绕数据库选型以及使用HBase的痛点展开#xff0c;从四个方面对HBase的使用进行优化#xff0c;取得了一些… 作者来自 vivo 互联网服务器团队-Leng Jianyu、Huang Haitao HBase是一款开源高可靠性、扩展性、高性能和灵活性的分布式非关系型数据库本文围绕数据库选型以及使用HBase的痛点展开从四个方面对HBase的使用进行优化取得了一些不错效果。
一、业务简介
统一内容平台主要承担vivo内容生态的内容审核、内容理解、内容智作和内容分发等核心功能通过聚合全网内容建设行业级的业务中台和内容生态为上下游提供优质可靠的一站式服务目前服务的业务方包括视频业务、泛信息流业务等。 作为一个内容中台每天要新增存储大量图文和视频内容来满足分发的需要。与此同时对这些内容加工处理的数据也都需要存储包括基础信息分类标签信息审核信息等等。而且不仅仅是需要存储的数据量级很大对数据的读取和写入操作也非常频繁当前对数据库的读写主要集中在两个方面 核心链路的内容处理包含了大量对内容特征信息的读取和写入操作 对外提供的查询服务会产生很多回源查询数据库的操作。 在经过多年累积后当前存储的数据量越变越大并且可以预见数据量级会不断膨胀下去如何选择一种可靠的存储选型来保证服务稳定性和扩展性成了当前项目架构的重中之重。
二、存在的问题
在选用HBase之前内容平台核心数据的存储以Mongodb为主要存储选型但是在日常的使用中发现存储侧存在如下一些痛点问题 核心数据量大大表有20TB 以上总存储 60TB 以上Mongodb 的存储架构无法满足良好扩展性要求 访问查询流量大需要承载智慧push、泛信息流、视频推荐侧的大回源查询流量保持查询接口高性能 为了维护Mongodb的稳定性需要定期切换 Mongodb 数据库主从节点重做实例需要运维长期投入维护成本高。
所以我们迫切需要寻找一个更适合当前场景的数据库来满足业务请求量和存储大小日益增长的需求并且要求具备高性能、高稳定、可扩展、低维护成本的特性。
三、存储选型
经过一些调研后发现HBase的一些特性能很好地满足当前场景的要求。
1高性能
HBase采用的是Key/Value的列式存储方式对比Mongodb是行式数据库同一个列族的数据存放在一个文件中随着文件的增长会进行分裂分散到其他机器上所以即使随着数据量增大也不会导致读写性能的下降。HBase具备毫秒级的读写性能如果写入数据量大还可以使用bulkload导入数据的方式进行高效入库。
2高扩展性、高容错性
HBase的存储是基于Hadoop的Hadoop实现了一个分布式文件系统HDFSHDFS的副本机制使得其具有高容错性的特点并且HDFS的Federation机制使得其具有高扩展性。基于Hadoop意味着HBase与生俱来的超强扩展性和高容错性。
3强一致性
HBase的数据是强一致性的从CAP理论来看HBase是属于CP的。CAP 定理表明在存在网络分区的情况下一致性和可用性必须二选一。HBase在写入数据时先把操作的记录写入到预写日志中Write-ahead logWAL然后再被加载到Memstore的。就算某个节点机器宕掉了由于WAL的数据是存储在HDFS上的所以数据并不会丢失后续可以通过读取预写日志恢复内容。
4列值支持多版本
HBase的多版本特性可以针对某个列族控制列值的版本数默认是1即每个key保存一个版本同一个rowkey的情况下后面的列值会覆盖前面的列值。可以动态修改列族的版本数每个版本使用时间戳进行标记默认是写入时间作为该版本的时间戳也可以在写入时指定时间戳。
综合以上特性HBase是非常适合当前项目对数据库选型的要求。
四、HBase 优化实践
随着HBase在整个项目中逐步扩大使用也发现了一些使用规范问题以及一些查询的性能问题。比如查询毛刺比较多、夜间Compact期间耗时比较高、流量高峰期的时候少量请求会有延迟。针对这些问题我们从下面四个方面对HBase的使用进行了优化。
4.1 集群升级
刚开始使用HBase的时候我们使用的HBase集群版本是1.2版本的此版本存在诸多弊端如RITRegion-In-Transition问题频发、请求延时突刺、建删表速度慢、meta 表稳定性差、节点故障恢复速度慢等问题。我们在使用过程发现的主要问题是响应时间突刺问题该问题会导致我们实时查询接口在回源时超时较多导致接口的响应时间有突刺被下游业务方熔断影响业务查询。与HBase团队讨论与评估后决定将业务使用的集群升级到HBase 2.4.8 版本。该版本在公司较多的业务场景中已经得到验证可以解决大部分1.2.0版本存在的痛点问题可以大幅提升读写性能有效降低读毛刺单机处理性能的提升可减少20%左右机器成本。
下面是集群升级后的读写平均耗时对比图。可以看到在升级之前平均响应时间经常会有一些突刺最高能达到超过10s升级后几乎不存在这么高的平均响应时间突刺能保持在10ms以下偶尔较高也是几十毫秒级别。 升级前 升级后
4.2 连接池使用和连接预热
HBase Connection 创建对象并不是简单对应一个socket连接需要与Zookeeper以及HMaster、RegionServer都建立连接所以该过程是一个非常耗资源的过程一般只创建一个 Connection 实例其它地方共享该实例。在Connection初始化之后用connection下的getTable方法实现对表格的连接。为了减少与表格连接带来的网络开销我们建立了对不同表格的连接池来管理客户端和服务端的连接。大致流程图如下图所示。
通过建立连接池带来了以下三点优势
1对表和表之间进行了连接资源隔离避免互相影响
2对连接实现了复用减少了创建连接的网络开销
3防止突增的流量带来的影响实现平滑处理流量。
此外图中可以看到在程序启动阶段可以实现对HBase表连接的预热提前建立对表格的连接可以有效避免在程序启动阶段由于大量建立连接导致读写的响应时间变长影响整体性能。
连接池通过使用Apache Commons Pool提供的GenericObjectPool通用对象池来实现GenericObjectPool包含丰富的配置选项能够定期回收空闲对象并且支持对象验证具有强大的线程安全性和可扩展性。然后将不同表格的连接池对象放到本地缓存LoadingCache中LoadingCache底层通过LRU算法实现对最久远且没有使用的数据的淘汰保证没有使用的表格连接能及时释放。通过使用第三方的对象池和本地缓存建立了对HBase表格的连接池并且实现了预加载减少了一些读写HBase的开销降低了读写耗时对于刚启动服务时的读写突刺带来了一些改善。 4.3 按列读取
HBase建表的时候是不需要确定列的因为列是可变的它非常灵活唯一需要确定的就是列族。一张表的很多属性比如过期时间、数据块缓存以及是否压缩等都是定义在列族上而不是定义在表上或者列上这一点做法跟以往的数据库有很大的区别。同一个表里的不同列族可以有完全不同的属性配置但是同一个列族内的所有列都会有相同的属性。一个没有列族的表是没有意义的因为列必须依赖列族而存在所以在HBase中一个列的名称前面总是带着它所属的列族。列族存在使得HBase会把相同列族的列尽量放在同一台机器上不同列族的列分布在不同的机器上。
一般情况下从客户端发起请求读取数据到数据返回大致有如下几步 客户端从ZooKeeper中获取meta表所在regionServer节点信息。 客户端访问meta表所在的regionServer节点获取region所在节点信息。 客户端访问具体region所在regionServer找到对应的region。 首先从blockCache中读取数据存在则返回不存在则去memstore中读取数据存在则返回不存在去storeFileHFile中读取数据存在会先将数据写入到blockCache中然后返回数据不存在则返回空。
简单的示意图如下所示 整个过程中如果读取字段过多或者字段长度过大那么返回所有列的数据会导致大量无效的数据传输进而导致集群网络带宽等系统资源被大量占用必然导致读取性能降低所以需要减少一些不必要字段的查询。
Get类是HBase官方提供的查询类在该类中主要有以下几个方法提供来实现减少字段读取 addFamily添加要取出的列族 addColumn添加要取出的列 setTimeRange设置要取出的版本范围 setMaxVersions设置取出版本数量。
当前项目中没有使用到HBase的版本范围和版本数量的特性但是主要场景使用的表字段都比较多如内容的基本属性能达到上百个字段或者字段的大小都比较大如内容解析的一些向量字段原本在查询时都是直接读取所有字段导致很多字段其实不需要使用也被一直读取浪费性能。通过改用按列读取的方式来实现不同场景下不同字段的查询避免了超过一半无用字段的返回平均响应时间也下降了一些。
4.4 compact优化
HBase是基于LSM树存储模型的分布式NoSQL数据库。LSM树相比于普遍使用在各种数据库的B树来说能够获得较高随机写性能的同时也能保持可靠的随机读性能。在进行读请求的时候LSM树要把多个子树类似B树结构进行归并查询 因此归并查询的子树数越少查询的性能就越高。当MemStore超过阀值的时候就要flush到HDFS上生成一个HFile。因此随着不断写入HFile的数量将会越来越多根据前面所述HFile数量过多会降低读性能。为了避免对读性能的影响可以对这些HFile进行compact操作把多个HFile合并成一个HFile。compact操作需要对HBase的数据进行多次的重新读写因此这个过程会产生大量的IO。可以看到compact操作的本质就是以IO操作换取后续的读性能的提高。 HBase的compact是针对HRegion的HFile文件进行操作的。compact操作分为major和minor两种。major compaction会把所有的HFile都compact为一个HFile并同时忽略标记为delete的KeyValue被删除的KeyValue只有在compact过程中才真正被删除可以想象major compaction会产生大量的IO操作对HBase的读写性能产生影响。minor则只会选择数个HFile文件compact为一个HFileminor的过程一般较快而且IO相对较低。在业务高峰期间都会禁止major操作只在业务空闲的时段定时执行。
hbase.hstore.compaction.throughput.higher.bound是HBase中控制HFile文件合并compaction速度的参数之一。它指定了一个HFile文件每秒最大合并数据大小的上限以字节为单位。如果一个HFile文件的大小超过了这个上限HBase就会尝试将其分裂成较小的文件来加快合并速度。通过调整该参数可以控制HBase在什么条件下开始尝试合并HFile文件。较小的值会导致更频繁的文件合并也会降低HBase的性能。较大的值则可能导致HFile文件的大小增长过快从而影响读取性能。
hbase.hstore.compaction.throughput.lower.bound也是HBase中控制HFile文件合并速度的参数之一。它指定了一个HFile文件每秒最小合并数据大小的下限以字节为单位。当合并速度达到这个下限时HBase会停止合并更小的HFile文件而等待更多的数据到达之后再进行合并操作。与higher.bound参数相比lower.bound参数更加影响文件合并频率和性能。过高的值会导致较少的文件合并和较大的HFile文件这会影响读取性能和写入并发性。反之过低的值会导致过于频繁的文件合并从而占用过多的CPU和磁盘I/O资源影响整个HBase集群的性能。针对Compact对业务耗时的影响我们对Compact 操作进行了限流并且通过多次测试调整Compact上文提到的两个限流的阈值取得了非常好的效果。Compact期间的耗时下降了70%y以上。下图展示了采取限流前后的耗时对比。 4.5 字段级版本管理
除了上述提到的优化点我们也探索了一些HBase的其它特性以备将来用来优化其他方面。上文提到通过对HBase进行按列读取数据可以减少get查询的时间通常意义来讲列也就是每个字段已经是每条数据的最基本单位了但是HBase中的数据粒度比传统数据结构更细一级同一个位置的数据还细分成多个版本一个列上可以存储多个版本的值多个版本的值被存储在多个单元格里面多个版本之间用版本号 version来区分。所以唯一确定一条结果的表达式应该是行键:列族:列:版本号rowkey:column family:column:version。不过版本号通常是可以省略的如果写入时不写版本号每个列或者单元格的值都被赋予一个时间戳这个时间戳默认是由系统制定的当然写入时也可以由用户显式指定具体的版本号。在查询时如果不指定版本号HBase默认获取最后一个版本的数据返回给你。当然也可以指定版本号返回需要的其他版本的数据。简单的示意图如下所示 同时HBase为了避免数据存在过多的版本造成不必要的负担HBase提供了两种数据版本的回收方式一是按照数量维度保存最后的n个版本二是按照时间维度保存最近一段时间的版本数据比如保存一个月。通过多版本同时存储对于一些有时序要求的场景非常友好通过指定版本的时间戳可以避免在已经更新了新数据的情况下被旧数据覆盖。当前我们建表是都是只指定了一个版本使用也都是用的以时间戳为版本号的默认版本没有采取版本管理的措施不同单元格可以记录多版本的特性可以考虑应用于字段更新时记录下多个版本的数据在不影响读写效率的情况下方便后续在没有相关日志的情况下回溯最近几次更新的值并且可以防止误操作或数据损坏因为用户可以恢复到之前的版本数据。此外我们的系统中存在一些通过消息队列异步更新场景此时可以使用消息体中的时间戳作为当前版本号这样可以在多线程消费时也能保证消费的时序性因为低版本的版本号无法更新高版本的版本号。
五、总结
本文在对统一内容平台在数据库选型分析和优化的基础上简要介绍了HBase在实际使用中的一些优化方案经优化后项目整体读取和写入性能都有比较明显的提升较好的保障了统一内容平台业务的稳定性并且大大降低了业务侧的运维成本。Hbase本身就具备强大的功能在大数据领域有独有的优势但是在不同的业务场景对于HBase的要求也是不一样的可以结合具体的实际情况从使用的数据库版本、从HBase底层机制的调参、从客户端调用机制的优化等多方面挖掘探索更适合业务的方式希望本文中提到的一些优化方案能给读者带来一些启发。