- mongodb - 在 MongoDB mapreduce 中,如何展平值对象?
- javascript - 对象传播与 Object.assign
- html - 输入类型 ="submit"Vs 按钮标签它们可以互换吗?
- sql - 使用 MongoDB 而不是 MS SQL Server 的优缺点
我正在尝试配置从 mongo 副本集的主节点和两个辅助节点读取以提供更好的负载平衡。 3 个节点中的每一个都位于具有 IP 地址的不同机器上:ip1、ip2、ip3。
我的 GoLang
站点,即 martini
网络服务器,有两个 url /insert
和 /get
:
package main
import (
"github.com/go-martini/martini"
"gopkg.in/mgo.v2"
"gopkg.in/mgo.v2/bson"
"net/http"
)
const (
dialStr = "ip1:port1,ip2:port2,ip3:port3"
dbName = "test"
collectionName = "test"
elementsCount = 1000
)
var mainSessionForSave *mgo.Session
func ConnectToMongo() {
var err error
mainSessionForSave, err = mgo.Dial(dialStr)
mainSessionForSave.SetMode(mgo.Monotonic, true)
if err != nil {
panic(err)
}
}
func GetMgoSessionPerRequest() *mgo.Session {
var sessionPerRequest *mgo.Session
sessionPerRequest = mainSessionForSave.Copy()
return sessionPerRequest
}
func main() {
ConnectToMongo()
prepareMartini().Run()
}
type Element struct {
I int `bson:"I"`
}
func prepareMartini() *martini.ClassicMartini {
m := martini.Classic()
sessionPerRequest := GetMgoSessionPerRequest()
m.Get("/insert", func(w http.ResponseWriter, r *http.Request) {
for i := 0; i < elementsCount; i++ {
e := Element{I: i}
err := collection(sessionPerRequest).Insert(&e)
if err != nil {
panic(err)
}
}
w.Write([]byte("data inserted successfully"))
})
m.Get("/get", func(w http.ResponseWriter, r *http.Request) {
var element Element
const findI = 500
err := collection(sessionPerRequest).Find(bson.M{"I": findI}).One(&element)
if err != nil {
panic(err)
}
w.Write([]byte("get data successfully"))
})
return m
}
func collection(s *mgo.Session) *mgo.Collection {
return s.DB(dbName).C(collectionName)
}
我使用命令 go run site.go
运行这个 GoLang
站点并准备我请求的实验 http://localhost:3000/insert
- 大约一分钟后我的测试数据被插入。
然后我开始测试从辅助节点和主节点读取在 attacker.go
:
package main
import (
"fmt"
"time"
vegeta "github.com/tsenart/vegeta/lib"
)
func main() {
rate := uint64(4000) // per second
duration := 4 * time.Second
targeter := vegeta.NewStaticTargeter(&vegeta.Target{
Method: "GET",
URL: "http://localhost:3000/get",
})
attacker := vegeta.NewAttacker()
var results vegeta.Results
for res := range attacker.Attack(targeter, rate, duration) {
results = append(results, res)
}
metrics := vegeta.NewMetrics(results)
fmt.Printf("99th percentile: %s\n", metrics.Latencies.P99)
}
运行它go runattacker.go
我只是每秒请求 URL http://localhost:3000/get
4000 次。当攻击者工作时,我打开了我所有的 3 台服务器并运行 htop
命令来观察资源消耗。 PRIMARY 节点显示它处于高负载状态,CPU 大约为 80%。中学很平静。
当我使用 mgo.Monotonic
...
mainSessionForSave.SetMode(mgo.Monotonic, true)
... 我希望从所有节点读取:ip1, ip2, ip3
并且我希望在相同负载和相同 CPU 消耗下观察所有节点。但事实并非如此。我配置错了什么?事实上 mgo.Monotonic
在我的情况下不起作用,我只从 PRIMARY 节点读取。
最佳答案
sessionPerRequest
只创建一次:prepareMartini
在服务器启动时调用,然后设置 sessionPerRequest
。传递给 m.Get()
的闭包访问该变量。然后,在第一次写入之后(在您的测试设置期间),mgo
will only access the primary :
Monotonic consistency will start reading from a slave if possible, so that the load is better distributed, and once the first write happens the connection is switched to the master.
(如果 mgo
在写入主节点后只是继续从辅助节点读取,则读取不一定反射(reflect)您刚刚进行的写入,这可能会很痛苦。切换到主节点应该只为您提供更新的数据,而不是您从辅助服务器获得的数据,从不旧,这保持了单调性。无论如何,理想情况下它应该是这样工作的;有关更多信息,请参阅下面的“未解决问题”链接。)
解决方案是将创建 session 推送到您的处理程序中,例如,删除 sessionPerRequest
并在每个处理程序顶部放置一些明确的内容,例如
coll := mainSessionForSave.Copy().DB(dbName).Collection(collName)
应根据 open issues with MongoDB consistency 阅读所有一致性 promise :现在,在网络分区期间,读取可以看到旧数据和稍后将回滚的写入,即使 mgo
正在尝试从主数据库读取。 (比较和设置没有这个问题,但当然这是一个更大更慢的操作。)同样值得仔细阅读这篇文章只是为了讨论一致性级别和描述不同的数据库行为可能如何体现在应用程序的最终用户。
关于mongodb - 使用 mgo.Monotonic 从中学读取,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29865895/
我最近开始学习 Go,到目前为止我非常喜欢它。我想了解如何使用 mgo Mongo 驱动程序制作 REST API。 在网站上,共有三个API:mgo、mgo/bson、mgo/txn。它们是什么意思
我有一个 GoLang 代码: c.Find(selectQuery).All(&results) if err == mgo.ErrNotFound { // error handling } se
我有一组动态的成分名称,并为每个用户提供。我想将它与 mongo 文档匹配,其中有一个名为 ingredients 的对象的 array 具有属性 name。我已经编写了一个查询(见下文),它将从 U
我 我很难将 MongoDB 查询转换为 mgo bson。 Mongo 记录模式如下所示。我想查找主题标签为“教育”和“学生”的记录。 db.questions.insert ( {
我正在尝试使用 mgo 库进行批量更新插入。我正在阅读 documentation关于批量更新插入,因为这是我第一次使用 MongoDB,看起来我必须提供成对的文档才能更新。 在我的函数中,我正在执行
我一直在为我的 API 使用 mgo,但我在我的 MongoDB 中看到许多当前连接(同时使用少于 5 个设备进行测试)。通过在我的 Mongo 服务器中执行 db.serverStatus().co
我正在尝试检索以下数据中每个 object_name 的最早创建日期和最后修改日期 { "_id" : ObjectId("5a510666b2e543371cff44ef"), "object_na
我是 Golang 的新手,我正在使用 mgo 框架构建 Golang CRUD 来练习。当我使用 mgo 插入一个元素时,插入了两次而不是一次,我在 MongoDB Compass 社区中检查了它。
我正在从事一个基于 MongoDB 数据结构的项目。我们存储在数据库中的对象如下所示: { "_id" : ObjectId("567a877df1c7720bea7c2f51"), "usernam
我正在尝试使用 golang mgo 执行查询为了有效地从连接中获得不同的值,我知道这可能不是在 Mongo 中使用的最佳范例。 像这样: pipe := []bson.M{ {
我的目标是实现这个 code .除了不使用 sql,我想使用 mongoDB。我认为我处理 session 的方式存在问题。 我正在尝试使用 mgo 通过 Rest API 将一些用户数据插入到 Mo
我正在尝试使用 Go 中的 mgo 库实现以下功能: db.artists.update( {_id: ObjectId("534944125117082b30000001")}, {
我的 Go 应用程序已使用 MGO 连接到 MongoDB(托管在 Compose.io 上),没有任何问题。 今天我决定删除这个数据库并添加一个不同的数据库(再次使用 Compose)。我更新了连接
我有这个模型数据,我用它来将数据保存到数据库中 type Nos struct { UnitCode string `json:"unitCode" bson:"unitCode
我正在用 mgo 编写一个数据库接口(interface)。我的模型中的某些文档引用了其他文档。 type Child struct{ Id bson.ObjectId `js
我有一个查询,它从包含特定文本的集合文档中返回所有名称。在以下示例中,不区分大小写地返回所有包含序列“oh”的名称;不返回文档中的其他字段: find({name:/oh/i}, {name:1, _
我使用以下 go 文件作为我的 http API 和 mgo 之间的层: package store import ( "reflect" "strings" "labix.o
我正在编写一个快速写入 mongodb 的应用程序。 mongodb 和 mgo 处理得太快了。我的问题是,有没有办法让我确定 mongo 跟不上并开始阻塞?但我也不想无谓地阻止。以下是模拟问题的代码
我有以下代码: competitionMatch := bson.M{ "$match": bson.M{"competition" : bson.M{"$in" : []string{"PREMIE
下面我设计了文档结构如下: type MIS_Course struct { ID bson.ObjectId `bson:"_id,omitempty"` Name string
我是一名优秀的程序员,十分优秀!