zoukankan      html  css  js  c++  java
  • golang的mongo批量写入压测

      在实际场景中,操作nosql是很常用的,下面分享下压测mongo的场景和具体结果:

    测试用例代码如下:

    package main
    
    import (
        "fmt"
        "gopkg.in/mgo.v2/bson"
        "time"
    )
    
    func main() {
    
        for j := 0; j < 20; j ++ {
            go     pressTest()
        }
        pressTest()        //测试mongo写入压测
    }
    
    func pressTest (){
    
        defer timeCost()()        //注意,是对 timeCost()返回的函数进行调用,因此需要加两对小括号
        for j := 0; j < 2; j ++ {
            InsertMfAndroid("abc",1)
        }
    }
    
    // 耗时统计函数
    func timeCost() func() {
        start := time.Now()
        return func() {
            tc := time.Since(start)
            fmt.Printf("time cost0000 = %v
    ", tc)
        }
    }
    
    
    //可插入多条数据(先做循环插入mongo) MId string, token_arry, userIds []string, p, appId int
    func InsertMfAndroid(newMid string, tokenNums int) {
    
        //defer timeCost()()        //注意,是对 timeCost()返回的函数进行调用,因此需要加两对小括号
    
            session := GetSession().Clone()
            defer session.Close()
    
            timeUnix := time.Now().Unix()
            timeUnixString := strconv.FormatInt(timeUnix,10)            // int64到string
            sendTime, _ := strconv.Atoi(timeUnixString)                   // string到int
    
            var docs []interface{}
    
            for j := 0; j < tokenNums; j ++  {
                    docs = append(docs, bson.M{"mid": newMid, "t": "1","sut": sendTime, "cut": time.Now(), "expireTime":getExpireTime()})
            }
    
            collection := session.DB(beego.AppConfig.String("mongo::db")).C("token_msg")
            err := collection.Insert(docs...)
            if err != nil {
                    beego.Error("mongo存储消息流水:[%s]", err)
            }
    }

    //获取过期时间
    func getExpireTime() time.Time {

      timeStr := time.Now().Format("2006-01-02")

      //使用Parse 默认获取为UTC时区 需要获取本地时区 所以使用ParseInLocation
      t, _ := time.ParseInLocation("2006-01-02 15:04:05", timeStr+" 23:59:59", time.Local)
      zeroTime := t.Unix() + 1
      //时间戳 to 时间
      tm := time.Unix(zeroTime + 356400, 0)
      return tm
    }

     

    UAT环境压测 mongo副本集:

    816G 虚拟机,(上面已搭若干实例),已使用10G,空闲内存6G左右前提下,压测mongo服务。

    (插入字段和生产线上字段格式长度基本相同。)

    1)单进程(携程)写入:单次批量写入,1万条/次,耗时221ms

    2)单进程(携程)写入:单次批量写入,1千条/次,耗时38ms40ms左右);

    3)单进程(携程)写入: 连续遍历1千次,每次insert_all 1k/次,插入总数量1百万条记录,总耗时19s

    4)单进程(携程)写入: 连续遍历1万次,每次insert_all 1k/,  插入总量1千万条记录,总耗时3min12s3min14s),cpu 使用率 150%左右,mongo状态每秒钟insert操作5w多次;

    5)单进程(携程)写入: 遍历两次,每次insert-all 1k/次,耗时77ms

    6)并发写入:20个进程同时批量写入,每个进程总共insert_all 100万条记录,连续遍历1000次,每次写入1000条记录,mongo的写入次数每秒钟/20万次写操作,每个进程写完1min40

    S20个进程写入基本为1min40s左右。

    7)2千万的表中,单纯的做TTL过期,iostat查看awaitutil%util%达到30-40%左右,说明这个操作比较消耗IO性能.

    8) 并发写入:20个进程,2千万条记录,每个进程写入100w条记录的IoStat状态

     

     9)最左边是Mongo每秒钟的写操作次数,连接数和等待队列正常,无明显增高变化;

     

     10)用固定集合capCollection指定集合(表)大小和条数,Insert每秒钟2w多条操作,iostat的util最高在30%多,io正常.

     
    结合前几篇写的博客, 地址如下,https://www.cnblogs.com/unqiang/p/11987684.html

    创建mongo删除的索引,根据业务,如果是白天忙时,晚上闲时,最好选择晚上去做TTL过期,这个不会在业务高峰的时候,批量插入和删除都去抢占IO操作,

    而单纯的TTL过期,就会把io的util%打到30%,业务数据量如上,总计2000w数据,然后TTL索引过期.

    要是再加上,2000w的数据,20个进程每个进程100w同时批量写,IO util%一下会飙升上去.

    故建议根据业务选择删除mongo的数据,或者选择写脚本或程序手动控制或自动删除.

  • 相关阅读:
    202103226-1 编程作业
    MSF原则
    介绍
    4 20210412-1 原型设计作业
    案例分析作业
    第二次编程
    阅读任务
    自我介绍
    案例分析作业
    阅读任务
  • 原文地址:https://www.cnblogs.com/unqiang/p/12202263.html
Copyright © 2011-2022 走看看