HBase的Write Ahead Log (WAL)
HBase的Write Ahead Log (WAL)
一、预写日志WAL(Write-Ahead-Log)
HBase的Write Ahead Log (WAL)提供了一种高并发、持久化的日志保存与回放机制。每一个业务数据的写入操作(PUT / DELETE)执行前,都会记账在WAL中。
WAL(Write-Ahead-Log)是HBase的RegionServer在处理数据插入和删除的过程中用来记录操作内容的一种日志。大致过程如下图所示,首先客户端启动一个操作来修改数据,每一个修改都封装到KeyValue对象实例中,并通过RPC调用发送到含有匹配Region的HRegionServer。一旦KeyValue到达,它们就会被发送管理相应行的HRegion实例。数据被写到WAL,然后被放入到实际拥有记录的存储文件的MemStore中。同时还会检查MemStore是否满了,如果满了就会被刷写到磁盘中去。
默认是每个RegionServer有1个WAL,在HBase1.0开始支持多个WALHBASE-5699,这样可以提高写入的吞吐量。配置参数为hbase.wal.provider=multiwal,支持的值还有defaultProvider和filesystem(这2个是同样的实现)。
WAL的持久化的级别有如下几种:
SKIP_WAL:不写wal日志,这种可以较大提高写入的性能,但是会存在数据丢失的危险,只有在大批量写入的时候才使用(出错了可以重新运行),其他情况不建议使用。
ASYNC_WAL:异步写入
SYNC_WAL:同步写入wal日志文件,保证数据写入了DataNode节点。
FSYNC_WAL: 目前不支持了,表现是与SYNC_WAL是一致的
USE_DEFAULT: 如果没有指定持久化级别,则默认为USE_DEFAULT, 这个为使用HBase全局默认级别(SYNC_WAL)
HBase的Write Ahead Log (WAL)提供了一种高并发、持久化的日志保存与回放机制。每一个业务数据的写入操作(PUT / DELETE)执行前,都会记账在WAL中。
如果出现HBase服务器宕机,则可以从WAL中回放执行之前没有完成的操作。
HLog
HLog是实现WAL的类。一个HRegionServer对应一个HLog实例。当HRegion初始化时,HLog将作为一个参数传给HRegion的构造函数。
HLog最核心的是调用doWrite的append() 方法,前面提到的可能对数据改动的操作都就将首先调用这个方法。出于性能的考虑,put(), delete() 和incrementColumnValue()有一个开关函数setWriteToWAL(boolean) , 设为false将禁用WAL。这是为什么上图中向下的箭头是虚线的原因。默认时候当然需要WAL,但是假如你运行一个数据导入的MapReduce Job,你可以通过关闭WAL获得性能上的提升。
另一个重要的特性是HLog将通过“sequence number”追踪数据改变。它内部使用AtomicLong保证线程安全。sequence number的起始值为0,或者是最近一次存入文件系统中sequence number。Region打开存储文件,读取每个HFile中的最大的sequence number,如果该值大于HLog 的sequence number, 就将它作为HLog 的sequence number的值。最后,HLog将得到上次存入文件和继续记log的点。
上图表示了3个不同的region,每一个负责一段rowkey的范围。这些region将共享同一个HLog实例,我们可以看出,从不同region来的数据写入WAL的顺序是不确定的。在后面我们会再详细的介绍。
最后,Hlog利用HMaster恢复和切分一个由一个崩溃的HRegionServery遗留下来的Log。之后,重新部署regions。
HLogKey
WAL使用Hadoop的SequenceFile,它将记录存储为key/values 的数据集。对于WAL,key是一个HLogKey的实例。KeyValue不仅包括row,column family, qualifier, timestamp, value, 还包括“Key Type”—派上用场啦, 这里,可以用Key Type代表一个“put”或“delete”操作。
但是,哪里去存放KeyValue的归属信息,比如region或者表名呢?这些存放在HLogKey中。同时还包括 sequence number,和“写入时间”, 是一个记录数据何时写入到log的时间戳。
LogFlusher
数据以KeyValue形式到达HRegionServer,将写入WAL,之后,写入一个SequenceFile。看过去没问题,但是因为数据流在写入文件系统时,经常会缓存以提高性能。这样,有些本以为在日志文件中的数据实际在内存中。这里,我们提供了一个LogFlusher的类。它调用HLog.optionalSync(),后者根据“hbase.regionserver.optionallogflushinterval”(默认是10秒),定期调用Hlog.sync()。另外,HLog.doWrite()也会根据“hbase.regionserver.flushlogentries”(默认100秒)定期调用Hlog.sync()。Sync() 本身调用HLog.Writer.sync(),它由SequenceFileLogWriter实现。
LogRoller
Log的大小通过$HBASE_HOME/conf/hbase-site.xml 的“hbase.regionserver.logroll.period”限制,默认是一个小时。所以每60分钟,会打开一个新的log文件。久而久之,会有一大堆的文件需要维护。首先,LogRoller调用HLog.rollWriter(),定时滚动日志,之后,利用HLog.cleanOldLogs()可以清除旧的日志。它首先取得存储文件中的最大的sequence number,之后检查是否存在一个log所有的条目的“sequence number”均低于这个值,如果存在,将删除这个log。
Replay
当HRegionServer启动,打开所管辖的region,它将检查是否存在剩余的log文件,如果存在,将调用Store.doReconstructionLog()。重放一个日志只是简单地读入一个日志,将日志中的条目加入到Memstore中。最后,flush操作将Memstore中数据flush到硬盘中。
旧日志往往由region server 崩溃所产生。当HMaster启动或者检测到region server 崩溃,它将日志文件拆分为多份文件,将其存储在region所属的文件夹。之后,根据上面提到的方法,将日志重放。需要指出的是,崩溃的服务器中的region只有在日志被拆分和拷贝之后才能被重新分配。拆分日志利用HLog.splitLog()。旧日志被读入主线程内存中,之后,利用线程池将其写入所有的region文件夹中,一个线程对应于一个region。
问题
为什么要一个RegionServer 对应于一个HLog。为什么不是一个region对应于一个log file?
如果我们每一个“tablet”(对应于HBase的region)都提交一个日志文件,会需要并发写入大量的文件到GFS,这样,根据每个GFS server所依赖的文件系统,写入不同的日志文件会造成大量的磁盘操作。
HBase依照这样的原则。在日志被回滚和安全删除之前,将会有大量的文件。如果改成一个region对应于一个文件,将会不好扩展,迟早会引发问题。
二、WAL的写入
与WAL相关的几个主要类:
- WALKey: wal日志的key,包括 regionName: 日志所属的region tablename:日志所属的表,writeTime:日志写入时间,clusterIds:cluster的id,在数据复制的时候会用到。
- WALEdit: 在hbase的事务日志中记录一系列的修改的一条事务日志。另外WALEdit实现了Writable接口,可用于序列化处理。
- FSHLog: WAL的实现类,负责将数据写入文件系统
对每个wal的写入使用的是多生产者单消费者的模式,这里使用到了disruptor框架,将WALKey和WALEdit信息封装为FSWALEntry,然后通过RingBufferTruck放入RingBuffer中。
接下来看hlog的写入流程,分为以下3步:
日志写入缓存:由rpcHandler将日志信息写入缓存ringBuffer.
缓存数据写入文件系统:每个FSHLog有一个线程负责将数据写入文件系统(HDFS)
数据同步:如果操作的持久化级别为(SYNC_WAL或者USE_DEFAULT 则需进行数据同步处理
各类线程是如何配合来实现这几步操作的:
rpcHandler线程负责将日志信息(FSWALEntry)写入缓存RingBbuffer,在操作日志写完后,rpcHandler会调用wal的sync方法,进行数据同步,其实际处理为写入一个SyncFuture到RingBuffer,然后blocking一直到syncFuture处理完成。
wal线程从缓存RingBuffer中取数据,如果为日志(FSWALEntry)就调用Writer将数据写入文件系统,如果为SyncFuture,则由专门的同步线程来进行同步处理。
三、相关博文
CSDN(Kuzury):HBase WAL 解析
博客园( Yijian):HBase的Write Ahead Log (WAL) —— 整体架构、线程模型
简书(牦牛sheriff):05. HBase WAL解析
HBase的Write Ahead Log (WAL)的更多相关文章
- HBase的Write Ahead Log (WAL) —— 整体架构、线程模型
解决的问题 HBase的Write Ahead Log (WAL)提供了一种高并发.持久化的日志保存与回放机制.每一个业务数据的写入操作(PUT / DELETE)执行前,都会记账在WAL中. 如果出 ...
- HBase的Write Ahead Log (WAL) —— 整体架构、线程模型【转】
转自:http://www.cnblogs.com/ohuang/p/5807543.html 解决的问题 HBase的Write Ahead Log (WAL)提供了一种高并发.持久化的日志保存与回 ...
- HBase的Write Ahead Log (WAL) —— API与基本概念
HBase的数据写入操作,会先记录到HLog中,再真正写入到MemStore中.前者是对写入友好的格式,后者是对查询友好的格式.所以前者吞吐量更高,写入成功率大,提高了系统的可靠性,“基本”可以实现宕 ...
- RocksDB 之Write Ahead Log(WAL)
Overview RocksDB 中有三个基本的数据结构概念:memtable, sstfile 和 logfile memtable 是个内存数据结构,新写入会插入memtable 切回选择性地写入 ...
- SparkStreaming “Could not read data from write ahead log record” 报错分析解决
# if open wal org.apache.spark.SparkException: Could not read data from write ahead log record FileB ...
- HBase源码分析之WAL
WAL(Write-Ahead Logging)是数据库系统中保障原子性和持久性的技术,通过使用WAL可以将数据的随机写入变为顺序写入,可以提高数据写入的性能.在hbase中写入数据时,会将数据写入内 ...
- Hbase记录-Hbase shell使用命令
1.进入hbase shell 执行./bin/hbase shell 2.进入后,help 帮助信息,如可以使用help 'create' 3.创建表:create 'test','cf' 表 ...
- hbase官方文档(转)
FROM:http://www.just4e.com/hbase.html Apache HBase™ 参考指南 HBase 官方文档中文版 Copyright © 2012 Apache Soft ...
- HBase 官方文档
HBase 官方文档 Copyright © 2010 Apache Software Foundation, 盛大游戏-数据仓库团队-颜开(译) Revision History Revision ...
随机推荐
- python-scrapy爬取某招聘网站信息(一)
首先准备python3+scrapy+mysql+pycharm... 这次我们选择爬取智联招聘网站的企业招聘信息,首先我们有针对的查看网站的html源码,发现其使用的是js异步加载的方式,直接从服务 ...
- json 与 ajax
json类似与js中的对象,但是json中不能有方法,json相当于python中的字典,但是json中的键值如果是字符串的话,需要加上双引号:ajax是一个前后台配合的技术,它可以让js发送http ...
- TurtleBot3 Waffle (tx2版华夫)(6)
重要提示:请在配网通信成功后进行操作,配网后再次开机需要重新验证通信: 重要提示:[Remote PC]代表PC端.[TurtelBot]代表树莓派端: 操作步骤如下: 1)[Remote PC] 启 ...
- java中变量和标识符名命名规范
变量存放的是内存地址,当定义一个变量后,我们可以通过变量名找到该内存地址,可以修改该内存区间的值. 标识符的命名规范:首字母:字母,下划线,$符号:其余部分:数字,字母,下划线,$. 标识符应该避开j ...
- Kubernetes官方java客户端之三:外部应用
欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java.Docker.Kubernetes.DevOPS ...
- [学习笔记]尝试go-micro开发微服务<第一波>
平时项目都是基于c++,lua,node, 现在打算开始自学开发微服务; 也顺带磨砺下go和docker 前期准备 1. 有golang编程基础 本系列文章是基于有golang编程基础,有过实际开 ...
- 风炫安全Web安全学习第十节课 数字型的Sql注入
数字型的Sql注入 风炫安全Web安全学习第十一节课 字符型和搜索型的sql注入 风炫安全Web安全学习第十二节课 mysql报错函数注入 风炫安全Web安全学习第十三节课 CUD类型的sql注入 风 ...
- 【Redis3.0.x】NoSql 入门
Redis3.0.x NoSql 入门 概述 NoSQL(Not Only SQL ),即不仅仅是 SQL,泛指非关系型的数据库.NoSQL 数据库的产生就是为了解决大规模数据集合多重数据种类带来的挑 ...
- 如何在 Vite 中使用 Element UI + Vue 3
在上篇文章<2021新年 Vue3.0 + Element UI 尝鲜小记>里,我们尝试使用了 Vue CLI 创建 Vue 3 + Element UI 的项目,而 Vue CLI 实际 ...
- show engine innodb status
TRANSACTIONS------------Trx id counter 2003909(当前事务号)Purge done for trx's n:o < 2003905 (清理线程完成到了 ...