博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
从MySQL到HBase:数据存储方案转型的演进
阅读量:7025 次
发布时间:2019-06-28

本文共 3461 字,大约阅读时间需要 11 分钟。

hot3.png

一、集群化方案

1、MySQL应用的演化

MySQL与HBase说到最核心的点,是一种数据存储方案。方案本身没有对错、没有好坏,只有合适与否。相信多数公司都与MySQL有着不解之缘,部分学校的课程甚至直接以SQL语言作为数据库讲解。我想借自身经历,先来谈谈MySQL应用的演化。

只有MySQL

笔者之前曾在一家O2O创业公司工作,公司所有数据都存储在同一个MySQL里,而且没有任何主备方案。相信这是很多初创公司会用到的一个典型解决办法,当时这台MySQL为用户、订单、物流服务,同时也为线下分析服务。

f7f9b665d53789a12a522a7bda73880a65532483

单实例的问题:

d47e62d2b349aca45e42305ed6714efbe5ed61d9一旦MySQL挂了,服务全部停止;

d47e62d2b349aca45e42305ed6714efbe5ed61d9一旦MySQL的磁盘坏了,公司的所有服务都没有了 (一般会定时备份数据文件)。

主从方案

随着业务增加,单个DB是无法承载这么多请求的。于是就有了主从复制、读写分离的解决方案。

1812d4a4c1861162db00b1153ffee9ef508c17cb

master只负责写请求,slave同步master用来服务读请求:

d47e62d2b349aca45e42305ed6714efbe5ed61d9为了扩展读能力可以增加多个slave;

d47e62d2b349aca45e42305ed6714efbe5ed61d9允许slave同步有一定的延迟;
d47e62d2b349aca45e42305ed6714efbe5ed61d9一致性要求严格的,可以指定读主库。

主从功能的问题:

d47e62d2b349aca45e42305ed6714efbe5ed61d9需要增加管理Proxy层,分配写请求、读请求;

d47e62d2b349aca45e42305ed6714efbe5ed61d9节点故障:其它节点应该快速接管故障节点的功能。

垂直拆分

业务继续增长,master甚至无法承载所有的写请求,数据库需要按业务拆分。

b8c017d71435315babb0fa6aa303e65b081f98a4

垂直拆分的问题:

d47e62d2b349aca45e42305ed6714efbe5ed61d9线下分析,需要在业务代码里join各个表。因为拆成多个库,已经无法join了。

d47e62d2b349aca45e42305ed6714efbe5ed61d9不容易做数据库的事务性,用户余额减少与下单成功的情况下无法使用MySQL的事务功能。

水平拆分

业务继续增长,订单表有大量的并发写入,而且已经有了几千万行数据。

d47e62d2b349aca45e42305ed6714efbe5ed61d9单个库无法承载大量的并发写入;

d47e62d2b349aca45e42305ed6714efbe5ed61d9上千万行的大表,数据写入可能需要调整一棵巨大的B+树;
d47e62d2b349aca45e42305ed6714efbe5ed61d9上千万行,B+树过深,读写需要更多的磁盘IO;
d47e62d2b349aca45e42305ed6714efbe5ed61d9很多老数据访问较少,B+树上层缓存的部分信息无用;
d47e62d2b349aca45e42305ed6714efbe5ed61d9……

参考:大众点评订单系统分库分表实践

https://zhuanlan.zhihu.com/p/24036067

aef7c6c45fb8041125c607c03d2b5dae8a26a6cb

水平分库/分表带来的问题:

d47e62d2b349aca45e42305ed6714efbe5ed61d9维护map方案;

d47e62d2b349aca45e42305ed6714efbe5ed61d9辅助索引只能局部有效;
d47e62d2b349aca45e42305ed6714efbe5ed61d9由于分库,无法使用join等函数;由于分表count、order、group等聚合函数也无法做了;

d47e62d2b349aca45e42305ed6714efbe5ed61d9扩容:需要再次水平拆分的:修改map,迁移数据……

2、MySQL的问题

MySQL的主要瓶颈,单机单进程。CPU有限、内存/磁盘功能、连接数有限、网卡吞吐有限……

集群的限制点:

d47e62d2b349aca45e42305ed6714efbe5ed61d9关系型数据库,纵向的外键相互join;

范式参考链接:https://zhuanlan.zhihu.com/p/20028672

d47e62d2b349aca45e42305ed6714efbe5ed61d9数据库事务性,基于单机的锁机制,无法扩展到集群中使用;

d47e62d2b349aca45e42305ed6714efbe5ed61d9全局有序列性基于B+树,数据有序聚合存储,集群化后无法保证;
d47e62d2b349aca45e42305ed6714efbe5ed61d9数据本地存储,扩容需要迁移数据。

集群的方案:

d47e62d2b349aca45e42305ed6714efbe5ed61d9放弃部分功能,辅助索引检索、join、全局事务性、聚合函数等;

d47e62d2b349aca45e42305ed6714efbe5ed61d9水平拆分:存储KV化,用机械的map思路实现集群;
d47e62d2b349aca45e42305ed6714efbe5ed61d9扩容方案:手动导数据,开发数据迁移脚本;
d47e62d2b349aca45e42305ed6714efbe5ed61d9事务性:两阶段事务、paxos、单库事务……
d47e62d2b349aca45e42305ed6714efbe5ed61d9备份容灾:从节点同步主节点,但有一定的数据延迟;

d47e62d2b349aca45e42305ed6714efbe5ed61d9服务稳定性:主节点挂了,Proxy会将从节点升级为主节点;从节点挂了会被其它从节点替换。

3、HBase集群化解决方案

水平拆分:

d47e62d2b349aca45e42305ed6714efbe5ed61d9region:拆分后的子表;

d47e62d2b349aca45e42305ed6714efbe5ed61d9Region Server:管理这些数据的server,相当于一个MySQL实例;
d47e62d2b349aca45e42305ed6714efbe5ed61d9.META.表存储拆分信息map<row, server>。

8f6b6a4d2b6cdc826073c1a57afbcf0a6766b20d

单个region过大,RegionServer会将region均分为两个(自动、手工)。然后更新.META.表。

扩容方案:

RegionServer向HMaster汇报状态。HMaster为RegionServer负载均衡,调整其负责的region 。

增/删RegionServer后,会为重新调整region的分配方式。

服务稳定性:

RegionServer只是计算单元,挂掉后Hmaster可以随便再找一个节点代替坏节点服务。

事务性:

HBase只保证行级事务,单行数据肯定存在同一台机器(单机事务很好做)。

备份容灾:

d47e62d2b349aca45e42305ed6714efbe5ed61d9数据使用HDFS存储,多复本,任何一个复本挂掉都不影响功能;

d47e62d2b349aca45e42305ed6714efbe5ed61d9RegionServer只是计算单元,挂掉后不影响服务。

二、性能取舍

1、数据请求流程

HBase:

d47e62d2b349aca45e42305ed6714efbe5ed61d9Client会通过Zookeeper定位到 .META. 表;

d47e62d2b349aca45e42305ed6714efbe5ed61d9根据 .META. 查找需要服务的RegionServer,连接RegionServer进行读写;
d47e62d2b349aca45e42305ed6714efbe5ed61d9Client会缓存 .META. 表信息,下次可以直接连到RegionServer 。

MySQL:

d47e62d2b349aca45e42305ed6714efbe5ed61d9Client通过Proxy,查找需要连接的MySQL实例,连接并进行读写。

Rquest的路由流程,MySQL与HBase基本一致,那么RegionServer与MySQL的性能差异如何呢?

2、Hbase写得快

新增

为什么MySQL建议自增主键?(MySQL随机插入的代价)

d47e62d2b349aca45e42305ed6714efbe5ed61d9主键索引是有序的B+树结构,新增条目的ID肯定是最大的,新增给B+结构带来的调整最小;

d47e62d2b349aca45e42305ed6714efbe5ed61d9主键索引是聚簇的:新增条目,ID是最大的。其data追加在上一次插入的后面,磁盘更容易顺序写。

辅助索引,插入基本是随机的:

d47e62d2b349aca45e42305ed6714efbe5ed61d9插入条目,可能会引起B+树结构很大的调整。

HBase可以随机插入:

d47e62d2b349aca45e42305ed6714efbe5ed61d9HBase的所有插入只是写入内存memstore,只保证内存数据的有序即可(很快、很容易);

d47e62d2b349aca45e42305ed6714efbe5ed61d9为防止数据丢失写入memstore前,先写入wal(可以关闭,速度更快);
d47e62d2b349aca45e42305ed6714efbe5ed61d9HBase没有辅助索引需要维护;
d47e62d2b349aca45e42305ed6714efbe5ed61d9memstore写满了,申请一块新的内存,旧的memstore被后台线程刷盘,存入HFile。

修改

MySQL数据变化引起存储变动:

d47e62d2b349aca45e42305ed6714efbe5ed61d9数据块大小变化:磁盘空间不足,可能需要调整磁盘存储结构,引起大量的磁盘随机读写;

d47e62d2b349aca45e42305ed6714efbe5ed61d9辅助索引发生变化:可能需要重新调整辅助索引B+树。

HBase直接将变化写入到memstore,没有其它开销。

删除

MySQL数据删除:

d47e62d2b349aca45e42305ed6714efbe5ed61d9直接操作B+树的节点,肯定需要刷新磁盘;

d47e62d2b349aca45e42305ed6714efbe5ed61d9如果引起树结构变化,甚至可能需要多次刷新磁盘。

HBase只是在memstore记录删除标记,没有其它开销。

3、结论

HBase写入内存+后台刷盘(最多是WAL,磁盘顺序写);MySQL需要维护B+树,大量的磁盘随机读写。

MySQL要求尽量追加写(自增 ID),速度较慢;HBase可以随机插入,速度很快。

MySQL读得快

MySQL数据是本地存储的,HBase是基于HDFS,有可能数据不在本地。

B+ 树天然的全局有序

d47e62d2b349aca45e42305ed6714efbe5ed61d9根据主键查询,可以快速定位到数据所在磁盘块,只需要极少的磁盘IO即可拿到数据:通过缓存高层节点,主健查询只需要一次磁盘IO就可拿到数据;MySQL单表行数一般建议不会超过2千万,千万行以下的大表,B+树只需2~3层即可;

d47e62d2b349aca45e42305ed6714efbe5ed61d9辅助

索引,提供快速定位能力:辅助索引B+树,可以快速定位到最终所需的主键ID,根据主键ID可以快速拿到所需信息。

HBase只有局部信息,没有辅助索引

d47e62d2b349aca45e42305ed6714efbe5ed61d9查询会优先查找memstore,如果没有会查找Hfile(存储结构类似B+树)。如果第一个Hfile中没有所需的信息,则需要去第二、第三个Hfile中查询;如果查询的数据恰好在memstore,第一个Hfile,HBase会优于MySQL;平均下来,HBase读性能一般。减少Hfile数据以提速,小的HFile合并成大的HFile文件。这种存储结构叫LSM树(Log-structured merge-tree);

d47e62d2b349aca45e42305ed6714efbe5ed61d9如果需要检索特定的列,可能需要遍历所有Hfile,成本巨高。

MySQL成也B+,败也B+;HBase成也LSM,败也LSM。

4、附录

2dffa213706cb6c08f780f7b34c80d4b6d58389a

B+ 树

查询“值为25”的节点,只需要2次定位即可。

cc378ddcad927cf061a1e0afb9854f1848391595

LSM树

查询“值为25”的节点,只需要4次定位即可。

 

三、优化思路

1、HBase优化点 (主要是读)

异步化

d47e62d2b349aca45e42305ed6714efbe5ed61d9后台线程将memstore写入Hfile;

d47e62d2b349aca45e42305ed6714efbe5ed61d9后台线程完成Hfile合并;
d47e62d2b349aca45e42305ed6714efbe5ed61d9wal异步写入(数据有丢失的风险)。

数据就近

d47e62d2b349aca45e42305ed6714efbe5ed61d9blockcache,缓存常用数据块:读请求先到memstore中查数据,查不到就到blockcache中查,再查不到就会到磁盘上读,把最近读

转载于:https://my.oschina.net/u/3889140/blog/1833425

你可能感兴趣的文章
UVa10405
查看>>
为乐趣而生----禁止网页右键、复制、另存为方法
查看>>
JavaScript 文件拖拽上传插件 dropzone.js 介绍
查看>>
JS删除数组条目中重复的条目
查看>>
jQuery数组处理详解(转)
查看>>
ztree 获取子节点所有父节点的name的拼接
查看>>
hdu1412
查看>>
后仿真笔记 - ise 联合 modelsim
查看>>
python @property
查看>>
XCOJ 1168 (搜索+期望+高斯消元法)
查看>>
紫书 例题11-9 UVa 1658 (拆点+最小费用流)
查看>>
紫书 例题11-4 UVa247 (Floyd判断联通)
查看>>
防cc攻击利器之Httpgrard
查看>>
PCA MATLAB
查看>>
【天池大数据赛题解析】资金流入流出预测(附Top4答辩ppt)
查看>>
广告点击率预测 [离线部分]
查看>>
CodeForces 659F Polycarp and Hay
查看>>
Servlet客户请求的处理:HTTP请求报头HttpServletRequest接口应用
查看>>
http://stormzhang.com/devtools/2014/12/09/android-studio-tutorial3/ 安卓studio 安装教程
查看>>
ES6(5) - 变量的解构赋值
查看>>