HBase与传统数据库的存储革命:从MySQL瓶颈到海量数据选型
发布时间:2026/10/1 16:16:26来源:尧图网络
我接触HBase其实是被逼的。当时负责的网约车订单系统MySQL里一张订单表已经接近十亿行业务高峰期写入延迟一路飙到秒级传统数据库那套分库分表的玩法也快到了瓶颈。那阵子我天天看监控面板看着磁盘IO、主从延迟、慢查询像过山车一样上下翻心里特别没底。在一次技术选型会上有人提了一句要不要试试HBase我才开始认真研究这个在大数据圈里名声很响、但在传统数据库工程师眼里一直有些异端的存储系统。这篇内容想聊的就是HBase和传统数据库在大数据场景下的那场存储革命。如果你正面临类似困惑——单表数据量大到MySQL扛不住、或者正在准备大数据方向的学习和面试希望搞明白HBase到底解决什么问题、和MySQL有什么本质区别、实际项目里该怎么选型——那这篇文章应该能帮你把思路理清楚。我尽量少讲虚的多讲原理和实操中真正会踩到的坑。1. 当MySQL顶不住时HBase是怎么冒出来的——理解两类系统的设计初衷1.1 传统数据库的强项与隐忧我们得先说清楚一件事MySQL、Oracle这类传统关系型数据库能在软件行业统治几十年靠的不是运气。它们有几样非常扎实的能力——ACID事务保证数据不会出现半成品状态、SQL查询让业务开发能用很简洁的代码完成复杂逻辑、B树索引和优化器让点查和范围查询都非常快。你今天去任何一个互联网公司核心的订单、账户、商品库几乎全跑在关系型数据库上这个基本盘短时间内不会变。但是当数据量进入大数据这个量级之后传统数据库的三堵墙会慢慢暴露出来。第一堵是容量墙。InnoDB引擎的B树索引天然是内存敏感的数据量大了以后热数据没法全部放进Buffer Pool随机磁盘IO就会出现查询延迟变得很不稳定。我那个项目里订单表到了十亿行简单的SELECT * FROM order WHERE order_id ?都可能要扫好几层索引树响应时间从几十毫秒膨胀到几百毫秒。第二堵是写入墙。关系型数据库的写入是原地更新要在磁盘上定位到旧数据所在页然后修改、刷盘过程中还要处理行锁、间隙锁、页分裂。并发一旦上去锁冲突和IO竞争会把写入吞吐牢牢卡死。业务高峰期写入延迟飙到秒级就是我们当时最直观的感受。第三堵是扩展墙。分库分表确实是传统数据库应对大数据量最常用的方案但它有三个让人头疼的副作用跨库查询要引入中间件业务代码要改造成按分片键路由全局排序、聚合、唯一性约束都变得极其别扭扩容时数据迁移和rebalance像在拆炸弹一不小心就影响线上。这三堵墙叠加在一起就逼出了一个问题有没有一种存储系统天生就为海量数据、海量写入、弹性扩容而生1.2 从BigTable到HBase专门为海量数据设计的存储层答案的源头可以追溯到2006年Google发表的那篇经典论文《BigtableA Distributed Storage System for Structured Data》。当时Google内部已经在用Bigtable支撑搜索索引、地图数据、网页抓取等多达PB级别的结构化数据。Bigtable的设计目标很明确一张表可以放数PB的数据能够横跨几千台廉价服务器写入吞吐和存储容量可以随节点数量线性扩展。HBase就是Bigtable的开源实现而且是Hadoop生态里最核心的存储组件之一。这里要稍微提一下大数据架构的四层——采集层用Flume、Kafka这类工具把日志和业务数据收进来存储层靠HDFS和HBase这类分布式系统把海量数据存住计算层用MapReduce、Spark、Flink做批处理和流处理应用层再做报表、推荐、数据服务。**HBase在整个体系里的位置就是存储层而且是面向近线、在线随机读写的存储层。**它跑在HDFS之上靠ZooKeeper协调分布式节点天生就是一个分布式系统。关键点在于HBase和MySQL的设计出发点完全不同。MySQL的出发点是一个通用的事务型数据库HBase的出发点则是一张几乎没有容量上限的稀疏大表。为了达到这个目标它主动做了一些牺牲不支持跨行事务不支持Join不支持SQL甚至连二级索引都需要额外想办法。你可能觉得这些牺牲很离谱但这正是它能在海量数据场景下活下来的原因——什么都想要的结果通常是什么都做不好。1.3 存储革命不是取代是分工我经常遇到朋友问HBase能不能把MySQL直接替换掉我的回答通常是这个问法本身就错了。它们不是替代关系而是不同赛道上的不同选手。拿我当时的实际场景来说网约车订单系统里有两类数据一类是当前订单状态、账户余额这类需要强一致、要支持复杂事务的热数据必须留在MySQL另一类是历史订单、轨迹点、用户行为日志这类写入量大、几乎不更新、查询永远按订单ID或时间范围来查的冷数据这类数据如果也全塞MySQL很快就爆炸了而喂给HBase又特别合适。所以存储革命的真实含义不是HBase革了传统数据库的命而是它给大数据时代增加了一个前所未有的选择。系统设计从什么都能干的一台数据库变成了各司其职的一组存储组件MySQL管交易Redis管缓存HBase管海量在线数据HDFS管离线文件数据仓库管分析。把这一点想明白了后续所有技术选择都会清晰很多。2. 底层架构剖开看一张表在HBase和MySQL里分别是怎么存的2.1 MySQL的InnoDB经典的B树行存储要看懂HBase的设计逻辑最好先理解传统数据库的一张表是怎么存在的。以InnoDB为例一张表的物理存储结构本质上是一棵聚簇索引B树主键作为索引的Key叶子节点直接存放一整行数据的物理记录。所以如果你通过主键去查一行走的就是这棵树的搜索路径速度很快。这种结构有它天然的劣势——随机写。新数据要插入的时候如果主键不是严格递增的InnoDB可能要把某个叶子节点页分裂开然后把新行插入到页中间再刷到磁盘对应的位置。整个过程是典型的随机IO磁盘磁头要来回寻道效率远低于顺序写。再加上写操作要持有行锁、记录undo日志、维护二级索引写路径每一步都在增加成本。这也是为什么传统数据库在写并发很高的场景下吞吐很难线性扩展。我一直喜欢用一个比喻传统数据库像一本账本每来一笔新交易都要翻到对应的页码在原来的行上动手修改。为了保证不写错账得锁住那一页别人不能碰改完再放行。还是那句话在数据量小、并发不大时这个模型很完美一旦变成几亿笔交易同时扑过来账本翻页的速度就成了瓶颈。2.2 HBase的分布式布局Region、Store与HFileHBase对一张表的切分方式完全是从分布式和水平扩展这两个词长出来的。一张HBase表里的所有行首先按照RowKey行键的字典序排好。整个表的RowKey范围会被切成很多个分片每个分片叫作一个Region。Region是HBase负载均衡和扩展的基本单位最小的表只有一个Region数据量大了就自动从中间分裂成两个再大了继续分裂。每个Region被分配到某台RegionServer上同一张表的不同Region可以分布在完全不同的机器上——这就是HBase能够水平扩展的核心机制。再往下看一层每个Region内部按列族Column Family把数据分成若干个Store。一个列族对应一个StoreStore内部有两个关键部分——一个内存写缓存MemStore以及一堆不可变的HFile文件。HFile是HBase最终的落盘格式存放在HDFS上可以理解成这列族数据在磁盘上的分片文件集合。我用一张文本示意来帮你建立整体印象[HBase Table: trip_trace] ├── Region ARowKey范围 0000~3FFF由RegionServer-1托管 │ └── 列族 cf - Store(A) │ ├── MemStore内存正在积累写入 │ ├── HFile-1已经刷盘的文件不可修改 │ └── HFile-2已通过Compaction合并后的新文件 ├── Region BRowKey范围 4000~7FFF由RegionServer-2托管 │ └── 列族 cf - Store(B) └── Region CRowKey范围 8000~BFFF由RegionServer-3托管 └── 列族 cf - Store(C)你看同样的RowKey范围分布在完全不同的服务器上。数据再多Region就继续分裂机器不够就加RegionServer容量和吞吐可以跟着线性增长。这跟分库分表有本质区别——分库分表是需要DBA手动参与、提前规划、切分键写死在代码里的HBase的Region分裂、移动、负载均衡都是运行期自动完成的你只需要保持RowKey设计合理就行。2.3 LSM用顺序写换写吞吐HBase在单机存储引擎层面选了一条和B树完全不同的路叫做LSM树Log-Structured Merge Tree日志结构合并树。这套思想的核心是把随机写变成顺序写把更新变成追加。具体到HBase的写路径是这样走的。客户端发来一个Put请求RegionServer会把这条数据先追加到WAL日志HBase里叫HLog防止系统宕机丢数据然后写入当前Region对应列族的MemStore内存区。数据在MemStore里是按RowKey排好序的所以写入都是内存操作速度极快。当MemStore的大小超过阈值默认128MB左右RegionServer就会把这个内存区整体刷写成一个新的HFile文件写到HDFS上。HFile一旦生成就不可变了后续对这个RowKey的更新只会写到新的HFile里不会去改旧文件。这整个过程里磁盘操作只有追加WAL和顺序写HFile两步全部是顺序IO所以写入吞吐特别高。等HFile文件越积越多后台的Compaction进程会把多个小HFile合并成一个大HFile清理掉被覆盖或已删除的旧版本数据。你瞧这就像收银员不再每笔交易都翻开账本改上一笔而是先把所有的新交易记在便签上下班后再把便签整理装订成新的账册。但LSM不可能是免费的午餐。它的代价主要在读取端由于同一个RowKey的数据可能散落在MemStore和多个HFile里一次读取需要检查内存、再检查多个磁盘文件最后把不同版本的数据合并到一起才能拿到最终结果。如果不做任何优化读放大问题会非常严重。所以HBase在读取路径上又加了BlockCache缓存、Bloom Filter布隆过滤器等手段来加速。这也是为什么HBase强在海量写入海量存储而单纯点查性能并不比内存型的Redis快——它的核心竞争力和传统数据库是错开的。3. 数据模型与读写路径同样是表语义完全不同的两回事3.1 RowKey、列族、时间戳先忘掉关系表那套东西第一次接触HBase的人最容易犯的一个错误是拿MySQL的表模型往HBase上套。HBase虽然也叫表但它的逻辑模型完全不一样。一张HBase表里每一行数据由一个唯一的RowKey定位RowKey就是那个行键类似MySQL的主键但它的作用更极端——它是HBase定位和读取数据的唯一路径。一行的数据由若干个列族组成每个列族下可以有很多个列限定符Column Qualifier你可以把列限定符当成动态的列名。最灵活的一点是每一行可以有不同的列集合某行没有的列不占任何存储空间这就是稀疏表的核心价值。比如我们要建一张网约车轨迹表表名叫trip_trace列族cf下面可以动态加很多列。在HBase Shell里建表和写数据是这样的# 建一张只有cf列族的表 hbase(main):001:0 create trip_trace, cf # 写入一行数据RowKey叫 row_001分别写入司机ID、经度、纬度 hbase(main):002:0 put trip_trace, row_001, cf:driver_id, D1001 hbase(main):003:0 put trip_trace, row_001, cf:lon, 116.40 hbase(main):004:0 put trip_trace, row_001, cf:lat, 39.90 hbase(main):005:0 put trip_trace, row_001, cf:ts, 1700000000每一行还有一个隐藏字段——时间戳Timestamp也叫版本号。默认情况下你多次对同一个RowKey和同一个列做putHBase会保留多个版本取数据时默认返回版本最新的那个。这意味着HBase天然支持记录变化历史的能力这在存储价格波动、状态变迁这类数据时非常有用。但代价也很直接**这个表没有字段定义没有ALTER TABLE那种结构变更更没有一个查询优化器来给你做多表关联。**你用scan扫出来的就是一堆RawKey和单元格数据所有业务语义都需要应用层自己理解和维护。3.2 读写路径一次Put和一次Get到底发生了什么我们再把读写路径完整走一遍。写路径刚才在LSM那部分已经提到过了完整顺序是Client请求到达RegionServer后先写入HLog再写MemStoreMemStore满后刷成HFile。只要HLog写成功了把数据返回给客户端说写入成功哪怕后面内存里数据还没落盘服务宕机了也能从HLog里恢复不会丢。读路径稍微复杂一点。RegionServer收到一个Get请求时会先在MemStore里查最新写入但还没落盘的记录如果没有再去BlockCache读缓存里查如果缓存里也没有才会去对应的HFile文件里查找。由于HFile可能有多个HBase会用Bloom Filter先判断某个文件里到底有没有这个RowKey快速跳过不可能包含数据的文件然后又把多个文件里读到的内容按版本合并成最终结果返回。说到这你应该能get到一个关键点**HBase的查询效率非常依赖RowKey。**用RowKey做点查也就是get trip_trace, row_001速度非常快因为Region通过定位直接跳到对应的RegionServer内存里找不到再去HFile里精确找那一个位置。用RowKey范围做Scan也就是scan trip_trace, {STARTROW row_001, ENDROW row_002}也很快因为RowKey在Region内是有序的顺序扫就行。但如果你企图查所有lon大于某个值的行——抱歉没有任何索引可用只能全表扫描这在几十亿行上根本跑不动。3.3 关于列式存储这个常见误解市面上有个很流行的说法叫HBase是列式存储数据库这句话严格来说是不准确的而且会误导很多人选错系统。我们对比一下ClickHouse这类真正的列式数据库ClickHouse把每一列的数据分开连续存放压缩率极高做聚合统计比如SELECT AVG(lon) FROM trip_trace只需要读取lon那一列的数据块其他列完全不碰所以分析型查询快得惊人。而HBase呢它的数据在列族层面是分开的不同列族的数据存在不同的Store里这确实有一点按列管理的味道。但在列族内部同一行的所有列的数据在HFile里其实是连续存放的本质上还是行式组织。所以HBase的列优势主要体现在两点一是稀疏存储某行没有的列不占空间二是按列族裁剪IO查询时只访问涉及的列族。它并不适合做任意列的聚合统计你要让HBase去算全表经纬度平均值那基本等于灾难。所以如果你听别人说列式存储适合大数据然后无脑选HBase去做数据分析大概率会踩坑。HBase的定位始终是海量数据的在线随机读写真正的离线分析、聚合统计交给Spark、Hive、ClickHouse这类计算和分析引擎更合适。这一点在数据量上来以后会体会特别深。4. 一致性、事务和查询能力HBase放弃了什么换来了什么4.1 ACID到BASE的取舍清单在讨论HBase是否好用之前最好先看清楚它做了哪些交易。传统数据库引以为傲的ACID在HBase这里被大幅简化了。先做一个直白的特性对照特性维度MySQL典型关系型HBase事务能力完整ACID支持跨行、跨表事务仅支持行级原子性跨行跨表事务需要额外方案SQL支持原生SQL语法丰富无原生SQL需靠Phoenix等中间层补充Join/多表关联原生支持不支持需应用层或计算层处理二级索引天然支持多个索引自由组合无全局二级索引需自己维护索引表水平扩展需要分库分表复杂度高原生分布式Region自动分裂迁移写吞吐受单机IO和锁竞争限制可随节点增加线性扩展存储规模单机或分片集群容量有限理论上无限PB级别常见数据模型固定Schema严格结构稀疏宽表列可动态增减查询模式任意条件组合查询主要是RowKey点查和范围Scan这张表看完你就能明白HBase做的是一次极端的性能与能力的交换它把关系型数据库引以为傲的复杂查询、多行事务、完整一致性统统砍掉换来了海量写入吞吐和无上限的水平扩展。为什么它可以砍掉这些因为大数据的核心场景就是写入量巨大、以主键为中心读写、对跨行强一致没那么多要求。用户行为日志写进来没人会要求它和一个订单跨行做事务轨迹数据存下来查询永远是按订单ID或者司机ID和时间范围去取。为了这些不需要的能力付出性能代价在离线规模下是不划算的。4.2 用生态补短Phoenix、Hive/Spark、二级索引的常见玩法HBase砍掉的那些能力实际工程里当然还有需求所以生态里出现了各种各样的补位方案。如果你实在想要SQL可以使用Phoenix。它是个跑在HBase之上的SQL皮肤把SQL解析成HBase的Scan和Get操作还支持创建二级索引内部会自己维护索引表。但你要清楚Phoenix的SQL能力远不如MySQL灵活Join、子查询、复杂聚合都很有限更多时候是给团队提供至少不用写Shell命令的便利。如果你要做离线批量分析更主流的做法是Hive或者Spark SQL直接读HBase表把HBase当作数据源批量Scan整表数据去做ETL和统计。比如我们当时做司机每日收入汇总就是Spark凌晨去扫HBase里的订单历史表做完聚合写回结果表。这种模式下HBase只承担存储计算完全在上层完成。二级索引的通用方案有两种一是用Phoenix的索引特性二是在业务层自己维护索引表。比如按司机ID查轨迹列表而实际RowKey是订单ID和时间戳的组合那我们可以额外建一张driver_index表把司机ID作为RowKey存他所有的订单ID列表。写入订单时同时写这两张表。说到底HBase给人添的麻烦在选型阶段就要想清楚等上了生产才发现没有索引那代价就大了。4.3 回答一个面试高频题HBase到底是强一致还是最终一致HBase相关的技术面试题里这个问题出现的频率很高而且很多答案说得含糊。我可以给你一个比较准确的层次拆解。先从最核心的机制说起。HBase中一个Region在任意时刻只会由一个RegionServer负责所有对该Region的读写都走同一个节点并且HLog和MemStore的写入都在该节点上串行完成。所以在单行数据这个粒度上HBase是强一致的——你写入成功后再读一定能读到刚写入的值不会出现MySQL主从延迟那种写完马上读不到的情况因为HBase根本没有传统意义上的异步主从复制。但从多个Region或者整个表的角度看情况就复杂了。默认情况下跨Region的多个写操作不是原子的可能一边成功一边失败Region在Split分裂或RegionServer宕机恢复期间这个Region会短暂不可用出现类似暂时不可服务的状态。所以更准确的说法是**HBase提供单行的强一致以及简单的最终一致性但不提供跨行事务。**你把这句话说清楚面试官基本就满意了。这一点在选型时也极其重要。如果你做一个交易系统一笔转账需要同时更新两个账户HBase的单行强一致完全不够用。这类业务老老实实留在传统数据库不要指望HBase帮你解决。5. 真实的选型决策哪些场景该用HBase哪些场景别硬上5.1 该用HBase的典型场景我从实际项目经验出发给你几个HBase真正能发挥价值的典型战场。第一个是海量订单与轨迹的历史存储。订单表在MySQL里积累到几亿行之后查询和运维都会变得痛苦尤其是不再频繁更新的历史订单。把历史订单定期归档到HBase按用户ID_日期或者订单ID做RowKey查询时直接Get又快又不占在线库空间。我们当年的链路就是订单在MySQL里做在线交易过了30天归档期后由Spark批量写入HBase供用户端历史行程页面查询。第二个是用户行为日志与画像数据。比如埋点日志、点击流、推荐系统的用户特征向量。这类数据的特点是写入量巨大、字段经常变化、需要按用户维度实时读写。HBase的列族可以让你随时给某个用户增加一个画像标签列不用改表结构稀疏存储又不会浪费空间非常适合。第三个是物联网时序数据。设备上报的传感器值、车辆GPS坐标、智能电表的读数全是高频写入、按设备ID和时间范围查询、旧数据基本不更新的模式。HBase天然吃这类负载只要RowKey设计成设备ID反序时间戳单设备的顺序扫就很快。第四个是消息和事件类数据的临时存储。很多消息系统会把最近一段时间的事件存到HBase里方便消费者回溯和补数据。HBase的行级强一致和TTL过期机制让这类场景实现起来非常干净。5.2 别硬上HBase的典型场景反过来有几类场景我劝你离HBase远一点。第一是强事务业务系统。账务、支付、股票交易每一笔操作都牵扯多行、甚至跨表一致性。HBase没有原生跨行事务硬上就需要你自己做分布式事务复杂度会爆炸。这种场景选MySQL或者TiDB这种分布式SQL数据库更合适。第二是复杂报表和数据分析系统。用户想看任意维度的交叉统计比如按城市、按车型、按时间段的订单分布HBase没有二级索引、没有Join、聚合能力差一个简单查询都可能变成全表Scan性能上完全不可接受。这种需求该走数据仓库、ClickHouse、或者是Spark预聚合。第三是需要大量动态条件查询的在线API。如果产品经理要求按字段A、B、C任意组合过滤而A、B、C都不是RowKey那HBase要实现这玩意会让人怀疑人生。你得为每个查询维度建索引表写入要维护多张表查询要跨表合并开发成本高到离谱。这里顺便给出一个选型层面的判断口诀**数据量是否大到单表十亿行以上写入是否高频海量查询是否以主键/时间范围为主对跨行事务是否没什么要求**如果四个问题答案都是是那HBase非常适合如果前两问是否那大概率用不上它别为了用大数据技术而硬上。5.3 四步判定法一个网约车案例的复盘我把当时做网约车历史订单系统的选型过程拆成四步给你做参考。第一步评估数据规模。历史订单每个月新增几千万行加上轨迹点存储量是几十TB级别。这个量级已经不是单机MySQL的菜了分库分表也只是把问题延后。第二步评估读写模式。这些历史数据的查询特征是用户端只按用户ID订单列表做分页查客服后台按订单ID查明细。写入是每天定时批处理导入没有更新需求。这正好命中HBase的RowKey点查和Scan模型。第三步评估一致性要求。历史订单一旦生成就不会再变最多是状态修正也不涉及多行原子操作。单行的强一致完全够不需要事务。第四步评估团队运维能力。我们有Hadoop集群经验HDFS和ZooKeeper都是现成的上HBase的附加成本可控。如果团队对Hadoop生态零基础那选择HBase前要慎重它的运维门槛确实比单机MySQL高不少。最后的结果大家也知道了——历史订单系统用HBase来做线上跑得很稳单次查询P99在几十毫秒级别存储成本比扩MySQL实例低了一个数量级。再补一个同类产品对比帮助你在更宽的视野里做决策存储系统核心优势最适合的场景Redis内存读写极低延迟热数据缓存、计数器、排行榜HBase海量在线读写水平扩展订单历史、轨迹、行为日志、特征存储Cassandra多数据中心容灾写可用性极高全球化部署的时序与消息场景TiDB分布式但有完整SQL和事务想分布式扩容又舍不得MySQL语法的业务ClickHouse极高的分析聚合性能离线分析、日志分析、BI报表这张表其实在提醒你**没有最好的存储只有最匹配的存储。**选型永远是基于你的核心矛盾去的而不是跟风追新技术。6. 入坑HBase之前这些经验和坑先收好6.1 环境准备、端口清单和Windows伪分布式部署的注意点HBase自己不是一个独立运行的数据库它依赖HDFS提供底层文件存储依赖ZooKeeper做分布式协调。所以如果只是想快速学习和验证我建议先在环境配置上走一遍但不要在生产上一开始就上大集群。先给出一份常用端口清单排错的时候特别有用服务组件默认端口说明ZooKeeper2181HBase依赖ZK做RegionServer协调和元数据管理HMaster Web UI16010集群管理界面能看到Region分布、表列表HMaster RPC16000HMaster进程间的通信端口RegionServer Web UI16030查看单个RegionServer的读写指标RegionServer RPC16020客户端读写请求走这个端口HDFS NameNode Web UI9870新版HDFS管理界面查看底层文件状态如果你是本地练习可以在Windows上搭一个伪分布式或者单机模式。**一个特别容易踩的坑是Windows下需要先配置好JAVA_HOME并下载与HBase版本兼容的Hadoop Windows二进制工具winutils.exe否则启动时经常报找不到Hadoop native库的错。**我第一次在Windows上装了三天才跑起来后来发现就是缺少winutils而已。现在很多人直接用Docker来跑HBase一条命令docker run -d -p 2181:2181 -p 16010:16010 harisekhon/hbase就能起一个单机镜像反而省心很多。启动后先用status命令确认集群状态没问题再执行list查看表列表能返回就说明环境OK了。6.2 RowKey设计是最大的坑预分区和热Region如果让我说HBase生产实践里最致命的坑RowKey设计排第一而且和后面九名拉开断档差距。RowKey决定了一个请求会打到哪个Region也就决定了整个集群的数据分布和热点分布。最常见的反面案例是用自增ID或者当前时间戳直接做RowKey。以时间戳为例所有新写入的数据都会落在最后一个Region上因为这个Region的RowKey范围最大其他Region完全空闲。结果就是集群里一台RegionServer忙成狗其余机器闲着看戏所谓分布式变成了伪分布式。这时候无论数据量多大写入速度永远被那一个热点节点锁死。解决办法要说透两件事第一是预分区。建表时让HBase把表的RowKey范围预先切成若干个Region避免所有数据一开始挤在一个Region里等着自动分裂。Shell里可以这样指定分区点# 预先把表按 RowKey 的 1~9 数字前缀切成多个 Region hbase(main):001:0 create trip_trace, cf, {SPLITS [1,2,3,4,5,6,7,8,9]}第二是RowKey加盐。加盐就是在原始业务Key前面加一个散列前缀让数据均匀分散到各个Region。比如原始RowKey是order_id_10086我们可以算一个哈希桶号前缀变成07_order_id_10086。这样同一批写入的不同订单会因为前缀不同打到不同的Region热点问题就解决了。再补充一个常用技巧如果查询模式是按用户查最近N条记录RowKey可以设计成user_id_reverse 时间戳也就是把时间戳倒序存储。这样Scan出来的第一条就是最新数据不用倒排。RowKey设计变成什么样查询性能就是什么样——这句话我建议你写进自己的笔记里因为所有HBase系统成败八成都在这上面。6.3 内存、Compaction和运维层面的几个血泪经验最后分享几个运维层面的实际经验都是我在生产上真金白银换来的。先说内存分配。每个RegionServer的JVM堆内存是有限的它要同时管写缓存MemStore和读缓存BlockCache。如果两者都想要最大就会打架。我们当时的经验是如果业务偏写多读少可以把MemStore占比调大如果读多写少BlockCache占比调大。这两个参数直接决定RegionServer会不会频繁Full GC——Full GC一次就是秒级卡顿在线读写直接受影响。然后是Compaction的IO抖动问题。HBase的后台Compaction会把多个小HFile合并成大文件这个操作是磁盘IO大户如果在业务高峰触发Major Compaction很可能把磁盘带宽吃满造成读写延迟飙高。运维上要做两件事一是把Major Compaction的自动触发时间错开到业务低谷窗口二是时刻关注RegionServer的IO指标发现明显抖动先查Compaction队列。还有一个非常容易忽略的问题**HBase并不擅长小文件。**如果你的写入量不大MemStore很久才刷一次盘每次刷出来的HFile都是很小的文件。小文件多了以后查询时打开文件的次数暴涨扫表性能急剧下降。所以低吞吐场景反而不适合HBase——这是很多人没料到的事实。我在一些Demo项目里见过有人用默认配置、每天就写几百条数据过段时间表里的HFile碎成几百个随手一个Scan慢到怀疑人生。这种场景你不如乖乖用MySQL。另外如果你做的是离线分析尽量走Spark或者Hive批量Scan不要在HBase上做Group By级别的操作。让HBase干它最擅长的事——在线数据服务离线计算交给计算引擎。这样才能让整个大数据架构的每一层都发挥出最大价值。说回我自己的经历那个网约车项目上线HBase之后我最大的感受其实是两个字的转变安心。订单历史表不用再每个月提心吊胆地清数据了扩容就是加机器热点问题通过预分区和加盐解决了查询响应稳稳的。如果你也是被海量存储和数据写入逼到墙角的人HBase值得你花时间学会它、用好它。至于那些动辄要消灭传统数据库的口号听听就行了真到架构设计的时候让MySQL和HBase各管一摊往往才是最优解。
网站建设高端定制企业官网