多线程插入elasticsearch时如何保证唯一性?
How to ensure uniqueness when elasticsearch is inserted in multithreading?
我们有elasticsearch的一些文档。文档的唯一性是由一些字段共同决定的,java多线程判断是否存在和插入时如何保证唯一性
之前也不知道自己有什么好方法,所以自己写了一个方法:我猜如果存在,如果不存在就插入,这个方法是通过syncronized修改的。但我发现这是一种非常低效的做法。
/**
* @param document
*/
synchronized void selectAndInsert(Map<String, Object> document){
//Determine if it exists, insert it if it does not exist
}
我的映射如下:
{"properties":{"pt_number":{ "type":"keyword" }, "pt_name":{"type":"keyword" },"pt_longitude":{ "type":"text"},"pt_latitude":{"type":"text" },"rd_code":{ "type" :"text" }, "rd_name":{ "type":"keyword"}, "area_code":{ "type":"keyword"} ...等等}}
唯一性由 area_code、pt_longitude 和 pt_latitude 决定。插入文档时,我会根据area_code、pt-longitude、pt_latitude判断是否存在,不存在则插入。 java多线程运行时如何保证文档的唯一性?
这个问题困扰了我一段时间。谁能帮帮我,感激不尽
如果您检测到插入,为什么不在插入完成后(和索引刷新...)检查您是否没有重复项。第二种解决方案是使用批量插入更新数据包写入每个 X(= 将新文档存储在共享区域的列表中,这样您就可以检查您的文档是否已经存在,并每 10 秒写入一次此列表例如)。
任何方式都无法仅通过索引中的属性来保证不存在此类文档。即使您检查它在索引中的存在但没有看到它,发出该操作的响应和 ES 接受您的索引请求之间也有一段时间。
所以基本上你只有两种方法:
- 保证索引操作的单次执行(漫长且不那么简单的方法,因为我们没有恰好一次的系统)
- 将文档唯一属性转换为文档 ID,因此即使您的索引操作重叠,它们也只会将相同的值写入同一文档(或者第二个和后面的将失败,具体取决于请求选项)。
后一个很简单,您有一些开箱即用的选项:
- 按照确定的顺序获取所有唯一属性并连接它们的字符串表示(丑陋)
- 按照确定的顺序获取所有唯一属性,连接它们的字节值并使用 Base64 编码(不那么难看)
- 按照确定的顺序获取所有唯一属性,将它们传递给散列函数(md5、sha-X 系列,任何你喜欢的)并使用结果的字符串表示。
常见的情况可能是您以某种方式(例如 kafka)发送了文档,并希望确保没有重复。据我所知,在 ElasticSearch 中没有这样的方法,尽管你可以在这里尝试一个技巧:
- ElasticSearch 允许提供自定义文档 ID
- 文档 ID 限制为 512 字节长度,不能用于正常“处理”
您可能希望根据您的字段(如数据库中的主键)创建一个 ID。如果使用 _create,那么只有当您的文档尚不存在时才会创建它。
还有一些问题有待解决:
如何生成ID?简单的串联是可行的,但前提是您确定总长度不会超过 512B。否则可以使用校验和 - 但冲突的可能性很小。
如果收到几乎相同的文档怎么办(您的密钥相同但存在其他差异)。 Elastic 只允许“替换”或“不替换”。您需要处理其他情况。
我们有elasticsearch的一些文档。文档的唯一性是由一些字段共同决定的,java多线程判断是否存在和插入时如何保证唯一性
之前也不知道自己有什么好方法,所以自己写了一个方法:我猜如果存在,如果不存在就插入,这个方法是通过syncronized修改的。但我发现这是一种非常低效的做法。
/**
* @param document
*/
synchronized void selectAndInsert(Map<String, Object> document){
//Determine if it exists, insert it if it does not exist
}
我的映射如下: {"properties":{"pt_number":{ "type":"keyword" }, "pt_name":{"type":"keyword" },"pt_longitude":{ "type":"text"},"pt_latitude":{"type":"text" },"rd_code":{ "type" :"text" }, "rd_name":{ "type":"keyword"}, "area_code":{ "type":"keyword"} ...等等}}
唯一性由 area_code、pt_longitude 和 pt_latitude 决定。插入文档时,我会根据area_code、pt-longitude、pt_latitude判断是否存在,不存在则插入。 java多线程运行时如何保证文档的唯一性?
这个问题困扰了我一段时间。谁能帮帮我,感激不尽
如果您检测到插入,为什么不在插入完成后(和索引刷新...)检查您是否没有重复项。第二种解决方案是使用批量插入更新数据包写入每个 X(= 将新文档存储在共享区域的列表中,这样您就可以检查您的文档是否已经存在,并每 10 秒写入一次此列表例如)。
任何方式都无法仅通过索引中的属性来保证不存在此类文档。即使您检查它在索引中的存在但没有看到它,发出该操作的响应和 ES 接受您的索引请求之间也有一段时间。
所以基本上你只有两种方法:
- 保证索引操作的单次执行(漫长且不那么简单的方法,因为我们没有恰好一次的系统)
- 将文档唯一属性转换为文档 ID,因此即使您的索引操作重叠,它们也只会将相同的值写入同一文档(或者第二个和后面的将失败,具体取决于请求选项)。
后一个很简单,您有一些开箱即用的选项:
- 按照确定的顺序获取所有唯一属性并连接它们的字符串表示(丑陋)
- 按照确定的顺序获取所有唯一属性,连接它们的字节值并使用 Base64 编码(不那么难看)
- 按照确定的顺序获取所有唯一属性,将它们传递给散列函数(md5、sha-X 系列,任何你喜欢的)并使用结果的字符串表示。
常见的情况可能是您以某种方式(例如 kafka)发送了文档,并希望确保没有重复。据我所知,在 ElasticSearch 中没有这样的方法,尽管你可以在这里尝试一个技巧:
- ElasticSearch 允许提供自定义文档 ID
- 文档 ID 限制为 512 字节长度,不能用于正常“处理”
您可能希望根据您的字段(如数据库中的主键)创建一个 ID。如果使用 _create,那么只有当您的文档尚不存在时才会创建它。
还有一些问题有待解决: 如何生成ID?简单的串联是可行的,但前提是您确定总长度不会超过 512B。否则可以使用校验和 - 但冲突的可能性很小。 如果收到几乎相同的文档怎么办(您的密钥相同但存在其他差异)。 Elastic 只允许“替换”或“不替换”。您需要处理其他情况。