zoukankan      html  css  js  c++  java
  • 【转】HBase业务实践

    原文链接 http://rdc.taobao.org/?p=457

    HBase业务实践

    源作者:我们团队最闷骚的武祖哥

    适合读者

    2012年因为业务需求,我们的底层数据库从Mysql迁移到HBase上面,正好也亲身经历了HBase-Client从0.92到0.94变化。我们总结了一些业务上面使用HBase的办法,希望本文能够对业务上面刚刚使用HBase的人一些帮助,降低入门门槛。

    准备工作

    • HBase Toturial,需要对HBase有一定的了解
    • Mysql 基础,需要对Mysql有一定的了解
    • Java 基础,需要对Java有一点的了解

    为什么需要HBase

    优势:

    • 再见了,分库分表。再见了,TDDL
    • 更高性能的读和写。

    不足:

    • 没有SQL
    • 没有iBtatis、Hibernate这些ORM工具,HBase的ORM目前还不成熟
    • HBase的RowKey的设计要求比较高
    • 需要自己构建索引表

    HBase的使用

    构建单例的HBaseFactory

    构建单例的HBaseFactory,我们只需要关心三个事情

    • hbase.zookeeper.quorum
    • zookeeper.znode.parent
    • HTablePool的maxSize

    我们使用的是HTablePool构建一个HBaseFactory对象

    *为什么使用HTablePool

    HTablePool您可以看成JDBC的连接池,适合多线程使用环境,如果需要把连接“还”给连接池的话,只需要调用HTableInterface#close() 就可以了

    HBaseFactory的Interface
    HBaseFactory的Implemention
    Usage

    Scan

    1. StartRow&Cache如果不设置StartRow,那就会从头开始搜索,这样做的话速度就会很慢 Cache能够保证一次搜索拿到内存的数据,否则您iterator一次就得走一次网络
    2. 关于FilterPrefixFilter是最常用的filter,有个非常需要注意的点 如果Rowkey是”123_1_00000“这样的,如果prefix是123_1,切记切记要记得写成123_1_

      其次要注意filter不要太多,最好不要超过2个

    3. 关于分页在Mysql里面,常常需要用到分页,那么在HBase里面你该如何实现,使用PageFilter配合startRow,但是在Mysql里面常常会有一个总数的概念,切记切记HBase里面不要做类似Count的操作
    4. 关于分布式流式处理比方说,现在有10台机器,需要同时处理1000万的数据,那么这个时候,我们就可以用到checkAndPut。就像Mysql里面的一个乐观锁一样。

    具体的做法是:

    • 我们通过PageFilterSingleColumnValueFilter配合startRow获取一部分数据
    • 然后用checkAndPut标记该数据正在处理
    • 最后再用put标记该数据已经处理

    HBase实战经验

    向下兼容

    开发过程中,难免需要加字段的,那这个时候,就需要代码、数据能够向下兼容。

    比方说我们现在需要新增一个column,因为是新加的一列,原来的数据这列就是null,那么这时候从HBase里面读到的值就是null,所以写HBase代码一定要注意:

    • 从HBase里面的数据一定要check null,如果是null,我就用一个默认值
    • 代表元数据的DO类的默认值,最好不要是nullnull永远不要存在在代码中
    • 再一次强调,非常建议数据用String的方式存储,因为可视化的数据能够帮您解决很多问题

    RowKey的设计

    1. 建议使用String如果不是特殊要求,RowKey最好都是String。
      • 方便线上使用Shell查数据、排查错误
      • 更容易让数据均匀分布
      • 不必考虑存储成本
    2. RowKey的长度尽量短如果RowKey太长话,第一是,存储开销会增加,影响存储效率;第二是,内存中Rowkey字段过长,内存的利用率会降低,这会降低索引命中率。

      一般的做法是:

      • 时间使用Long来表示
      • 尽量使用编码压缩
    3. RowKey尽量散列RowKey的设计,最重要的是要保证散列,这样就会保证所有的数据都不都是在一个region上,避免做读写的时候负载将会集中在个别region上面。

      假设我们需要存储一个用户的所有微博(暂时不需要考虑时间倒排),这时候的RowKey的设计是UserId_WeiboId ,但是这样设计的话,UserId 的分布就很可能不均匀,因为RowKey是字符串排序的。

      有两种办法来解决这个问题

      • ReversesUserId字符串反转后存储
      • Hash或者ModUserIdMD5 后作取前6位为前缀加入到 UserId 前面
    4. RowKey排序假设我们有个很多微博用户发微博,但是这个时候,我们要开辟一个“广场”,所有的微博都是按照时间倒排序展示在这个“广场”里。这个时候我们就得为原来的UserId_WeiboId建立一张索引表,并且这个表的Rowkey要和时间相关
      • Rowkey的设计可以使用当前时间 - 微博发表时间的 long 值作为 RowKey 的前缀
      • RowKey散列
      • 如果数据可以定期清理如果数据不是需要一直保存的话,就算所有数据落在一个region,因为按时间搜索会指定startRow,存储时候Rowkey也是连续的,所以速度也非常块,当然数据容量最好和DBA商量一下
      • 如果数据都需要保存把DayOfMonth作为前缀

        那么RowKey会是 DayOfMonth_(当前时间 - 微博发表时间)

        不过这样在代码实现上面的时候会有一些麻烦。

    5. 关于事务目前HBase的Put,Delete操作都是事务的,但是如果您希望能够对好几个Table发起一连串操作并且希望是事务的话,目前还没有好的办法。所以HBase使用的时候,要有解决数据出错的觉悟。
  • 相关阅读:
    优达,计算机科学导论
    关于未来发展阶段小结
    CS50.5
    CS50.4
    简单查看tomcat中部署java服务的内存使用情况
    python3环境搭建(CentOS7.2)
    mysql主从配置脚本
    安装rkhunter
    转移到博客园啦!
    Eclipse上Maven环境配置使用 (全)
  • 原文地址:https://www.cnblogs.com/ihongyan/p/4741092.html
Copyright © 2011-2022 走看看