博客
关于我
记一次go中map并发引起的事故
阅读量:456 次
发布时间:2019-03-06

本文共 1640 字,大约阅读时间需要 5 分钟。

错误使用 map 引发的血案

最近业务中,同事使用 map 来接收返回的结果,使用 WaitGroup 来并发处理执行返回的结果,结果上线之后,直接崩了。

日志分析

日志显示大量的数据库缓存池连接失败:

{"ecode":-500,"message":"timed out while checking out a connection from connection pool"}{"ecode":-500,"message":"connection(xxxxxxxxx:xxxxx) failed to write: context deadline exceeded"}

场景复原

来看伪代码:

package mainimport (    "fmt"    "sync"    "time")var count = 300func main() {    var data = make(map[int]string, count)    var wg sync.WaitGroup    for i := 0; i < count; i++ {        wg.Add(1)        go func(i int) {            defer wg.Done()            time.Sleep(time.Second * 1)            mockSqlPool()            data[i] = "test"        }(i)    }    fmt.Println("-----------WaitGroup执行结束了-----------")    wg.Wait()}// 模拟数据库的连接和释放func mockSqlPool() {    defer fmt.Println("关闭pool")    fmt.Println("我是pool")}

运行输出

运行的输出显示:

...我是pool关闭poolconcurrent map writes我是poolgoroutine 56 [running]: runtime.throw(...)...

错误原因

  • map 不是并发安全

    map 在并发环境下不是安全的,特别是在多个 goroutine 同时修改时,会导致 panic。
    在示例中,多个 goroutine 并发写入 map,导致并发修改,触发 concurrent map writes 错误。

  • 避免在循环中连接数据库

    在循环中频繁连接数据库会导致连接泄漏,进而导致数据库连接池连接无法被及时释放。

  • WaitGroup 的信号量

    WaitGroup 使用信号量机制来管理 goroutine 的等待状态:

    • Wait() 会阻塞,直到所有 goroutine 完成。
    • Done() 会在最后一个 goroutine 完成时,释放信号量,允许 Wait() 继续执行。

    goroutine 状态分析

    输出显示有多个 goroutine 处于 semacquire 状态,这意味着它们正在等待信号量被唤醒。然而,由于 WaitGroup 因 panic 退出,无法通过 Done() 通知 goroutine 退出,导致这些 goroutine 阻塞到最后,占用数据库连接,造成连接泄漏。

    解决方案

  • 使用 sync.RwLock 或 sync.Mutex 保护 map

    确保在并发环境下,map 的读写操作是安全的。

  • 避免在 goroutine 中直接访问数据库连接

    使用数据库连接池(如 sqlc 或自定义连接池)来管理数据库连接,确保连接能被及时释放。

  • 优化 WaitGroup 使用

    确保在 WaitGroup 中正确处理 Done() 信号,避免 panic 导致的资源泄漏。

  • 通过以上优化,可以避免并发写入导致的 panic,同时确保数据库连接能够被正确释放,避免连接泄漏问题。

    转载地址:http://xzcfz.baihongyu.com/

    你可能感兴趣的文章
    Python在def函数中使用for循环
    查看>>
    Python在Conda环境中,但在Windows虚拟环境中没有激活
    查看>>
    python系列【仅供参考】:python pip 错误 ModuleNotFoundError: No module named pip._internal 解决办法
    查看>>
    python图像条状状噪声,使用PYTHON PIL从验证码图像中删除背景嘈杂的线条
    查看>>
    Python图像处理:从内存加载jpeg
    查看>>
    python固定后缀(名物化词汇)词频统计:抽取+统计+可视化
    查看>>
    python商品评论数据采集与分析可视化系统 Flask框架 requests爬虫 NLP情感分析 毕业设计 源码
    查看>>
    python商品数据分析可视化系统(带爬虫)京东销售数据分析 计算机毕业设计 源码下载
    查看>>
    python商品库存管理系统 django框架 商品网站 MySQL数据库 源码下载 计算机毕业设计
    查看>>
    Python哪个版本最稳定好用2023.10.19
    查看>>
    Python和黑客技术的渊源
    查看>>
    Python和RF编写接口自动化
    查看>>
    Python和RF编写web自动化
    查看>>
    python和js哪个难_【Python】记一次学习,Python 与 js 在实现闭包时的差异
    查看>>
    python和java哪个更值得学——来自知乎高赞回答
    查看>>
    python和c混合编程 github_在pycharm中使用git版本管理以及同步github的方法
    查看>>
    python命名空间更改_Python模块xml.etree.ElementTree自动修改xml命名空间键
    查看>>
    Python命名中尾随下划线有什么好处?
    查看>>
    Python启动脚本
    查看>>
    Python听写汇总结果
    查看>>