golang mysql批量插入实例

业务逻辑:

tcp接收消息后,先将消息保存到数据库再进行后续操作。

问题:

压测发现,tcp连接非常多,消息更多,每秒10000条消息时,程序会内存溢出。

解决:

自然就想到了,问题出在不能及时把消息处理掉的问题。所以先想能不能加快mysql的处理流程,可以定时批量插入代替及时插入。

思路:

1.接收tcp消息,通多channel发送到临时的切片。

2.定时任务,定时将临时切片的数据批量插入到mysql。

 

知识点:

1.channel来接收消息

2.互斥锁,保证切片操作和mysql插入互斥

3.定时器,定时触发插入任务

 

package service

import (
	"bytes"
	"fmt"
	"sync"
	"time"
)

/*
问题:mysql连接过多可能导致内存溢出
思路:
1.使用定时批量更新代替即收即插
2.使用channel,将接受的信息先留在内存中,然后定时,插入数据库
3.定时器,定时将内存中的数据整理后插入
*/

var tmpMessage []message
var messageMysqlChan chan message
var mesLock sync.Mutex //使用互斥锁,保证切片添加和数据库插入互斥

func init() {
	messageMysqlChan = make(chan message, 100000)
	go batchMessageReceive()
	go batchStartTimer()
}

/*
接收消息的逻辑
只负责接收消息
*/
func batchMessageReceive() {
	for {
		select {
		case oneMessage := <-messageMysqlChan:
			mesLock.Lock()
			tmpMessage = append(tmpMessage, oneMessage)
			mesLock.Unlock()
		}
	}

}

func batch(batchMessage []message) {
	if len(batchMessage) == 0 {
		fmt.Print("空消息")
		return
	}

	var buffer bytes.Buffer
	sql := "insert into `t_msg` (`id`,`msg`,`insert_time`) values"
	if _, err := buffer.WriteString(sql); err != nil {
		fmt.Print(err.Error())
	}

	for index, value := range batchMessage {
		if index == len(batchMessage)-1 {
			buffer.WriteString(fmt.Sprintf("('%d','%s','%s');", value.Id, value.Mn, value.Msg, value.InsertTime))
		} else {
			buffer.WriteString(fmt.Sprintf("('%d','%s','%s'),", value.Id, value.Mn, value.Msg, value.InsertTime))
		}
	}

	err := MysqlDB.Exec(buffer.String()).Error
	if err != nil {
		fmt.Print("插入消息失败:", err.Error())
	}
	return
}

/*
插入的逻辑
*/
func batchStartTimer() {

	tick := time.NewTicker(5 * time.Second)

	for {
		select {
		case <-tick.C:
			mesLock.Lock()
			batch(tmpMessage)
			tmpMessage = tmpMessage[0:0] //置空,重复利用切片
			mesLock.Unlock()
		}
	}

}

 

参考博客:

https://www.cnblogs.com/jssyjam/p/11773439.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值