在实际场景中,操作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副本集:
8核16G 虚拟机,(上面已搭若干实例),已使用10G,空闲内存6G左右前提下,压测mongo服务。
(插入字段和生产线上字段格式长度基本相同。)
1)单进程(携程)写入:单次批量写入,1万条/次,耗时221ms;
2)单进程(携程)写入:单次批量写入,1千条/次,耗时38ms(40ms左右);
3)单进程(携程)写入: 连续遍历1千次,每次insert_all 1k条/次,插入总数量1百万条记录,总耗时19s;
4)单进程(携程)写入: 连续遍历1万次,每次insert_all 1k条/次, 插入总量1千万条记录,总耗时3min12s(3min14s),cpu 使用率 150%左右,mongo状态每秒钟insert操作5w多次;
5)单进程(携程)写入: 遍历两次,每次insert-all 1k条/次,耗时77ms;
6)并发写入:20个进程同时批量写入,每个进程总共insert_all 100万条记录,连续遍历1000次,每次写入1000条记录,mongo的写入次数每秒钟/20万次写操作,每个进程写完1min40
S,20个进程写入基本为1min40s左右。
7)在2千万的表中,单纯的做TTL过期,iostat查看await和util%,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的数据,或者选择写脚本或程序手动控制或自动删除.