如何使用 "pessimistic" Couchbase 锁定与 C API?
How to use "pessimistic" Couchbase locking with the C API?
这真是令人沮丧...我正在使用 Couchbase v3 C API,并且我 运行 遇到了一个可以通过使用他们的“悲观”锁定完美解决的问题。经过大量努力,我相信我终于想出了如何使用它锁定记录(使用 lcb_cmdget_locktime()
,大概需要微秒的参数),但我不知道如何 unlock 完成后记录,而不是让它超时,这是不可接受的解决方案。
文档提供了一个示例,here,但由于某些未知原因,它位于 Javascript 而不是 C (!!!),并且概念未映射到 C API.
有谁知道如何解锁悲观锁,或者有任何示例 C/C++ 使用那个 API 的代码吗?除此之外,有谁知道在哪里可以找到任何使用 C 的非 C API 的源代码,因为我应该能够从那里解决它? (我也找不到其中任何一个,不确定它们是否是开源的。)
谢谢提问
时间以秒为单位,请注意,如果时间大于最大时间(两个持续时间都是可配置的),服务器可能会将时间重置为默认值。以下命令将有助于发现该功能的有效值。
$ cbstats -u Administrator -p password localhost all | grep ep_getl
ep_getl_default_timeout: 15
ep_getl_max_timeout: 30
要锁定密钥,必须使用get操作并使用lcb_cmdget_locktime
设置锁定时间并在成功锁定的情况下捕获CAS值,例如这样
struct my_result {
lcb_STATUS status{LCB_SUCCESS};
uint64_t cas{0};
};
static void get_callback(lcb_INSTANCE *instance, lcb_CALLBACK_TYPE, const lcb_RESPGET *resp)
{
my_result *res = nullptr;
lcb_respget_cookie(resp, (void **)&res);
res->status = lcb_respget_status(resp);
if (res->status == LCB_SUCCESS) {
lcb_respget_cas(resp, &res->cas);
}
}
最好把get with lock代码放到循环中
uint64_t locked_cas{0};
int retries = 3;
while (retries > 0) {
std::string document_id{"foo"};
my_result result{};
lcb_CMDGET* cmd = nullptr;
lcb_cmdget_create(&cmd);
lcb_cmdget_key(cmd, document_id.c_str(), document_id.size());
lcb_cmdget_locktime(cmd, 5);
lcb_get(instance, &result, cmd);
lcb_cmdget_destroy(cmd);
lcb_wait(instance, LCB_WAIT_DEFAULT);
if (result.rc == LCB_SUCCESS) {
locked_cas = result.cas;
break;
} else if (result.rc == LCB_ERR_DOCUMENT_LOCKED || result.rc == LCB_ERR_TEMPORARY_FAILURE) {
std::this_thread::sleep_for(std::chrono::milliseconds(100));
--retries;
continue;
} else {
std::cerr << "Unexpected issue during get with lock: " << lcb_strerror_short(result.rc) << "\n";
break;
}
}
一旦密钥被锁定,可能会执行更新操作,但请记住它必须使用locked_cas
,否则突变操作将失败。
std::string document_id{"foo"};
std::string new_value{"new value"};
lcb_CMDSTORE* cmd = nullptr;
lcb_cmdstore_create(&cmd, LCB_STORE_REPLACE);
lcb_cmdstore_key(cmd, document_id.c_str(), document_id.size());
lcb_cmdstore_value(cmd, new_value.c_str(), new_value.size());
lcb_cmdstore_cas(cmd, locked_cas);
lcb_store(instance, nullptr, cmd);
lcb_cmdstore_destroy(cmd);
lcb_wait(instance, LCB_WAIT_DEFAULT);
要解锁密钥,您还需要 locked_cas
,或者等待服务器自动解锁文档。
std::string document_id{"foo"};
lcb_CMDUNLOCK *cmd = nullptr;
lcb_cmdunlock_create(&cmd);
lcb_cmdunlock_key(cmd, document_id.c_str(), document_id.size());
lcb_cmdunlock_cas(cmd, locked_cas);
lcb_unlock(instance, nullptr, cmd);
lcb_cmdunlock_destroy(cmd);
lcb_wait(instance, LCB_WAIT_DEFAULT);
这真是令人沮丧...我正在使用 Couchbase v3 C API,并且我 运行 遇到了一个可以通过使用他们的“悲观”锁定完美解决的问题。经过大量努力,我相信我终于想出了如何使用它锁定记录(使用 lcb_cmdget_locktime()
,大概需要微秒的参数),但我不知道如何 unlock 完成后记录,而不是让它超时,这是不可接受的解决方案。
文档提供了一个示例,here,但由于某些未知原因,它位于 Javascript 而不是 C (!!!),并且概念未映射到 C API.
有谁知道如何解锁悲观锁,或者有任何示例 C/C++ 使用那个 API 的代码吗?除此之外,有谁知道在哪里可以找到任何使用 C 的非 C API 的源代码,因为我应该能够从那里解决它? (我也找不到其中任何一个,不确定它们是否是开源的。)
谢谢提问
时间以秒为单位,请注意,如果时间大于最大时间(两个持续时间都是可配置的),服务器可能会将时间重置为默认值。以下命令将有助于发现该功能的有效值。
$ cbstats -u Administrator -p password localhost all | grep ep_getl
ep_getl_default_timeout: 15
ep_getl_max_timeout: 30
要锁定密钥,必须使用get操作并使用lcb_cmdget_locktime
设置锁定时间并在成功锁定的情况下捕获CAS值,例如这样
struct my_result {
lcb_STATUS status{LCB_SUCCESS};
uint64_t cas{0};
};
static void get_callback(lcb_INSTANCE *instance, lcb_CALLBACK_TYPE, const lcb_RESPGET *resp)
{
my_result *res = nullptr;
lcb_respget_cookie(resp, (void **)&res);
res->status = lcb_respget_status(resp);
if (res->status == LCB_SUCCESS) {
lcb_respget_cas(resp, &res->cas);
}
}
最好把get with lock代码放到循环中
uint64_t locked_cas{0};
int retries = 3;
while (retries > 0) {
std::string document_id{"foo"};
my_result result{};
lcb_CMDGET* cmd = nullptr;
lcb_cmdget_create(&cmd);
lcb_cmdget_key(cmd, document_id.c_str(), document_id.size());
lcb_cmdget_locktime(cmd, 5);
lcb_get(instance, &result, cmd);
lcb_cmdget_destroy(cmd);
lcb_wait(instance, LCB_WAIT_DEFAULT);
if (result.rc == LCB_SUCCESS) {
locked_cas = result.cas;
break;
} else if (result.rc == LCB_ERR_DOCUMENT_LOCKED || result.rc == LCB_ERR_TEMPORARY_FAILURE) {
std::this_thread::sleep_for(std::chrono::milliseconds(100));
--retries;
continue;
} else {
std::cerr << "Unexpected issue during get with lock: " << lcb_strerror_short(result.rc) << "\n";
break;
}
}
一旦密钥被锁定,可能会执行更新操作,但请记住它必须使用locked_cas
,否则突变操作将失败。
std::string document_id{"foo"};
std::string new_value{"new value"};
lcb_CMDSTORE* cmd = nullptr;
lcb_cmdstore_create(&cmd, LCB_STORE_REPLACE);
lcb_cmdstore_key(cmd, document_id.c_str(), document_id.size());
lcb_cmdstore_value(cmd, new_value.c_str(), new_value.size());
lcb_cmdstore_cas(cmd, locked_cas);
lcb_store(instance, nullptr, cmd);
lcb_cmdstore_destroy(cmd);
lcb_wait(instance, LCB_WAIT_DEFAULT);
要解锁密钥,您还需要 locked_cas
,或者等待服务器自动解锁文档。
std::string document_id{"foo"};
lcb_CMDUNLOCK *cmd = nullptr;
lcb_cmdunlock_create(&cmd);
lcb_cmdunlock_key(cmd, document_id.c_str(), document_id.size());
lcb_cmdunlock_cas(cmd, locked_cas);
lcb_unlock(instance, nullptr, cmd);
lcb_cmdunlock_destroy(cmd);
lcb_wait(instance, LCB_WAIT_DEFAULT);