• HBase优化


    一.表设计 

      1.预分区【Pre-Creating Regions】

        默认情况下,在创建HBase表的时候会自动创建一个region分区,当写入数据时,所有的HBase客户端都向这一个region写数据,直到这个region足够大时才进行切分。因此,为了提高批量写入的效率可以预先创建好多个分区【这个要和rowkey的设计紧密关联】,这样当数据写入HBase时会按照region分区的情况,不同rowkey类型的数据写入对应的分区中,写入数据的速度会大大提高,同时也做到了数据的负载均衡。

      2.Row Key【行键】

        HBase中的rowkey用来检索表中的记录,支持一下三种方式:

        1.通过单个rowkey访问,即按照某个rowkey键值进行get操作。

        2.通过rowkey的range进行scan,即通过设置startRowKey和endRowKey在这个范围内进行扫描。

        3.全表扫描,及直接扫描整张表中所有行记录。

        备注:

          1.在HBase中rowkey可以是任意字符串,最大长度64KB,实际应用中一般为10~100bytes,存为byte[]字节数组,一般设计成定长的。

          2.rowkey是按照字典顺序存储,因此,可以在设计rowkey时充分利用这一点,将经常一起读取的数据存储到一块,将最近可能被访问的数据放在一块。

      3.Column Family【列簇】

        不要在一张表里定义太多的column family。目前HBase并不能很好的处理超过2~3个column family的表。因为某个column family在flush的时候,它邻近的column family因关联效应被触发flush,最终导致系统产生更多的I/O。

      4.In Memory

        创建表时,可以通过HColumnDescriptor.setInMemory(true)将表放到RegionServer缓存中,保证在读取的时候被cache命中。

      5.Max Version

        创建表时,可以通过HColumnDescriptor.setMaxVersions(int maxVersions)设置数据的最大最大版本。

      6.Time To Live

        创建表时,可以通过HColumnDescriptor.setTimeToLive(int timeToLive)设置表中数据的生命周期,过期数据将自动被删除,例如如果只需要存储最近一天的数据,那么可以设置为HColumnDescriptor.setTimeToLive(1 * 24 * 60 * 60)。

      7.Compact & Split

        在HBase中,数据在更新时首先写入WAL(HLog)和内存(MemStore)中,MemStore数据是排序的,当MemStore累计到一定阈值时,就会创建一个新的MemSotee,并且将老的MemStore添加到flush队列,由单独的线程flush到磁盘上,成为一个StoreFile。与此同时系统会在zookeeper中记录一个redo point,表示这个时刻之前的变更已经持久化了(minor compact)。StoreFile是只读的,一旦创建后就不能再修改,因此HBase的更新其实是不断追加的过程,若一个Store中的StoreFile达到一定的阈值后,就会进行一次合并(major compact),将对同一个Key的修改合并到一起,形成一个大的StoreFile,当StoreFile的大小达到一定阈值时又会对StoreFile进行切分(split),等分成两个SotreFile。由于对表的更新是不断追加的,处理读请求时,需要访问Store中全部的StoreFile和MemStore,将它们按照row key进行合并,由于StoreFile和MemSrore都是进行过排序的,并且StoreFile带有内存索引,通常合并过程是比较快的。实际应用中,可以考虑必要时手动进行major compact,将同一个row key的修改进行合并形成一个大的StoreFile。同时可以将SoreFile设置大些,减少split的发生。

    二.写表  

      1.创建多个HTable客户端写数据,提高写数据的吞吐量

        Configuration conf = HBaseConfiguration.create();
        List<HTable> list = new ArrayList<HTable>();    

        for(int i = 0; i<10; i++){
          list.add(new HTable(conf, table_name));
        }
      2.批量写

        调用HTable.put(List<Put>)
      3.多线程并发写

        在客户端开启多个HTable写线程,每个写线程负责一个HTable对象的flush操作,这样结合定时flush和写buffer(writeBufferSize),可以既保证在数据量少的时候数据可以在较短时间内被flush,同时又保证在数据量大的时候写buffer一满就及时进行flush。
      4.参数优化
        4.1.Auto Flush

          通过调用HTable.setAutoFlush(false)方法可以将HTable写客户端的自动flush关闭,这样可以批量写数据到HBase,而不是一条数据执行一次更新,只用当put写满客户端缓存时才实际向HBase服务端发起写请求,默认情况下auto flush是开启的。
        4.2.Write Buffer

          通过调用HTable.setWriteBufferSize(wirteBufferSize)方法可以设置HTable客户端的写buffer大小,如果新设置的buffer小于当前写buffer中的数据大小时,buffer将会被flush到服务器端。其中,writeBufferSize的单位是byte字节数,可以根据实际写入数据量的多少来设置该值。
        4.3.WAL Flag

          在HBase中,客户端向集群中的RegionServer提交数据时(Put/Delete),首先会写WAL(即HLog,一个RegionServer上所有Region共享一个HLog),只有当WAL写成功后,再接着写MemStore,然后客户端被通知提交数据成功。如果写WAL失败,客户端则会被通知提交失败,这样做的好处是可以做到RegionServer宕机后数据恢复。

    三.读表  

      1.多HTable并发读

        同上,与多HTable并发写类似

      2.参数优化

        2.1Scanner Caching

          hbase.client.scanner.caching配置项可以设置HBase Scanner一次从服务端抓取的数据条数,默认一次返回一条数据。通过将其设置成一个合理的值,可以减少scan过程中next()的时间开销,代价是scanner需要通过客户端的内存来维持这些被cache的数据。

          有三个地方可以进行配置:

          1.HBase的conf配置文件

          2.HTable.setScannerCaching(int scannerCaching) 【最优选择】

          3.Scan.setCaching(int caching)    

        2.2 Scan Attribute Selection
          scan时指定需要的Column Family,这样可以减少网络传输时的数据量,否则默认scan操作返回整行数据。
        2.3 Close ResultScanner
          通过scan去完数据后,记得要关闭ResultScanner,否则RegionServer可能会出现问题(对应server资源无法释放)。
      3.批量读

        HTable.get(List<Get>)

      4.多线程并发读

        同上
      5.缓存查询结果

        对于频繁查询HBase的应用场景,可以考虑在应用程序中做缓存。当有新的查询请求时,首先在缓存中查找,如果存在则直接返回,不在查询HBase,否则对HBase发起读请求。

      6.Blockcache

        HBase上Regionserver的内存分为两部分:Memstore【主要用来写数据】,BlockCache【主要用来读数据】。写请求会先写入Memstore,Regionserver会给每个region提供一个Memstore,当Memstore满64M时,会启动flush刷新到磁盘。读请求会先到Memstore中查数据,查不到就导BlockCache中查,再查不到就会到磁盘上读取数据,并把结果写入BlockCache中。
      7.使用HTablePool

        try{
          Configuration conf = HBaseConfiguration.create();

          Connection connection = ConnectionFactory.createConnection(conf);
          Table table = connection.getTable(TableName.valueOf(Tablename));
        }cache(Exception e){
          e.printSchema();
        }

  • 相关阅读:
    高考词根树 高考词汇3071
    浏览器的文件访问 API 入门(英文) 资料
    translate speaker 翻译朗读者API vscode 插件推荐 单词发音
    .bat 批处理 手册 教程
    阿里巴巴20220422笔试编程题
    leetcode 587 安装栅栏
    记录一些面试题
    Java编辑提示错误: 编码 GBK 的不可映射字符 (0x80)
    Struct和Class区别?
    Swift String 与 NSString
  • 原文地址:https://www.cnblogs.com/yszd/p/11044025.html
Copyright © 2020-2023  润新知