nsq源码分析(3):nsqd之数据持久化
nsqd持久化使用 go-diskqueue 包实现
diskqueue包实现:
当nsqd进程退出时,将内存中的数据写入到磁盘
当nsqd进程启动时,将磁盘中的数据读入到内存
在nsqd运行过程中,定时(默认2秒)将内存中的数据写入到磁盘
go get github.com/nsqio/go-diskqueue
元数据和数据文件
nsqd.867.dat -> nsqd.dat
nsqd.dat
top1.diskqueue.000000.dat # top1队列(topic)下的数据文件
top1.diskqueue.meta.dat # top1队列(topic)下的元数据文件
diskqueue对外接口
go-diskqueue/diskqueue.go
type Interface interface {
Put([]byte) error // 消息生产接口
ReadChan() chan []byte // 消息消费接口 // this is expected to be an *unbuffered* channel
Close() error // 队列关闭接口
Delete() error // 消息删除接口
Depth() int64 // 消息长度接口
Empty() error // 清空队列接口
}
diskqueue结构体
// diskQueue实现了先入先出规则的队列服务
type diskQueue struct {
// 64bit atomic vars need to be first for proper alignment on 32bit platforms
// run-time state (also persisted to disk)
// 数据文件相关信息
readPos int64 // 记录数据文件读的位置
writePos int64 // 记录数据文件写的位置
readFileNum int64 // 当前读文件的编号
writeFileNum int64 // 当前写文件的编号
depth int64 // 队列中消息的数量
sync.RWMutex
// instantiation time metadata
// 元数据相关
name string // 元数据名称
dataPath string // 元数据的数据目录
maxBytesPerFile int64 // 每个文件的最大字节数,默认100M // currently this cannot change once created
minMsgSize int32 // 一条消息的最小长度
maxMsgSize int32 // 一条消息的最大长度
syncEvery int64 // 当写入的消息达到syncEvery时则执行sync操作 // number of writes per fsync
syncTimeout time.Duration // 每隔syncTimeout时间执行同步一次 // duration of time per fsync
exitFlag int32 // 队列退出标识。比如当删除队列时会将该队列标记为1,阻止其他线程操作该队列
needSync bool // 是否需要同步
// keeps track of the position where we have read
// (but not yet sent over readChan)
// 读操作是为了投递消息给客户端,如果投递失败则继续使用当前的读取位置再次尝试投递消息
nextReadPos int64 // 记录正在投递的消息的位置
nextReadFileNum int64 // 记录正在投递的消息的文件编号
readFile *os.File // 读文件句柄
writeFile *os.File // 写文件句柄
reader *bufio.Reader // 读文件操作的缓存区
writeBuf bytes.Buffer // 写文件操作的缓存区
// exposed via ReadChan()
readChan chan []byte // 获取消息的channel
// internal channels
writeChan chan []byte // 写入消息的channel
writeResponseChan chan error // 返回写入消息的状态
emptyChan chan int // 清空消息的channel
emptyResponseChan chan error // 返回清空队列的状态
exitChan chan int // 队列退出的channel
exitSyncChan chan int // 队列退出的同步channel,确保ioLoop先退出
logger Logger
}
diskqueue实例化过程
func New(name string, dataPath string, maxBytesPerFile int64,
minMsgSize int32, maxMsgSize int32,
syncEvery