这种弹性搜索更新会导致原子增量吗?或者它是非原子的?
curl -XPOST 'localhost:9200/test/type1/1/_update' -d '{
"script" : "ctx._source.counter += count",
"params" : {
"count" : 1
}
}'
答案 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;
}