分布式key-value数据库,面向数十亿数据的实时入库与快速的随机访问。上百万的QPS与PB级数据,需要专门学习。
Hbase与MP一起操作比较少见,与Java API操作较多。
HMaster:集群管理
HRegion Server:具体的数据存取
Zookeeper:集群状态管理与元数据的存储

本地文件系统
或 HDFS分布式文件系统
或 其他对象存储: S3(AWS)、OSS(Aliyun)、OBS(华为云)
1、服务器选型
2、配置优化
3、日常运维
内容如下:
1、确定集群的承载量
2、确定所需要的内存
3、确定CPU型号和核数
4、确定磁盘类型和容量
5、确定网络承载
确定最大的承载量,是Hbase的最基础的需求。在处理能力适中的情况上,Hbase的处理能力是根据RegionServer横向扩展:比如集群总体10w/s读写能力,处理能力是根据RegionServer横向扩展,其集群的承载量设计如下:

如此配置,每天的入库量在86亿条。计算规则:
1w/s * 3600秒/h * 24h * 10台主机 = 86400万 ,约等于86亿条
Hbase内存型数据库是同存型数据库,数据写入规则:
先存储在Memostore中 ,
同时将经常查询的热数据缓存在内存中RedCache,提高性能。

因此Hbase是对内存要求比较高的服务, 为了保证Hbase运行的稳定,线上要求Hbase的服务器的内存配置为:16GB、32GB、64GB
为了保证快速的对Hbase数据进行处理,我们选择4核、8核、16核。
根据对数据实时性要求高低配置不同的配置,如果对实时性要求不高的,我们选择4核16G,以够用为原则。CPU与内存的比例1/4,如下图:

1、磁盘选型:
HDD: 数据大小写与读取请求数适中
SSD:有大量高效读取请求
以下需求选择SSD加快数据的读取效率:
数据比较大,比如10GB
对数据 Read(读操作)要求频繁
以下需求选择HDS即可:
高速写入,比如500M/S
稀疏写入的场景
2、磁盘容量
根据数据量确定磁盘容量盘大小,参考如下指标:
数据结构
压缩算法
副本数
数据存储时长
方法:通过在测试环境写入一部份数据来确定每条数据大小,再根据存储长短与副本确定磁盘大小。
Hbase的副本机制,需要将一份数据的多个副本实时存储在多个HDFS上,保存一个副本数据丢失,可以从其他副本中恢复数据。
对网络的要求是只要能保证网络能实时完成多副本写入数据即可。

1、副本数与网络带宽算法
预估方式:
10kb * 10万/1024MB = 976MB

3 * 976MB/s = 2928MB/s 大约2.9GB
2、Rebalance
良好的网络运营环境,也能保障集群发生Rebalance所需要的时间不会太长。
服务器选型总结
| 项目 | 要点 |
|---|---|
| 数量承载量 | |
| 所需内存 | 写入先缓存到Memstore、热数据缓存Redcache,16G、32G、64G
|
| CPU型号与核数 | 和内存1/4的关系,对速度要求不高可选4核 |
| 磁盘选型与容量 | SSD与HDD、 容量由“数据结构、压缩算法、副本数、数据存储时间 |
| 网络承载量 | 副本机制计算带宽、网络环境对Relance的影响 |
操作系统和Hbase集群参数调优,以达最优性能表现。
一、 操作系统调优
文件句柄数
最大虚拟内存
Swap内存设置
同样适用于Mangodb、Cassandra、Elasticsearch等nosql数据库。
Linux默认的句柄数为1024,不适合作为服务器的linux,修改如下:
echo "* soft nofile 65535" >> /etc/security/limits.conf
echo "* hard nofile 65535" >> /etc/security/limits.conf
max_map_count: 定义为进程能拥有的最多的内存区域,建议设置如下:
sysctl -w vm.max_map_count=102400
Swap开启是为了服务器吞吐量,但Hbase需要一个内存操作都能快速执行的环境,关闭Swap会提高读效率,设置如下
echo "vm.swappiness = 0" >> /etc/sysctl.conf
二、Hbase配置优化
配置优化项很多,这里讲主要参数
Hbase实时数据首先写入Memstore内存中,再到磁盘,同时缓存热点数据。
分配数量计算规则参考,以操作系统总内存为32G为例:
Hbase JVM堆内存:24G(3/4)
操作系统+JVM堆外内存:8G(1/4) -- 保存系统稳定运行
配置信息如下
hbase_regionserfver_opts -Xmx24g -Xms24g -Xmn6g
#Xmx - 设定程序启动时占用堆内存大小
#Xms - 设定程序运行期间最大可占用的内存大小(超出为OOM)
#Xmn - 年轻代大小
G1垃圾回收器能有效的降低JVM full CG的次数。
-XX: +UseG1GC #配置G1垃圾回收,JDK升级到11(jdk8不支持)
-XX: MaxGCPauseMillis = 500
-XX: +ParalleRefProcEnabled
-XX: -ResizePLAB
-XX: +ParalleGCThreads=8
-Xloggc: /data/log/hbase/gc/gc-%t.log
-XX: +PrintGCDetails
-XX: +PrintGCTimeStamps
-XX: +PrintGCCause
-XX: +PrintTenuringDistribution
-XX: +UseGCLogFileRotation
-XX: NumberOfGCLogFile=20
-XX: GCLogFileSize=5M
和CPU计算资源相关

负载所有的compaction请求,当文件compaction总大小>(大于)throttlePoint,则compation分配给largeCompaction线程池,否则由smallCompaction线程池处理。
具体配置
# 配置throttlePoint,默认为2.5G
hbase.regionserver.thread.compaction.throttlePoint: 2.5G
# smallCompaction和largeCompaction线程池默认都只有1个线程
hbase.regionserver.thread.compaction.small: 4
hbase.regionserver.thread.compaction.large: 6
数据写入流程,数据合并与分裂的基本流程。

先写入Memstore,超过阀值,写入StoreFile(HFile), 超过阀值,启动compaction,合并为一个StoreFile,当合并后的StoreFile大于hbase.regionserver.max.filesize所设置的参数时,会触发分裂动作,拆分为两个region
hbase.regionserver.max.filesize的需大小适中。当filesize太小,则触发分裂的机率更大,系统整体访问服务会出现不稳定现象。当filesize太大,一次compaction 与split所需要的时间会较长,甚至产生停顿感,太大不适合常 compaction 与split,对应用读写冲击较大。
实战经验,高并发情况下,最佳大小是5~10G
# 参数的设置和单条数据的大小,和Region个数有关
# 参数调优必选项
hbase.regionserver.max.filesize 10G
关闭hbase表的major_compact是为避免major_compact对系统性能的影响。非高峰时期时,再调用major_compact对hbase表进行大合并,可减少split时间极大的提升集群性能和吞吐量。
语句如下,
major_compact 'table_name'
regionserver cache的大小,
#表示占hbase整个堆内存的0.2
hfile.block.cache.size 0.2
往大的调,会提升查询性能;大量查询为主,写入频率不高的情况下,设置为0.5即可.
一个regionserver默认的memstore的大小,默认为64MB。参考平均每个regionserver管理的region数量,如果管理量不大,可适当往大调整,如下:
hfile.hregion.memstore.flush.size 512MB
hfile.regionserver.global.memstore.upperLimit
hfile.regionserver.global.memstore.lowerLimit
upperLimit与lowerLimit指定memStore总使用内存大小百分比。upperLimit 开始刷盘百分比,lowerLimit 停止刷盘百分比。

读取频繁写入不频繁:适当调小,让更多内存让给查询缓存。
hfile.regionserver.global.memstore.upperLimit 6 #开始刷盘
hfile.regionserver.global.memstore.lowerLimit 4 #停止刷盘
指定Rowkey规则
Region预分区
开启数据压缩
监控报警
不合理的规则,会造成regionserver上的数据不均匀,造成数据倾斜,进行让某一个regionserver过热。
1、尽量保存Rowkey随机性

2、预创建分区
create 't1','f1',SPLITS_FILE => 'splits.txt';
预先根据可能的RowKey划分出多个Region而 不是一个,从而可以将后续的多个操作均衡到不同的Region上,避免热点现象的产生。
Hbase存储的数据以PB级别为主,将造成服务器磁盘费用过高。
create 'test',{NAME -> 'C', COMPRESSION => 'SNAPPY'};
Hbase默认的压缩算法有: GZ、LZO以及snappy,其中snappy算法其压缩率与性能最优。
安装Cloudera 监控对Hbase实时状态进行监控。
使用带有Rails插件的vim,您可以创建一个迁移文件,然后一次性打开该文件吗?textmate也可以这样吗? 最佳答案 你可以使用rails.vim然后做类似的事情::Rgeneratemigratonadd_foo_to_bar插件将打开迁移生成的文件,这正是您想要的。我不能代表textmate。 关于ruby-使用VimRails,您可以创建一个新的迁移文件并一次性打开它吗?,我们在StackOverflow上找到一个类似的问题: https://sta
我需要从一个View访问多个模型。以前,我的links_controller仅用于提供以不同方式排序的链接资源。现在我想包括一个部分(我假设)显示按分数排序的顶级用户(@users=User.all.sort_by(&:score))我知道我可以将此代码插入每个链接操作并从View访问它,但这似乎不是“ruby方式”,我将需要在不久的将来访问更多模型。这可能会变得很脏,是否有针对这种情况的任何技术?注意事项:我认为我的应用程序正朝着单一格式和动态页面内容的方向发展,本质上是一个典型的网络应用程序。我知道before_filter但考虑到我希望应用程序进入的方向,这似乎很麻烦。最终从任何
我想要做的是有2个不同的Controller,client和test_client。客户端Controller已经构建,我想创建一个test_clientController,我可以使用它来玩弄客户端的UI并根据需要进行调整。我主要是想绕过我在客户端中内置的验证及其对加载数据的管理Controller的依赖。所以我希望test_clientController加载示例数据集,然后呈现客户端Controller的索引View,以便我可以调整客户端UI。就是这样。我在test_clients索引方法中试过这个:classTestClientdefindexrender:template=>
如果您尝试在Ruby中的nil对象上调用方法,则会出现NoMethodError异常并显示消息:"undefinedmethod‘...’fornil:NilClass"然而,有一个tryRails中的方法,如果它被发送到一个nil对象,它只返回nil:require'rubygems'require'active_support/all'nil.try(:nonexisting_method)#noNoMethodErrorexceptionanymore那么try如何在内部工作以防止该异常? 最佳答案 像Ruby中的所有其他对象
关闭。这个问题需要detailsorclarity.它目前不接受答案。想改进这个问题吗?通过editingthispost添加细节并澄清问题.关闭8年前。Improvethisquestion为什么SecureRandom.uuid创建一个唯一的字符串?SecureRandom.uuid#=>"35cb4e30-54e1-49f9-b5ce-4134799eb2c0"SecureRandom.uuid方法创建的字符串从不重复?
我有一个正在构建的应用程序,我需要一个模型来创建另一个模型的实例。我希望每辆车都有4个轮胎。汽车模型classCar轮胎模型classTire但是,在make_tires内部有一个错误,如果我为Tire尝试它,则没有用于创建或新建的activerecord方法。当我检查轮胎时,它没有这些方法。我该如何补救?错误是这样的:未定义的方法'create'forActiveRecord::AttributeMethods::Serialization::Tire::Module我测试了两个环境:测试和开发,它们都因相同的错误而失败。 最佳答案
我想在Ruby中创建一个用于开发目的的极其简单的Web服务器(不,不想使用现成的解决方案)。代码如下:#!/usr/bin/rubyrequire'socket'server=TCPServer.new('127.0.0.1',8080)whileconnection=server.acceptheaders=[]length=0whileline=connection.getsheaders想法是从命令行运行这个脚本,提供另一个脚本,它将在其标准输入上获取请求,并在其标准输出上返回完整的响应。到目前为止一切顺利,但事实证明这真的很脆弱,因为它在第二个请求上中断并出现错误:/usr/b
我想让一个yaml对象引用另一个,如下所示:intro:"Hello,dearuser."registration:$introThanksforregistering!new_message:$introYouhaveanewmessage!上面的语法只是它如何工作的一个例子(这也是它在thiscpanmodule中的工作方式。)我正在使用标准的rubyyaml解析器。这可能吗? 最佳答案 一些yaml对象确实引用了其他对象:irb>require'yaml'#=>trueirb>str="hello"#=>"hello"ir
我的问题的一个例子是体育游戏。一场体育比赛有两支球队,一支主队和一支客队。我的事件记录模型如下:classTeam"Team"has_one:away_team,:class_name=>"Team"end我希望能够通过游戏访问一个团队,例如:Game.find(1).home_team但我收到一个单元化常量错误:Game::team。谁能告诉我我做错了什么?谢谢, 最佳答案 如果Gamehas_one:team那么Rails假设您的teams表有一个game_id列。不过,您想要的是games表有一个team_id列,在这种情况下
Region是HBase数据管理的基本单位,region有一点像关系型数据的分区。region中存储这用户的真实数据,而为了管理这些数据,HBase使用了RegionSever来管理region。Region的结构hbaseregion的大小设置默认情况下,每个Table起初只有一个Region,随着数据的不断写入,Region会自动进行拆分。刚拆分时,两个子Region都位于当前的RegionServer,但处于负载均衡的考虑,HMaster有可能会将某个Region转移给其他的RegionServer。RegionSplit时机:当1个region中的某个Store下所有StoreFile