尝试通过前缀删除所有键并重新放入时,在txn请求中给出重复键

时间:2017-11-02 14:56:13

标签: etcd etcd3

尝试使用coreos/jetcd从Java代码更新etcd中的haproxy设置。

我想要实现的目标是:

  1. 删除单个主机的所有端点
  2. 为给定主机添加更新数据
  3. 我想通过前缀删除所有键,并将实际数据作为原子操作放在etcd中。

    这就是我尝试使用etcd交易的原因。我的代码是:

    Op.DeleteOp deleteOp = Op.delete(
            fromString(prefix),
            DeleteOption.newBuilder().withPrefix(fromString(prefix)).build()
    );
    Txn tx = kvClient.txn().Else(deleteOp);
    newKvs.forEach((k,v) -> {
        tx.Else(Op.put(fromString(k), fromString(v), DEFAULT));
    });
    try {
        tx.commit().get();
    } catch (InterruptedException | ExecutionException e) {
        log.error("ETCD transaction failed", e);
        throw new RuntimeException(e);
    }
    

    使用ETCD v3 API(etcd v3.2.9)。 KVstore最初是空的,我想添加3条记录。 prefix值为:

    /proxy-service/hosts/example.com
    

    kvs是地图:

    "/proxy-service/hosts/example.com/FTP/0" -> "localhost:10021"
    "/proxy-service/hosts/example.com/HTTPS/0" -> "localhost:10443"
    "/proxy-service/hosts/example.com/HTTP/0" -> "localhost:10080"
    

    异常发生在commit().get()行,其原因如下:

    Caused by: io.grpc.StatusRuntimeException: INVALID_ARGUMENT: etcdserver: duplicate key given in txn request
        at io.grpc.Status.asRuntimeException(Status.java:526)
        at io.grpc.stub.ClientCalls$UnaryStreamToFuture.onClose(ClientCalls.java:427)
        at io.grpc.ForwardingClientCallListener.onClose(ForwardingClientCallListener.java:41)
        at com.coreos.jetcd.internal.impl.ClientConnectionManager$AuthTokenInterceptor$1$1.onClose(ClientConnectionManager.java:267)
        at io.grpc.internal.ClientCallImpl.closeObserver(ClientCallImpl.java:419)
        at io.grpc.internal.ClientCallImpl.access$100(ClientCallImpl.java:60)
        at io.grpc.internal.ClientCallImpl$ClientStreamListenerImpl.close(ClientCallImpl.java:493)
        at io.grpc.internal.ClientCallImpl$ClientStreamListenerImpl.access$500(ClientCallImpl.java:422)
        at io.grpc.internal.ClientCallImpl$ClientStreamListenerImpl$1StreamClosed.runInContext(ClientCallImpl.java:525)
        at io.grpc.internal.ContextRunnable.run(ContextRunnable.java:37)
        at io.grpc.internal.SerializingExecutor.run(SerializingExecutor.java:102)
        ... 3 more
    

    我做错了什么以及如何以原子操作完成几个etcd更改?

1 个答案:

答案 0 :(得分:0)

看起来,删除密钥然后为同一密钥添加新值的操作不能在同一txn中。根据{{​​3}}:

  

Txn在单个事务中处理多个请求。一个txn请求会增加键值存储的修订版本,并为每个完成的请求生成具有相同修订版本的事件。 不允许在一个txn内多次修改相同的密钥