在 Berkeley DB JE 中进行比较和交换?

Posted

技术标签:

【中文标题】在 Berkeley DB JE 中进行比较和交换?【英文标题】:Compare and swap in Berkeley DB JE? 【发布时间】:2016-07-11 05:26:24 【问题描述】:

我正在寻找一种在 Berkeley DB 中实现比较和交换操作的有效方法。现在我使用的是非常旧的版本,但乍一看,即使是最新的版本(从 Oracle 网站分发)也没有单一的方法来进行这种操作。

我正在寻找某种方法,例如

replace(Transaction, Key, ExpectedValue, NewValue) 

具有以下语义:DB 获取与给定键关联的值,如果该值存在且等于 ExpectedValue,则该值将更改为 NewValue,否则方法返回不成功的 OperationStatus。

看起来没有这样的方法,所以我想知道这应该如何以最有效的方式完成。

现在我正在使用以下方法:我愿意

db.get(null, key) -> currentValue, version
db.put(null, key, currentValue, newRandomIdVersion) 
db.get(null, key)

我比较值和版本,如果它们匹配,我会进行最终更新擦除旧版本。如果任何步骤失败,则整个过程重新开始。

我觉得这很不理想——我错了吗?

【问题讨论】:

你有没有尝试过? 作为第一次破解,尝试使用事务,看看性能是否足够大规模。 你的意思是仅仅更新交易中的计数器?这无济于事 - 并发事务只会覆盖自己。 好吧,我不确定你所说的覆盖是什么意思——但它们会提供原子性。在发生冲突时,一个事务胜负 N 个事务,由您的应用程序重试。如果您确实需要对同一“记录”进行并发写入,请查看是否可以弄清楚如何将其拆分为多个记录。有了这里的内容,您最好使用环形日志,并在恢复时整理出正确的应用程序级状态。 是的,你是对的,事务是原子的,但同样,如果它们同时开始更新同一个记录,第一个事务可能不会“看到”第二个事务更新记录的结果,反之亦然。同时比较和交换假定不会丢失任何更新。 【参考方案1】:

我对我的问题的更新解决方案是错误的 - 但是只需稍作修改即可使其变得更好。

解决方案可能如下:创建单独的数据库来存储将键关联到某个计数器的锁。该数据库应允许排序重复(以便 Database.get 将返回与给定键关联的最小值)。然后使用共享单调递增计数器。尝试执行 CAS 的多个线程将从该计数器获取值并将键值对存储在该锁定数据库中。存储与键关联的最低值的线程假定它具有写入权限并继续比较并交换所需记录,然后从锁定数据库中删除其条目,其他线程只需重试。

【讨论】:

以上是关于在 Berkeley DB JE 中进行比较和交换?的主要内容,如果未能解决你的问题,请参考以下文章

berkeley-db-je 的最新版本是啥?

Berkeley DB JE JDB 文件不断增加

Berkeley DB 错误:无法锁定 je.lck 文件

使用 berkeley DB 进行数据搜索时出错

Berkeley DB:仅检索密钥

Berkeley DB 文件压缩