diskqueue第六篇 - 如何使用diskqueue,示例

本文详细介绍了NSQ消息持久化组件diskqueue的使用方法,包括创建、写入、读取消息、删除和关闭等操作,以及在nsq中实际应用的示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 diskqueue是nsq消息持久化的核心,内容较多,故分为多篇

1. diskqueue第一篇 - 是什么,为什么需要它,整体架构图,对外接口

2. diskqueue第二篇 - 元数据文件,数据文件,启动入口,元数据文件的读写及保存

3. diskqueue第三篇 - 数据定义详解,运转核心ioloop()源码详解

4. diskqueue第四篇 - 怎么写入消息,怎么对外发送消息

5. diskqueue第五篇 - 追尾检测,错误处理,如何正常关闭

6. diskqueue第六篇 - 如何使用diskqueue,示例

经过前面5篇博客的介绍,大家对diskqueue的整体框架、内部原理应该很清楚了,这篇博客我们讲如何使用diskqueue,毕竟学习它是为了更好地使用。以nsq中实际使用为例,希望大家能看得更清楚一些

一、使用diskqueue的方法,先说结论

1. 调用diskqueue.New()函数来创建一个新的diskqueue

2. 调用diskqueue.Put()函数往diskqueue中写入消息,需在select中执行

3. 调用diskqueue.ReadChan()函数从diskqueue中接收消息,需在select中执行

4. 调用diskqueue.Empty()函数+diskqueue.Delete()函数来删除一个diskqueue

5. 调用diskqueue.Close()函数正常关闭一个diskqueue

二、使用diskqueue的举例,以nsq的channel为例

1. 调用diskqueue.New()函数来创建一个新的diskqueue

示例代码,源码位置在nsq/nsqd/channel.go

// 新建一个channel
func NewChannel(topicName string, channelName string, nsqd *NSQD, deleteCallback func(*Channel)) *Channel {
        // 省略无关代码
		c.backend = diskqueue.New(
			backendName,
			nsqd.getOpts().DataPath,
			nsqd.getOpts().MaxBytesPerFile,
			int32(minValidMsgLength),
			int32(nsqd.getOpts().MaxMsgSize)+minValidMsgLength,
			nsqd.getOpts().SyncEvery,
			nsqd.getOpts().SyncTimeout,
			dqLogf,
        // 省略无关代码
}

上面的NewChannel()函数是创建channel,内部调用了diskqueue.New()来创建一个新的diskqueue,内部参数不再一一解释了

2. 调用diskqueue.Put()函数往diskqueue中写入消息,需在select中执行

示例:topic往channel中压入消息时会调用put()函数,源码位置在nsq/nsqd/channel.go

// 压入一个新消息
func (c *Channel) put(m *Message) error {
	select {
	case c.memoryMsgChan <- m:	// 先尝试压入内存队列
	default:
		err := writeMessageToBackend(m, c.backend)	// 不成功的话则压入持久化队列
		c.nsqd.SetHealth(err)
		if err != nil {
			c.nsqd.logf(LOG_ERROR, "CHANNEL(%s): failed to write message to backend - %s", c.name, err)
			return err
		}
	}
	return nil
}

put()函数内部:先尝试往内存队列中压入,如果不成功,则调用writeMessageToBackend()函数压入到持久化队列,即diskqueue

再来看writeMessageToBackend()函数,源码位置在nsq/nsqd/message.go

// 把指定消息写入持久化队列
func writeMessageToBackend(msg *Message, bq BackendQueue) error {
	// 使用buffpoll作为写入缓冲区
	buf := bufferPoolGet()
	defer bufferPoolPut(buf)
	// 先把消息写入buff
	_, err := msg.WriteTo(buf)
	if err != nil {
		return err
	}
	// 再往队列中写
	return bq.Put(buf.Bytes())
}

函数内部先把消息序列化成[]byte,再调用diskqueue.Put()函数写入

3. 调用diskqueue.ReadChan()函数从diskqueue中接收消息,需在select中执行

示例:客户端连接从持久化队列中接收消息,往客户端推送

源码位置:nsq/nsqd/protocol_v2.go的messagePump()函数

// 客户端连接的消息循环
func (p *protocolV2) messagePump(client *clientV2, startedChan chan bool) {
        var backendMsgChan 	<-chan []byte	// 持久化队列的通道(只读)        
        // 省略无关代码
	    backendMsgChan 	= subChannel.backend.ReadChan()

		select {
        // 省略无关代码
		case b := <-backendMsgChan:		// 持久化队列中有消息
			if sampleRate > 0 && rand.Int31n(100) > sampleRate {
				continue
			}
        }   
}

可以看到messagePump()函数中的backendMsgChan会被赋值为diskqueue.ReadChan()的返回值,这是个只读的通道,然后在select中读取

4. 调用diskqueue.Empty()+diskqueue.Delete()来删除一个diskqueue

示例:nsq的channel关闭时会调用diskqueue的Empty()和Delete()函数

源码位置:nsq/nsqd/channel.go的Delete()函数

// 删除channel的处理
func (c *Channel) Delete() error {
	return c.exit(true)
}

函数内部调用了exit()函数,参数为true表删除,再来看exit()函数的实现

// channel退出操作(删除或关闭channel时调用)
func (c *Channel) exit(deleted bool) error {
    // 省略无关代码......

	// 删除channel时的操作
	if deleted {
		c.Empty()		// 清空消息(清空内存队列,清空持久化队列->调用Empty()函数)
		return c.backend.Delete()
	}

	// 关闭channel时的操作
	c.flush()					// 把数据刷到磁盘
	return c.backend.Close()
}

可以看到参数deleted为true时,有两步操作

第一步:调用Empty()函数,该函数内部调用了diskqueue.Empty()函数进行清空操作

第二步:调用diskqueue.Delete()函数

5. 调用diskqueue.Close()函数正常关闭一个diskqueue

示例: nsq的channel关闭时会调用diskqueue.Delete()函数

源码位置:nsq/nsqd/channel.go的Close()函数

// 关闭channel的处理(nsqd关闭时才调用)
func (c *Channel) Close() error {
	return c.exit(false)
}

函数内部调用了exit()函数,参数为false

具体exit()函数的实现,上面第4模块刚刚讲过,大家可以看到函数最下面调用了diskqueue.Close()函数,不再重复了

三、本篇总结

本篇博客主要讲如何使用diskqueue,并对各种用法都给出了示例,示例取自nsq。只要大家能仔细看下nsq的使用例子,相信以后自己使用时会得心应手

至此,diskqueue全部讲完

内容概要:本文详细探讨了基于樽海鞘算法(SSA)优化的极限学习机(ELM)在回归预测任务中的应用,并与传统的BP神经网络、广义回归神经网络(GRNN)以及未优化的ELM进行了性能对比。首先介绍了ELM的基本原理,即通过随机生成输入层与隐藏层之间的连接权重及阈值,仅需计算输出权重即可快速完成训练。接着阐述了SSA的工作机制,利用樽海鞘群体觅食行为优化ELM的输入权重和隐藏层阈值,从而提高模型性能。随后分别给出了BP、GRNN、ELM和SSA-ELM的具体实现代码,并通过波士顿房价数据集和其他工业数据集验证了各模型的表现。结果显示,SSA-ELM在预测精度方面显著优于其他三种方法,尽管其训练时间较长,但在实际应用中仍具有明显优势。 适合人群:对机器学习尤其是回归预测感兴趣的科研人员和技术开发者,特别是那些希望深入了解ELM及其优化方法的人。 使用场景及目标:适用于需要高效、高精度回归预测的应用场景,如金融建模、工业数据分析等。主要目标是提供一种更为有效的回归预测解决方案,尤其是在处理大规模数据集时能够保持较高的预测精度。 其他说明:文中提供了详细的代码示例和性能对比图表,帮助读者更好地理解和复现实验结果。同时提醒使用者注意SSA参数的选择对模型性能的影响,建议进行参数敏感性分析以获得最佳效果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值