Hadoop SequenceFile 详解

Hadoop中有两种基本的文件类型, 一个是SequenceFile, 一个MapFile

他们通过底层 I/O接口 FSDataOutputStream 来进行写入, 对外操作起来就像普通的文件操作.

两者的相同之处在于都存放了很多键值对

两者的不同在于MapFile是SequenceFile的升级版, 它总是根据key来排序, 支持通过key来查讯value

而SequenceFile的读取则是从第一个键值对一个一个往下读, 直到返回空值, 有点象读数据库的感觉.


SequenceFile的一个特点在在于有一个sync_maker, 这个sync_maker帮助SequenceFile型文件支持随机读取.

在未压缩的SequenceFile的文件结构是

  • Header

  • Record
    • Record length
    • Key length
    • Key
    • (Compressed?) Value
  • A sync-marker every few k bytes or so.

sync_maker的结构和生成如下:

    byte[] sync;                          // 16 random bytes
    {
      try {                                       
        MessageDigest digester = MessageDigest.getInstance("MD5");
        long time = Time.now();
        digester.update((new UID()+"@"+time).getBytes());
        sync = digester.digest();
      } catch (Exception e) {
        throw new RuntimeException(e);
      }
    }
    public void sync() throws IOException {
      if (sync != null && lastSyncPos != out.getPos()) {
        out.writeInt(SYNC_ESCAPE);                // mark the start of the sync
        out.write(sync);                          // write sync
        lastSyncPos = out.getPos();               // update lastSyncPos
      }
    }

在SequenceFile的header里会存放一个sync_maker的值, 指的就是head最后会有一个sync_marker

SequenceFile文件支持从文件的任意位置开始随机读取, 就是通过在文件的字节流里找这个全局唯一的sync_marker

所以SequenceFileRead里的sync函数是这样定义的:

sync

public void sync(long position)
          throws IOException
Seek to the next sync mark past a given position.

Throws:
IOException

实现逻辑是从任意位置找起,然后寻找和sync_marker一样的bytes[]

    public synchronized void sync(long position) throws IOException {
      if (position+SYNC_SIZE >= end) {
        seek(end);
        return;
      }

      if (position < headerEnd) {
        // seek directly to first record
        in.seek(headerEnd);
        // note the sync marker "seen" in the header
        syncSeen = true;
        return;
      }

      try {
        seek(position+4);                         // skip escape
        in.readFully(syncCheck);
        int syncLen = sync.length;
        for (int i = 0; in.getPos() < end; i++) {
          int j = 0;
          for (; j < syncLen; j++) {
            if (sync[j] != syncCheck[(i+j)%syncLen])
              break;
          }
          if (j == syncLen) {
            in.seek(in.getPos() - SYNC_SIZE);     // position before sync
            return;
          }
          syncCheck[i%syncLen] = in.readByte();
        }
      } catch (ChecksumException e) {             // checksum failure
        handleChecksumException(e);
      }
    }


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

爱知菜

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值