Kahadb设计思想

 

简介

  • hakadb是activemq的持久化数据库,作为消息队列的存储,每个消息有一个消息ID,提供了对消息的快速的查找,更新,以及消息的事物支持,以及意外磬机之后的恢复。丰富的功能决定了他在存储结构上与redis中简单的双端队列不同。
 

kahadb三大部分

  • 主要由索引(B-Tree Index),数据(PageFile),日志(Journal)组成。为了实现消息的快速定位更新,通过b-tree来索引数据,主要对应目录中的;为了数据的写入效率,数据都是顺序存储在文件中,这部分工作被抽象到了PageFile类;Journal负责了操作日志,用于写入和恢复最终都是决定与Journal
 

kahadb之Journal

 

核心类

 

Journal 读写日志的facade

  • write方法,向日志系统写入日志。返回Location。
  • read方法,根据Location从之日系统中读取日志
 

Location 日志系统中定位日志Record

  • 由日志的DataFileId,offset,size,type组成,用来定位日志
 

DataFile 日志文件的存储文件

日志都存储在db-{1,2,3,...n}.log文件中,每个这个文件都由DataFile类来封装,其中1,2,3..就是DataFileId,还有一些长度和文件指针的信息

 

DataFileAppender 多线程下优化了批量写入

  • 两个线程,一个队列,把并发写变成批量单线程写入,具体实现略
 

DataFileAccessorPool和DataFileAccessor

  • 封装了对日志的读操作,暂时略,对理解整体结构没有大的影响。
 

读写实例

 
  1. File dir = new File("target/tests/Test");
  2. dir.mkdirs();
  3. Journal dataManager = new Journal();
  4. dataManager.setDirectory(dir);
  5. dataManager.start();
  6. //写入日志
  7. ByteSequence write = new ByteSequence("Hello world".getBytes());
  8. Location location = dataManager.write(write, true);
  9. //读取日志
  10. ByteSequence read = dataManager.read(location);
  11. System.out.println(new String(read.data));
 

存储结构

  • 由头部28个字节,和数据组成
 

头部

  • 四个字节Journal.BATCH_CONTROL_RECORD_SIZE, 固定的28
  • 一个字节Journal.BATCH_CONTROL_RECORD_TYPE, 2
  • 十一个字节,字符串 Journal.BATCH_CONTROL_RECORD_MAGIC, WRITE BATCH 这几个字节
  • 四个字节记录批量写入了多少批的BATCH_SIZE ,不固定的int
  • 八个字节校验和,后半部分写入日志的校验和
 

数据

  • 四个字节的size,这个size是数据头部的长度+数据的长度
  • 一个字节数据类型
  • 若干字节的数据
 

日志文件的RecoveryCheck

  • 在第一次加载日志文件的时候会做一次Recovery,主要是恢复一些上次写入的Offset,知道了存储结构以后其实按照这个结构读写就可以找到最后一次写的Offset,但是假如日志写入一半失败到了,导致部分存储结构不整齐了,但后续是好的,理想情况应该跳过这些坏的部分,让后面的可用。Recovery的时候对这种情况会重新在文件里搜索日志的头部的前16字节,不知为何是要搜这头部,搜到以后就把之前搜索过的区域标记为corruptedBlocks
 

kahadb之PageFile

 

核心类

 

PageFile

PageFile负责了消息的持久化存储。PageFile对外的主要接口有删除数据库,载入数据库,生成一个用于读写的Transaction,数据被存储在了

 

Page

PageFile如果是用于存储数据的文件,Page就是文件中的每一小段,为了减少IO,每个文件被分成4K大小的段,是一个Page。至于为什么4K大小可以减少磁盘IO的原因是,当用户程序请求要读1K的数据时候,操作系统会预读更多的数据,放到内核缓冲中,因为内核中的缓冲一页的大小是4K,所以应用程序一般都会和操作系统的PageCache对齐,这样充分利用操作系统的PageCache。Page最重要的一个属性是PageId,这个Id是在一个PageFile中顺序排列的,所以根据这个PageId就可以定位到PageFile文件中的Offset。

 

Transaction

Transaction负责了创建Page,在Page上读写,提交以及回滚操作

 

读写实例

 
  1. File dir = new File("target/tests/Test");
  2. dir.mkdirs();
  3. PageFile pf = new PageFile(dir, "myfile");
  4. pf.load();
  5. //写入
  6. Transaction tx = pf.tx();
  7. Page<String> page = tx.allocate();
  8. page.set("Hello world");
  9. tx.store(page, StringMarshaller.INSTANCE, true);
  10. tx.commit();
  11. pf.unload();
  12. pf.load();
  13. //读取
  14. tx = pf.tx();
  15. tx.load(page.getPageId(), StringMarshaller.INSTANCE);
  16. String hello = page.get();
 

存储结构

  • 存储的时候包括{dbname}.data和{dbname}.redo {dbname}.free文件。data文件是保存真正消息的文件。当data文件META信息中的cleanShutdown为false的时候会通过redo文件来做recovery。
 

.data文件

 

头部

  • 4K的第一页存放META信息
  • META初始信息如下
 
  1. fileType=org.apache.activemq.store.kahadb.disk.page.PageFile
  2. pageSize=4096
  3. freePages=-1
  4. cleanShutdown=true
  5. metaDataTxId=0
  6. fileTypeVersion=1
  7. lastTxId=0
  • 需要说明一点的是这个信息在第一页中存储了两遍
 

BODY部分

  • 一个字节的type 固定的是2
  • 八个字节的transactionId
  • 八个字节的下一个记录的位置
  • 四个字节的校验和,不过是个保留字节,没什么用
  • N个字节真正的数据
 

.redo文件

 

头部

  • 八个字节的下一个TX的id 存储在第一页
  • 八个字节的校验和 存储在第一页
  • 四个字节的当前这个写入的记录数量 存储在第一页
 

BODY部分

  • 8个字节PageId
  • page数据与data文件中的body部分相同
  • pageId和page数据是一页的大小4K
 

PageFile的多级缓存

  • 可以看到当写入数据的时候分配新的Page,Page写入磁盘是比较消耗IO的,所以在一个Transaction上有一个freeList来保存空的Page,在PageFile也有freeList来加速新分配Page。同时为了加快读写Page的速度,PageFile中有一个PageCache
 

事物的回滚

  • 事物只有在commit的时候才会调用PageFile的write方法,Transaction中的store只是把他逻辑保存在Transaction中,但是回滚的时候要把PageFile中申请的Page归还到freeList

kahadb设计的更多相关文章

  1. kafka系列教程2(设计构造及原理1)

    kafka采用了一些非主流(unconventional)并经过实践的设计使其高效和可扩展.在实际使用中kafka显示出了相对于常见流行的消息系统的优越性.并且每天能够处理上百GB的新的数据.   类 ...

  2. KahaDB简介

    ActiveMQ 5.3以后,出现了KahaDB.她是一个基于文件支持事务的消息存储器,是一个可靠,高性能,可扩展的消息存储器.     她的设计初衷就是使用简单并尽可能的快.KahaDB的索引使用一 ...

  3. 如何一步一步用DDD设计一个电商网站(九)—— 小心陷入值对象持久化的坑

    阅读目录 前言 场景1的思考 场景2的思考 避坑方式 实践 结语 一.前言 在上一篇中(如何一步一步用DDD设计一个电商网站(八)—— 会员价的集成),有一行注释的代码: public interfa ...

  4. 如何一步一步用DDD设计一个电商网站(八)—— 会员价的集成

    阅读目录 前言 建模 实现 结语 一.前言 前面几篇已经实现了一个基本的购买+售价计算的过程,这次再让售价丰满一些,增加一个会员价的概念.会员价在现在的主流电商中,是一个不大常见的模式,其带来的问题是 ...

  5. 设计爬虫Hawk背后的故事

    本文写于圣诞节北京下午慵懒的午后.本文偏技术向,不过应该大部分人能看懂. 五年之痒 2016年,能记入个人年终总结的事情没几件,其中一个便是开源了Hawk.我花不少时间优化和推广它,得到的评价还算比较 ...

  6. 如何一步一步用DDD设计一个电商网站(十)—— 一个完整的购物车

     阅读目录 前言 回顾 梳理 实现 结语 一.前言 之前的文章中已经涉及到了购买商品加入购物车,购物车内购物项的金额计算等功能.本篇准备把剩下的购物车的基本概念一次处理完. 二.回顾 在动手之前我对之 ...

  7. 如何一步一步用DDD设计一个电商网站(一)—— 先理解核心概念

    一.前言     DDD(领域驱动设计)的一些介绍网上资料很多,这里就不继续描述了.自己使用领域驱动设计摸滚打爬也有2年多的时间,出于对知识的总结和分享,也是对自我理解的一个公开检验,介于博客园这个平 ...

  8. 如何一步一步用DDD设计一个电商网站(七)—— 实现售价上下文

    阅读目录 前言 明确业务细节 建模 实现 结语 一.前言 上一篇我们已经确立的购买上下文和销售上下文的交互方式,传送门在此:http://www.cnblogs.com/Zachary-Fan/p/D ...

  9. 如何一步一步用DDD设计一个电商网站(六)—— 给购物车加点料,集成售价上下文

    阅读目录 前言 如何在一个项目中实现多个上下文的业务 售价上下文与购买上下文的集成 结语 一.前言 前几篇已经实现了一个最简单的购买过程,这次开始往这个过程中增加一些东西.比如促销.会员价等,在我们的 ...

随机推荐

  1. Axis 生成客户端client stub文件

    [转自] http://blog.csdn.net/qiao000_000/article/details/5568442 开发前,有个同事先给我们不熟悉Web Service的程序员进行了一些培训, ...

  2. naginx安装入门

    一.nginx是什么 nginx是一个开源的,支持高性能,高并发的www服务和代理服务软件.它是一个俄罗斯人lgor sysoev开发的,作者将源代码开源出来供全球使用. nginx比它大哥apach ...

  3. PIE SDK矢量数据的查询

    1.功能简介 矢量数据查询有属性查询和空间几何查询,下面对矢量数据的属性查询和空间查询做介绍 2.功能实现说明 2.1. 矢量数据的属性和空间查询 2.2. 实现思路及原理说明 第一步 得到要查询的图 ...

  4. git和svn有什么区别

    如果你在读这篇文章,说明你跟大多数开发者一样对GIT感兴趣,如果你还没有机会来试一试GIT,我想现在你就要了解它了. GIT不仅仅是个版本控制系统,它也是个内容管理系统(CMS),工作管理系统等.如果 ...

  5. http请求报头和响应报头(1)

    1.web端不可避免的http缓存机制,要理解缓存机制,先来了解下http的请求报文和响应报文的内容 2.请求报文  2.1请求行    请求行三部分组成:请求方法.URL以及版本协议 请求的方法有G ...

  6. spark第二篇:Application Submission Guide

    提交应用 Spark的bin目录中的spark-submit脚本用于启动集群上的应用程序.它可以通过一个统一的接口使用所有Spark支持的集群管理器. 绑定应用程序的依赖 如果你的代码依赖其他项目,你 ...

  7. shell 操作符详解

     = 赋值操作符,可以用于算术和字符串赋值 +  加法计算   -  减法运算 *  乘法运算 /   除法运算 **  幂运算 % 模运算 取他除后的剩余数   因此这个十分好求公约数 += &qu ...

  8. bind-named

    main-book: http://www.zytrax.com/books/dns resolv.conf: http://dns-learning.twnic.net.tw/bind/intro4 ...

  9. 实现Docker跨主机间的容器网络联通

    Server1(Server) 192.168.81.58 内核版本 3.10.0-123.el7.x86_64 Docker版本 1.12.6Server2(Agent)  192.168.81.5 ...

  10. Hadoop Ecosytem

    There are a lot of Hadoop related projects which are open sourced and widely used by many componies. ...