分享
  1. 首页
  2. 文章

NSQ 源码阅读 (四) diskqueue 文件读写

buptztd · · 1951 次点击 · · 开始浏览
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

引言

我们在这个系列第一篇文章中提到过,如果需要消息落地而对存储子系统的选择上,从速度上来说 文件系统>分布式KV(持久化)>分布式文件系统>数据库。而NSQ选择了文件系统作为存储子系统。这篇文章将重点介绍nsq 对于文件的操作。

何时写入文件?

在内存的msg chan buffer 已满的时候,会将msg 写入文件,代码如下:

func (c *Channel) put(m *Message) error {
 select {
 case c.memoryMsgChan <- m:
 default:
 b := bufferPoolGet()
 err := writeMessageToBackend(b, m, c.backend)
 bufferPoolPut(b)
 c.ctx.nsqd.SetHealth(err)
 if err != nil {
 c.ctx.nsqd.logf(LOG_ERROR, "CHANNEL(%s): failed to write message to backend - %s",
 c.name, err)
 return err
 }
 }
 return nil
}

写一条message

func (d *diskQueue) writeOne(data []byte) error {

diskQueue维护了写文件和写文件的offset

// diskQueue implements a filesystem backed FIFO queue
type diskQueue struct {
 ...
 writePos int64
 ...
 writeFile *os.File
 ...
}

利用Seek 函数将写文件的偏移量设置为writePos:

 if d.writePos > 0 {
 _, err = d.writeFile.Seek(d.writePos, 0)

然后以二进制的方式写入data的size:

dataLen := int32(len(data))
d.writeBuf.Reset()
err = binary.Write(&d.writeBuf, binary.BigEndian, dataLen)

此处的巧妙在于binary.Write会根据写入数据的类型写入一段固定大小的数据。此处dataLen 是int32,所以会写入一段4个byte的数据来表示data的size。读取的时候先读一段4个byte的数据就知道了data的size。
之后写入data:

_, err = d.writeBuf.Write(data)
_, err = d.writeFile.Write(d.writeBuf.Bytes())

读一条message

readOne函数以byte 数组的形式读一条message 出来

func (d *diskQueue) readOne() ([]byte, error) {

diskQueue 维护了当前读取的文件和文件的offset

// diskQueue implements a filesystem backed FIFO queue
type diskQueue struct {
readPos int64
...
readFile *os.File

利用Seek 函数将当前文件的偏移量设置为readPos:

 if d.readPos > 0 {
 _, err = d.readFile.Seek(d.readPos, 0)
 if err != nil {
 d.readFile.Close()
 d.readFile = nil
 return nil, err
 }
 }

先把一个message的大小读出来:

err = binary.Read(d.reader, binary.BigEndian, &msgSize)

msgSize 和写文件时候的dataLen都是int32类型
有了msgSize, 定义一段msgSize大小的buffer,从文件里读一段数据来填满这个buffer,buffer里面的数据就是一条message

 readBuf := make([]byte, msgSize)
 _, err = io.ReadFull(d.reader, readBuf)

有疑问加站长微信联系(非本文作者)

本文来自:Segmentfault

感谢作者:buptztd

查看原文:NSQ 源码阅读 (四) diskqueue 文件读写

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

关注微信
1951 次点击
1 回复 | 直到 2025年05月15日 08:33:15
暂无回复
添加一条新回复 (您需要 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传

用户登录

没有账号?注册
(追記) (追記ここまで)

今日阅读排行

    加载中
(追記) (追記ここまで)

一周阅读排行

    加载中

关注我

  • 扫码关注领全套学习资料 关注微信公众号
  • 加入 QQ 群:
    • 192706294(已满)
    • 731990104(已满)
    • 798786647(已满)
    • 729884609(已满)
    • 977810755(已满)
    • 815126783(已满)
    • 812540095(已满)
    • 1006366459(已满)
    • 692541889

  • 关注微信公众号
  • 加入微信群:liuxiaoyan-s,备注入群
  • 也欢迎加入知识星球 Go粉丝们(免费)

给该专栏投稿 写篇新文章

每篇文章有总共有 5 次投稿机会

收入到我管理的专栏 新建专栏