go - 如何在 context.WithDeadline 或简单计时器之间做出决定?

标签 go timer transactions

在 Golang 中,我对传递 contexts意图相当陌生。下游到其他方法和功能。我明白如何 context工作原理,如何使用,如何保持其值,如何与父级相关context以及他们的行为——我只是不明白为什么首先要使用上下文。

在一个更具体的例子中,这是这个问题的实际原因,在我工作的公司中,我们发现了一些非常长时间运行的查询,这些查询经常由于边缘情况而发生。

考虑到我们在投入时间修复根本原因之前的限制,我们决定采取的一个显而易见的解决方案是终止耗时超过 5 分钟的查询。

运行我们交易的方法接受 context最初是在 API 调用中启动的。这context一直传递到交易功能。在那一刻,我找到了 2 种解决方案来终止该查询:

1) 使用新上下文:

  • 启动一个新的 context.WithTimeout(ctx, time.Duration( 5 * time.Minute) )

  • 观看 Done go routine 中的 channel 并在有信号时终止交易

  • 如果交易及时成功完成,只需cancel上下文并按预期提交事务。

2) 使用 Timer :

  • 创建 Timer持续 5 分钟
  • 如果时间到了,杀掉交易
  • 否则,提交事务。

从逻辑上讲,它们是相同的解决方案,但是,何时以及如何决定是否使用context有一个固定的截止日期或一个好的旧Timer

最佳答案

答案在于 context.Context 如何和 time.Timer传递(取消)信号。

context.Context 使您可以通过 Context.Done() 方法访问 channel 当 goroutines 使用它时将关闭应该终止。

time.Timer 使您可以访问 Timer.C 结构字段中的 channel ,在给定的时间后将在该 channel 上发送值时间段(该值将是当前时间,但在这里并不重要)。

此处突出显示了关键点。 channel 关闭可以被任意数量的 goroutine 观察到,并且可以观察到无数次。 Spec: Receive operator:

A receive operation on a closed channel can always proceed immediately, yielding the element type's zero value after any previously sent values have been received.

因此,Context 可用于向任意数量的 goroutine 和位置发出取消信号。 Timer 只能用于向一个目标发出信号,即从其 channel 接收值的目标。如果多个客户端正在收听或尝试从其 channel 接收,则只有一个会幸运地接收到它。

此外,如果您正在使用/使用已经支持/期望context.Context 的代码,那么使用哪一个不是问题。 Go 1.8 还添加了 more context support .已有significant additionsdatabase/sql具有上下文支持的包;包括 DB.BeginTx() :

The provided context is used until the transaction is committed or rolled back. If the context is canceled, the sql package will roll back the transaction. Tx.Commit will return an error if the context provided to BeginTx is canceled.

这是 context.Context 的主要用途:跨 API 边界携带截止日期和信号取消,它以并发安全的方式完成(如 Context值是不可变的, channel 对于并发使用也是安全的,数据竞争不会发生,这是设计使然;更多信息:If I am using channels properly should I need to use mutexes?)。

相关博文:

The Go Blog: Go Concurrency Patterns: Context

Pitfalls of context values and how to avoid or mitigate them in Go

Dave Cheney: Context is for cancelation

关于go - 如何在 context.WithDeadline 或简单计时器之间做出决定?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42359053/

相关文章:

android - 广播接收器android的定时器

ruby-on-rails - 验证 ActiveRecord 事务的存在

go - 在 GORM 中禁用 CreatedAt UpdatedAt DeletedAt 字段

algorithm - 在Go中回溯以找到有向非循环图的所有路径,将路径分配给解决方案 slice 时出现问题(Leetcode 797)

go - 为什么接口(interface)单元会出错

java - Android,java定时器只工作一次

typescript - 如何获取ngx倒计时的 'left'私有(private)属性(property)?

javascript - MongoDB 事务有很多 WriteConflict 错误

methods - 只读方法的EJB 3事务属性

go - golang项目是如何打包部署的?