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

来源:6-7 Go操作ES的一些技巧和注意事项 (二)

404_

2023-02-03

	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阻塞。

写回答

1回答

少林码僧

2023-02-03

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
1
一号IT民工
对的将请求丢给go的channel,如果主进程退出了,就不会提交请求到ES了,主要是sdk会自行合并打包请求
2023-02-08
共1条回复

海量数据高并发场景,构建Go+ES8企业级搜索微服务

全新 ES8 配合技术组件,实现高性能搜索

267 学习 · 54 问题

查看课程