我在我的应用程序中使用了很多(分片)计数器。根据我当前的设计,单个请求可能会导致 100-200 个不同的计数器递增。
因此,对于每个计数器,我都会拾取一个分片,其值会递增。我正在增加事务中的每个分片,这意味着我最终将执行 100-200 个事务作为处理单个请求的一部分。当然,我打算异步执行此操作,以便基本上并行运行所有 100-200 个事务。
由于这个数字感觉相当高,我想知道是否对每个请求或每个实例的并发事务(或数据存储请求)数量有一些限制。我无法从文档中找到这方面的信息。
顺便说一句,出于某种原因,Google 的文档指出“如果您的应用程序具有经常更新的计数器,则不应以事务方式增加它们”[1],但另一方面,他们关于分片计数器的代码示例使用事务来增加分片 [2]。我认为只要使用足够的分片就可以使用交易。我更喜欢交易,因为我希望我的计数器不会错过增量。
最佳答案
以下三个限制可能会给您带来问题:
- 每个实体组每秒 1 次的写入限制
- 每个 XG 5 个实体组
- 每个实例 10 个并发“线程”
最后一项对于您的用例来说是棘手的。
它有点难以找到信息(实际上可能是过时的信息 - 因此值得测试),但每个实例只允许 10 个并发核心线程(无论大小 - F1/F2/F... )。
也就是说,忽略后台线程的创建,如果您假设每个请求都需要一个线程,就像每个 RPC(数据存储、内存缓存、文本搜索等)一样,那么您一次只能使用 10 个线程。如果调度程序认为传入请求将超过 10,它会将请求路由到新实例。
在您想要并行写入 100 个实体的场景中,我希望它只允许大约 10 个并发写入(其余的会阻塞),而且您的实例一次只能服务一个请求。
您的替代方案:
- 使用专用内存缓存 - 您需要将计数器备份到持久存储上,但您可以在后端批量执行此操作。这可能会导致您因刷新而丢失一些数据,无论是否可以,您都必须决定
- 使用 CloudSQL 序列或表 - 如果您不需要大规模, 但确实需要很多计数器,这可能是一个好方法 - 你 可以将计数存储为原始计数或时间序列数据 后处理以实现准确计数
- 使用拉取队列批量更新后端的计数器。您可以在多个柜台上大批量处理许多“事件”。缺点是计数在任何给定时间点都不是最新的
最好的方法可能是混合方法。
例如,接受计数的最终一致性:
- 当请求到来时 - 内存缓存中计数器的原子增量
- 当收到请求时 - 将“事件”任务放入队列
- 从内存缓存提供所需的计数 - 如果不存在,则从数据存储区加载
- 在内存缓存上使用 TTL,以便最终将数据存储区视为“事实来源”
- 运行一个 cron,每 5 分钟(或根据需要)从队列中取出 100 个“事件”任务,并更新数据存储区中事务中所有事件的计数器
更新:我在文档中找到了此部分,talking about controlling max number of concurrent requests ,它模糊地引用了
You may experience increased API latency if this setting is too high.
我想说它值得一玩。
关于java - 每个请求的并发交易是否有限制?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26456058/