请稍等 ...
×

采纳答案成功!

向帮助你的同学说点啥吧!感谢那些助人为乐的人

BulkCreate方法为什么需要进行sleep才能写入

	for i := 0; i < 500; i++ {
		docID := strconv.Itoa(i)
		//update := map[string]interface{}{"name": "xxx"}
		doc := Goods{
			Id:             int64(i),
			Name:           "name" + docID,
			Price:          float64(i),
			Year:           2022,
			LastMonthSales: i,
			Favorites:      i,
		}
		esClient.BulkCreate(IndexName, docID, docID, doc)
	}

	//因为是异步处理,这里需要等待本地channel提交
	//time.Sleep(3 * time.Second)

这一块代码为什么需要sleep?难道不能自动提交吗?我们直接将数据扔给ES它自己提交不行吗?

但是client.Bulk()最后在调用Do方法 这种方式就可以,也不用进行sleep阻塞。

正在回答 回答被采纳积分+3

1回答

少林码僧 2023-02-03 17:31:24

bulk提交是需要在请求体中放多个文档的,比如我们通过官方api可以这样进行bulk提交

POST _bulk
{ "index" : { "_index" : "test", "_id" : "1" } }
{ "field1" : "value1" }
{ "delete" : { "_index" : "test", "_id" : "2" } }
{ "create" : { "_index" : "test", "_id" : "3" } }
{ "field1" : "value3" }
{ "update" : {"_id" : "1", "_index" : "test"} }
{ "doc" : {"field2" : "value2"} }

但是如果你只给一个文档就提交,虽然使用的是Bulk方式写入,ES收到请求后还是以请求为单位进行写入的,

这样就失去了批量写入的意义。

Bulk写入的目的就在于一次提交多个文档,减少ES的IO操作大幅提升ES的吞吐性能。

所以 go的sdk(也就是客户端)就提供了这种合并的能力,我们将一条条的文档丢给sdk,sdk将这些文档先放到channel中,然后根据我们设置的三个维度的条件(时间,大小和文档数)进行提交。

这里的提交其实就是定期调用Do方法,其实本质是在go的sdk完成对多次请求的打包,再通过一次Bulk请求提交给ES。

所以在调用BulkCreate时,我们只是将请求丢给go的channel而已,并没有立马提交Bulk请求到ES。

课程中也提供了两个方法,如果业务中本身就是一批批的写入可以调用我们封装的BulkCreateDocs() 方法,拿到实时的写入状态。

如果是单条文档写入想提升性能就可以调用BulkCreate()让SDK帮你做打包提交

2 回复 有任何疑惑可以回复我~
  • 对的将请求丢给go的channel,如果主进程退出了,就不会提交请求到ES了,主要是sdk会自行合并打包请求
    回复 有任何疑惑可以回复我~ 2023-02-08 11:55:31
问题已解决,确定采纳
还有疑问,暂不采纳
意见反馈 帮助中心 APP下载
官方微信