如何使用弹性搜索更新进行原子增量?

时间:2015-05-29 20:23:43

标签: elasticsearch

这种弹性搜索更新会导致原子增量吗?或者它是非原子的?

curl -XPOST 'localhost:9200/test/type1/1/_update' -d '{
    "script" : "ctx._source.counter += count",
    "params" : {
        "count" : 1
    }
}'

2 个答案:

答案 0 :(得分:6)

我认为建议的更新脚本<​​em>是原子,引用的Optimistic Concurrency Control谈论不是的文档的更新原子(意味着并行更新请求可能会使文档进入“不一致”的非预期状态)。

啊,在阅读了更多关于Partial Updates to Documents的文档之后,我了解到它实际上并不是原子的,但它会检查版本号并在它们不匹配时失败(因此更新不会默默地丢失,因为在CPU上使用非原子增量的情况):

  

为避免丢失数据,更新API将检索当前的_version   检索步骤中的文档,并将其传递给索引   在重新索引步骤期间请求。如果另一个进程改变了   检索和重新索引之间的文档,然后_version数字不会   匹配,更新请求将失败。

然而,有一个简单的解决方法,使其工作原理与原子增量相同:

  

对于部分更新的许多用途,文档都没有关系   被改变了。例如,如果两个进程都递增了   页面查看计数器,它发生的顺序无关紧要;如果一个   发生冲突时,我们唯一需要做的就是重新尝试更新。

     

这可以通过设置retry_on_conflict自动完成   参数指向update之前应重试的次数   失败;它默认为0

答案 1 :(得分:3)

非原子。您需要使用version parameter告诉ES仅在具有特定版本的情况下更新文档:https://www.elastic.co/guide/en/elasticsearch/guide/master/optimistic-concurrency-control.html

例如:// Standard C header needed for string functions #include <string.h> // Defines for line-ending conversion function #define LESTATUS INT #define LE_NO_CHANGES_NEEDED (0) #define LE_CHANGES_SUCCEEDED (1) #define LE_CHANGES_FAILED (-1) /// <summary> /// If the line endings in a block of data loaded from a file contain UNIX (\n) or MAC (\r) line endings, this function replaces it with DOS (\r\n) endings. /// </summary> /// <param name="inData">An array of bytes of input data.</param> /// <param name="inLen">The size, in bytes, of inData.</param> /// <param name="outData">An array of bytes to be populated with output data. This array must already be allocated</param> /// <param name="outLen">The maximum number of bytes that can be stored in outData.</param> /// <param name="bytesWritten">A pointer to an integer that receives the number of bytes written into outData.</param> /// <returns> /// If no changes were necessary (the file already contains \r\n line endings), then the return value is LE_NO_CHANGES_NEEDED.<br/> /// If changes were necessary, and it was possible to store the entire output buffer, the return value is LE_CHANGES_SUCCEEDED.<br/> /// If changes were necessary but the output buffer was too small, the return value is LE_CHANGES_FAILED.<br/> /// </returns> LESTATUS ConvertLineEndings(BYTE* inData, INT inLen, BYTE* outData, INT outLen, INT* bytesWritten) { char *posR = strstr(inData, "\r"); char *posN = strstr(inData, "\n"); // Case 1: the file already contains DOS/Windows line endings. // So, copy the input array into the output array as-is (if we can) // Report an error if the output array is too small to hold the input array; report success otherwise. if (posN != NULL && posR != NULL) { if (outLen >= inLen) { strcpy(outData, inData); return LE_NO_CHANGES_NEEDED; } return LE_CHANGES_FAILED; } // Case 2: the file contains UNIX line endings. else if (posN != NULL && posR == NULL) { int i = 0; int track = 0; for (i = 0; i < inLen; i++) { if (inData[i] != '\n') { outData[track] = inData[i]; track++; if (track>outLen) return LE_CHANGES_FAILED; } else { outData[track] = '\r'; track++; if (track > outLen) return LE_CHANGES_FAILED; outData[track] = '\n'; track++; if (track > outLen) return LE_CHANGES_FAILED; } *bytesWritten = track; } } // Case 3: the file contains Mac-style line endings. else if (posN == NULL && posR != NULL) { int i = 0; int track = 0; for (i = 0; i < inLen; i++) { if (inData[i] != '\r') { outData[track] = inData[i]; track++; if (track>outLen) return LE_CHANGES_FAILED; } else { outData[track] = '\r'; track++; if (track > outLen) return LE_CHANGES_FAILED; outData[track] = '\n'; track++; if (track > outLen) return LE_CHANGES_FAILED; } *bytesWritten = track; } } return LE_CHANGES_SUCCEEDED; }