在 BigTable 数据存储中,关于并发性,我如何“锁定”实体?
Posted
技术标签:
【中文标题】在 BigTable 数据存储中,关于并发性,我如何“锁定”实体?【英文标题】:In a BigTable datastore, with regards to concurrency, how do I "lock" an entity? 【发布时间】:2009-11-26 14:50:20 【问题描述】:我不确定如何在 BigTable 数据存储中处理此问题。
想象一下下面的例子(只是为了解释概念。这个例子与我的实际数据模型不匹配):
我有一个计数器实体来跟踪我的数据存储中的事务数。假设当前的“计数”为 100。 现在两个 Web 请求同时读取此值。 两个 Web 请求都添加了一个新事务 最后两者都将计数器更新为 101。计数器值现在不准确。应该是 102。
关于如何处理这种情况的任何建议?我可以“锁定”计数器以确保在第一个 Web 请求完成之前,第二个 Web 请求甚至不会读取它吗?
【问题讨论】:
【参考方案1】:您有多种选择:
根据您的计数器和实体的范围,让 Transaction 实体成为计数器的子实体。然后,您可以插入事务并更新计数器transactionally。请注意,这会将您的更新速率限制在 1-5 QPS 左右。 如果您的计数不必 100% 准确,请单独插入实体并更新计数器(使用单实体事务)。您可以运行常规 cronjob 来重新计算实体的数量,并在错误导致计数器不同步时修复计数器。 您可以建立自己的limited distributed transaction support。【讨论】:
谢谢尼克。当你说“插入事务”时,你的意思是在 db.run_in_transaction 中执行一个函数吗?当我在我的事务函数中执行“读取”时,如果另一个线程尝试访问现在“过时”的值,它会“锁定”对象并引发错误吗?谢谢,我对 bigTable 处理事务的方式还很陌生 :) 好吧,你称你的实体为“交易”,所以当我说“插入交易”时,我的意思是“插入一个'交易'实体”。事务内部的读取是事务性的,但是,是的 - 只有乐观并发而不是锁。【参考方案2】:除了 Nick 提供的选项之外,您还可以考虑对计数器进行分片。
保留多个计数器,并选择一个进行更新,以使任何两个请求同时选择同一个分片(理想情况下)不可能或(失败)不太可能。
然后你有更多的选择。您可以使用分片作为父级进行事务(与单个计数器相比,这减少了争用),尽管您最终会得到具有任意选择父级的新事务实体。或者不要为交易烦恼,在这种情况下,您可能需要不时修复计数,就像 Nick 的非交易选项一样。
要读取总计数,您需要将所有分片相加。您不会“同时”阅读它们,但这通常没问题。读取任何计数器,它可能会在您读取它和使用该值之间增加,因此该值实际上只是一个下限。添加分片没有什么不同,只是它可能需要更长的时间。
【讨论】:
以上是关于在 BigTable 数据存储中,关于并发性,我如何“锁定”实体?的主要内容,如果未能解决你的问题,请参考以下文章
Janus Graph 后端 cassandra 与 Bigtable