2024-06-04笔记

1.mongo push ,set

在实践中写入mongo的时候使用了push,发现流量非常非常的大,简直到了无语的程度。

查找资料后发现,使用push的时候默认会返回整个document的数据,也就是说每一次写入都要读取整个document并返回,导致流量巨大,网上资料比较多,例如这个

https://geek-docs.com/mongodb/mongodb-questions/1_mongodb_is_mongodb_push_performance_bad_and_should_i_change_my_data_structure.html

后来采用set来实现,用updateMany,但是这个有个问题就是当新建的时候,返回数据里没办法判断是否写入成功。

c.UpdateMany(ctx, filter, bson.M{"$set": mKeyVal})

op := options.FindOneAndUpdateOptions{Projection: bson.M{"_id": 1}}

err = c.FindOneAndUpdate(ctx, filter, bson.M{"$push": bson.M{"msg": bson.M{"$each": msgListToMongo}}}, &op).Err()

UpdateMany 会存在的问题就是filter的document不存在的时候不会返回错误,只能通过返回结果里说未找到。

所以没办法判断是否要进行新增。

FindOneAndUpdate 假如不设置options的话,在返回结果里会返回整个document的数据,这样就会导致流量暴增,插入一条数据,返回几千条数据,导致服务器流量是天量,能达到几百M

这里设置op为只返回 _id 这样是最小量的了,是最小的结果,流量几KB即可

但是写入的流量就没办法了,这个就是真实的写入数据库的量。

$push 设置了option之后,速度也是比较快的,和set差不多,设置略快。

$set 在当前场景里不好判断是否新增一个document

2.如何判断某个端口的流量

iftop -f "src port 27017" -P

iftop  -f "dst port 27017" -P

查看指定端口流量,src 表示源头流出,dst表示流入。

这样就能够看出流量变化了。

3.for range append陷阱

s := []int{1, 2, 3}

q := make([]*int, 0, 10)

for i, v := range s {

  q = append(q, &v)

  fmt.Println(&s[i])

}

for _, v := range q {

  fmt.Println(v)

}

上面的代码里,for,range里打印出的 &v地址都是同一个,也就是说假如append里加入for range里的v值的地址,其实都是同一个,这样就出问题。

可以查看for range的源码发现,返回的index,value都是申请的临时变量。自己看源码麻烦的话,直接看这个文章

Go Range 内部实现 · NewtonIO (newt0n.github.io)

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容